Skip to content
This repository has been archived by the owner on May 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #213 from edx/ihtram/YONK-1523
Browse files Browse the repository at this point in the history
Add API to purge notifications YONK-1523
  • Loading branch information
ihtram committed Jan 2, 2020
2 parents e4157b2 + 3ad4855 commit 174a742
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 18 deletions.
22 changes: 22 additions & 0 deletions edx_notifications/lib/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
All in-proc API endpoints for acting as a Notifications Admin
"""
from edx_notifications.stores.store import notification_store


def purge_user_data(user_ids):
"""
This will purge the notifications and preferences for the given user IDs
:param user_ids: and iterable of user IDs
"""
store = notification_store()
store.purge_notifications_for_users(user_ids)


def purge_notifications_with_payload(payload):
"""
This will purge the notifications and containing the given payload
:payload: string content contained in notifications payload
"""
store = notification_store()
store.purge_notifications_containing(payload)
25 changes: 25 additions & 0 deletions edx_notifications/server/api/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Administration endpoints
"""
from django.http import HttpResponseBadRequest, HttpResponse, HttpResponseForbidden

from edx_notifications.lib.admin import purge_user_data
from edx_notifications.server.api.api_utils import AuthenticatedAPIView


class DeleteUsersData(AuthenticatedAPIView):
"""
POST removes all data for given user IDs
"""

