From 71fb921dbe2a2cc845a4b48f96fb45dcaae6b4fb Mon Sep 17 00:00:00 2001 From: Alexander Kislitsky Date: Tue, 31 Jan 2017 13:08:55 +0300 Subject: [PATCH] Handler for changing notifications statuses added As workaround for decreasing loading in the UI on unread notifications fetching we can mark all notifications as read. For such purposes we add NotificationsMarkAllHandler Change-Id: I2e6a0daaf8712ab3064df728a8fb463ef805aa06 Partial-Bug: #1657348 --- .../nailgun/api/v1/handlers/notifications.py | 26 +++++++++++-- nailgun/nailgun/api/v1/urls.py | 5 +++ .../v1/validators/json_schema/notification.py | 29 +++++++++++++++ .../nailgun/api/v1/validators/notification.py | 12 ++++-- nailgun/nailgun/objects/notification.py | 5 +++ .../test/unit/test_notification_handler.py | 37 +++++++++++++++++++ 6 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 nailgun/nailgun/api/v1/validators/json_schema/notification.py diff --git a/nailgun/nailgun/api/v1/handlers/notifications.py b/nailgun/nailgun/api/v1/handlers/notifications.py index c516b4ea61..e12b6212eb 100644 --- a/nailgun/nailgun/api/v1/handlers/notifications.py +++ b/nailgun/nailgun/api/v1/handlers/notifications.py @@ -19,15 +19,14 @@ Handlers dealing with notifications """ import web +from nailgun.api.v1.handlers.base import BaseHandler from nailgun.api.v1.handlers.base import CollectionHandler -from nailgun.api.v1.handlers.base import SingleHandler - -from nailgun import objects - from nailgun.api.v1.handlers.base import handle_errors from nailgun.api.v1.handlers.base import serialize +from nailgun.api.v1.handlers.base import SingleHandler from nailgun.api.v1.handlers.base import validate from nailgun.api.v1.validators.notification import NotificationValidator +from nailgun import objects class NotificationHandler(SingleHandler): @@ -89,3 +88,22 @@ class NotificationCollectionStatsHandler(CollectionHandler): :http: * 405 (Method not allowed) """ raise self.http(405) + + +class NotificationStatusHandler(BaseHandler): + + validator = NotificationValidator + + @handle_errors + @validate + @serialize + def PUT(self): + """Updates status of all notifications + + :http: * 200 (OK) + * 400 (Invalid data) + """ + web_data = web.data() + data = self.validator.validate_change_status(web_data) + status = data['status'] + objects.NotificationCollection.update_statuses(status) diff --git a/nailgun/nailgun/api/v1/urls.py b/nailgun/nailgun/api/v1/urls.py index 78dbeba013..ee472ac335 100644 --- a/nailgun/nailgun/api/v1/urls.py +++ b/nailgun/nailgun/api/v1/urls.py @@ -88,6 +88,9 @@ from nailgun.api.v1.handlers.plugin_link import PluginLinkHandler from nailgun.api.v1.handlers.notifications import NotificationCollectionHandler from nailgun.api.v1.handlers.notifications import \ NotificationCollectionStatsHandler +from nailgun.api.v1.handlers.notifications import \ + NotificationStatusHandler + from nailgun.api.v1.handlers.notifications import NotificationHandler from nailgun.api.v1.handlers.orchestrator import DefaultDeploymentInfo @@ -336,6 +339,8 @@ urls = ( r'/notifications/?$', NotificationCollectionHandler, + r'/notifications/change_status/?$', + NotificationStatusHandler, r'/notifications/(?P\d+)/?$', NotificationHandler, r'/notifications/stats/?$', diff --git a/nailgun/nailgun/api/v1/validators/json_schema/notification.py b/nailgun/nailgun/api/v1/validators/json_schema/notification.py new file mode 100644 index 0000000000..84f382b030 --- /dev/null +++ b/nailgun/nailgun/api/v1/validators/json_schema/notification.py @@ -0,0 +1,29 @@ +# Copyright 2017 Mirantis, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from nailgun import consts + + +NOTIFICATIONS_CHANGE_STATUS = { + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "required": ["status"], + "properties": { + "status": { + "type": "string", + "enum": list(consts.NOTIFICATION_STATUSES) + }, + + } +} diff --git a/nailgun/nailgun/api/v1/validators/notification.py b/nailgun/nailgun/api/v1/validators/notification.py index 36ca7dbffb..d40594e188 100644 --- a/nailgun/nailgun/api/v1/validators/notification.py +++ b/nailgun/nailgun/api/v1/validators/notification.py @@ -13,11 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -from nailgun import consts -from nailgun import objects - from nailgun.api.v1.validators.base import BasicValidator +from nailgun.api.v1.validators.json_schema import notification +from nailgun import consts from nailgun import errors +from nailgun import objects class NotificationValidator(BasicValidator): @@ -90,3 +90,9 @@ class NotificationValidator(BasicValidator): without any validations. """ pass + + @classmethod + def validate_change_status(cls, data): + parsed = super(NotificationValidator, cls).validate(data) + cls.validate_schema(parsed, notification.NOTIFICATIONS_CHANGE_STATUS) + return parsed diff --git a/nailgun/nailgun/objects/notification.py b/nailgun/nailgun/objects/notification.py index e7d2bb83e2..ec58405cb7 100644 --- a/nailgun/nailgun/objects/notification.py +++ b/nailgun/nailgun/objects/notification.py @@ -109,3 +109,8 @@ class Notification(NailgunObject): class NotificationCollection(NailgunCollection): single = Notification + + @classmethod + def update_statuses(cls, status): + db().query(cls.single.model).update( + {cls.single.model.status: status}, synchronize_session=False) diff --git a/nailgun/nailgun/test/unit/test_notification_handler.py b/nailgun/nailgun/test/unit/test_notification_handler.py index 69fd57ee3a..fa4b277d32 100644 --- a/nailgun/nailgun/test/unit/test_notification_handler.py +++ b/nailgun/nailgun/test/unit/test_notification_handler.py @@ -16,6 +16,7 @@ from oslo_serialization import jsonutils +from nailgun import consts from nailgun.test.base import BaseIntegrationTest from nailgun.utils import reverse @@ -140,3 +141,39 @@ class TestHandlers(BaseIntegrationTest): expect_errors=True ) self.assertEqual(405, resp.status_code) + + def test_notification_status(self): + self.env.create_notification(status=consts.NOTIFICATION_STATUSES.read) + self.env.create_notification( + status=consts.NOTIFICATION_STATUSES.unread) + self.env.create_notification( + status=consts.NOTIFICATION_STATUSES.unread) + + expected_status = consts.NOTIFICATION_STATUSES.unread + resp = self.app.put( + reverse('NotificationStatusHandler'), + params=jsonutils.dumps({'status': expected_status}), + headers=self.default_headers + ) + self.assertEqual(200, resp.status_code) + + # Checking statuses are changed + resp = self.app.get( + reverse('NotificationCollectionHandler'), + headers=self.default_headers + ) + self.assertEqual(200, resp.status_code) + for notif in resp.json_body: + self.assertEqual(expected_status, notif['status']) + + def test_notification_status_not_allowed_methods(self): + methods = ('get', 'post', 'delete', 'patch', 'head') + url = reverse('NotificationStatusHandler') + for m in methods: + method = getattr(self.app, m) + resp = method( + url, + headers=self.default_headers, + expect_errors=True + ) + self.assertEqual(405, resp.status_code)