def post(self, request):
"""
HTTP POST Handler
"""
if 'user_ids' not in request.data:
return HttpResponseBadRequest('Missing user ids')
if not request.user.is_staff:
return HttpResponseForbidden()
user_ids = request.data.get('user_ids')
purge_user_data(user_ids)
return HttpResponse(status=204)
51 changes: 51 additions & 0 deletions edx_notifications/server/api/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Tests for the administration endpoints
"""
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.test import TestCase

from edx_notifications.server.api.tests.utils import TestClient


class AdminAPITests(TestCase):
"""
Tests for the admin.py
"""

def setUp(self):
"""
Create clients
"""

self.admin_client = TestClient()
self.admin_user = User(username='admin', is_staff=True)
self.admin_user.save()
self.admin_client.login_user(self.admin_user)

self.client = TestClient()
self.user = User(username='user', is_staff=False)
self.user.save()
self.client.login_user(self.user)

def test_purge_user_data(self):
"""
Make sure purging user data works
"""

response = self.admin_client.post(
reverse('edx_notifications.admin.delete_users_data'),
{'user_ids': [self.admin_user.id]}
)
self.assertEqual(response.status_code, 204)

def test_admin_required_to_purge(self):
"""
Make sure purging is only available to staff users
"""

response = self.client.post(
reverse('edx_notifications.admin.delete_users_data'),
{'user_ids': [self.admin_user.id]}
)
self.assertEqual(response.status_code, 403)
2 changes: 2 additions & 0 deletions edx_notifications/server/api/url_regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
CONSUMER_USER_PREFERENCES_DETAIL_REGEX = r'edx_notifications/v1/consumer/user_preferences/(?P<name>[0-9A-Za-z-]+)$'
CONSUMER_USER_PREFERENCES_DETAIL_NO_PARAM_REGEX = r'edx_notifications/v1/consumer/user_preferences/$'
CONSUMER_RENDERERS_TEMPLATES_REGEX = r'edx_notifications/v1/consumer/renderers/templates$'

ADMIN_USERS_DELETE = r'edx_notifications/v1/admin/user/delete$'
11 changes: 8 additions & 3 deletions edx_notifications/server/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns

from edx_notifications.server.api import consumer as consumer_views

from edx_notifications.server.api import consumer as consumer_views, admin as admin_views
from .url_regex import (
CONSUMER_NOTIFICATIONS_REGEX,
CONSUMER_USER_PREFERENCES_REGEX,
Expand All @@ -18,7 +17,8 @@
CONSUMER_NOTIFICATIONS_PREFERENCES_REGEX,
CONSUMER_NOTIFICATION_DETAIL_NO_PARAM_REGEX,
CONSUMER_NOTIFICATIONS_MARK_NOTIFICATIONS_REGEX,
CONSUMER_USER_PREFERENCES_DETAIL_NO_PARAM_REGEX
CONSUMER_USER_PREFERENCES_DETAIL_NO_PARAM_REGEX,
ADMIN_USERS_DELETE
)

urlpatterns = [ # pylint: disable=invalid-name
Expand Down Expand Up @@ -72,6 +72,11 @@
consumer_views.UserPreferenceDetail.as_view(),
name='edx_notifications.consumer.user_preferences.detail.no_param'
),
url(
ADMIN_USERS_DELETE,
admin_views.DeleteUsersData.as_view(),
name='edx_notifications.admin.delete_users_data'
),

]

Expand Down
8 changes: 7 additions & 1 deletion edx_notifications/server/api/urls_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
CONSUMER_NOTIFICATIONS_PREFERENCES_REGEX,
CONSUMER_NOTIFICATION_DETAIL_NO_PARAM_REGEX,
CONSUMER_NOTIFICATIONS_MARK_NOTIFICATIONS_REGEX,
CONSUMER_USER_PREFERENCES_DETAIL_NO_PARAM_REGEX
CONSUMER_USER_PREFERENCES_DETAIL_NO_PARAM_REGEX,
ADMIN_USERS_DELETE
)


Expand Down Expand Up @@ -80,4 +81,9 @@ def mock_handler(request): # pylint: disable=unused-argument
mock_handler,
name='edx_notifications.consumer.user_preferences.detail.no_param'
),
url(
ADMIN_USERS_DELETE,
mock_handler,
name='edx_notifications.admin.delete_user_notifications'
),
]
20 changes: 19 additions & 1 deletion edx_notifications/stores/sql/store_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
SQLNotificationMessage,
SQLNotificationPreference,
SQLNotificationCallbackTimer,
SQLUserNotificationPreferences
SQLUserNotificationPreferences,
SQLUserNotificationArchive
)


Expand Down Expand Up @@ -556,3 +557,20 @@ def get_all_namespaces(self, start_datetime=None, end_datetime=None):
result_set = result_set.values_list('namespace', flat=True).order_by('namespace').distinct()

return result_set

def purge_notifications_for_users(self, user_ids):
"""
This will remove all notifications and preferences for given user IDs
"""
user_notifications = SQLUserNotification.objects.filter(user_id__in=user_ids)
archived_notifications = SQLUserNotificationArchive.objects.filter(user_id__in=user_ids)
SQLNotificationMessage.objects.filter(id__in=user_notifications.values('msg_id')).delete()
SQLNotificationMessage.objects.filter(id__in=archived_notifications.values('msg_id')).delete()
SQLUserNotificationArchive.objects.filter(user_id__in=user_ids).delete()
SQLUserNotificationPreferences.objects.filter(user_id__in=user_ids).delete()

def purge_notifications_containing(self, payload):
"""
This will remove all notifications which contains the given payload
"""
SQLNotificationMessage.objects.filter(payload__contains=payload).delete()
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
"url": "git://github.com/edx/edx-notifications"
},
"devDependencies": {
"gulp": "latest",
"gulp-karma": "latest",
"gulp": "4.0.2",
"gulp-karma": "0.0.5",
"karma": ">=0.10 <=0.13",
"karma-chrome-launcher": "latest",
"karma-coverage": "latest",
"karma-firefox-launcher": "latest",
"jasmine-core": "latest",
"karma-jasmine": "latest",
"karma-jasmine-jquery": "latest",
"karma-phantomjs-launcher": "latest",
"sinon": "latest",
"karma-sinon": "latest",
"karma-spec-reporter": "latest"
"karma-chrome-launcher": "3.1.0",
"karma-coverage": "2.0.1",
"karma-firefox-launcher": "1.2.0",
"jasmine-core": "3.5.0",
"karma-jasmine": "2.0.1",
"karma-jasmine-jquery": "0.1.1",
"karma-phantomjs-launcher": "1.0.4",
"sinon": "<8.0.0",
"karma-sinon": "1.0.5",
"karma-spec-reporter": "0.0.32"
}
}
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def load_requirements(*requirements_paths):

setup(
name='edx-notifications',
version='1.0.2',
version='0.9.0',
description='Notification subsystem for Open edX',
long_description=open('README.md').read(),
author='edX',
Expand Down

0 comments on commit 174a742

Please sign in to comment.