From 97d644d95d6e99c0beec0a2f573609990ceea473 Mon Sep 17 00:00:00 2001 From: Charlton Austin Date: Tue, 11 Oct 2016 15:09:38 -0400 Subject: [PATCH] Adding in the delete api and the delete and create UI. --- README.md | 2 + data/database.py | 1 + .../c156deb8845d_add_uuid_to_messages.py | 23 +++++ data/model/message.py | 6 ++ endpoints/api/superuser.py | 30 +++++- static/directives/global-message-tab.html | 90 ++++++++++++++++++ static/js/directives/ui/global-message-tab.js | 81 ++++++++++++++++ static/js/pages/superuser.js | 8 +- static/partials/super-user.html | 12 ++- test/data/test.db | Bin 1261568 -> 1265664 bytes test/test_api_security.py | 23 ++++- test/test_api_usage.py | 13 ++- 12 files changed, 277 insertions(+), 12 deletions(-) create mode 100644 data/migrations/versions/c156deb8845d_add_uuid_to_messages.py create mode 100644 static/directives/global-message-tab.html create mode 100644 static/js/directives/ui/global-message-tab.js diff --git a/README.md b/README.md index a66f57ae1..ed57ddb67 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,8 @@ TEST=true python -m test.test_api_usage -f SuiteName PYTHONPATH=. alembic upgrade head # You can also rebuild your local sqlite db image from initdb.py using +# And once you have a migration you should do this and check in the +# changes to share your migration with others. rm test/data/test.db python initdb.py ``` diff --git a/data/database.py b/data/database.py index 47bd79fc2..e3db10efc 100644 --- a/data/database.py +++ b/data/database.py @@ -776,6 +776,7 @@ class LogEntry(BaseModel): class Messages(BaseModel): content = TextField() + uuid = CharField(default=uuid_generator, index=True) class RepositoryActionCount(BaseModel): repository = ForeignKeyField(Repository) diff --git a/data/migrations/versions/c156deb8845d_add_uuid_to_messages.py b/data/migrations/versions/c156deb8845d_add_uuid_to_messages.py new file mode 100644 index 000000000..eae45341c --- /dev/null +++ b/data/migrations/versions/c156deb8845d_add_uuid_to_messages.py @@ -0,0 +1,23 @@ +"""Add uuid to messages + +Revision ID: c156deb8845d +Revises: a3002f7638d5 +Create Date: 2016-10-11 15:44:29.450181 + +""" + +# revision identifiers, used by Alembic. +revision = 'c156deb8845d' +down_revision = 'a3002f7638d5' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + + +def upgrade(tables): + op.add_column('messages', sa.Column('uuid', sa.String(length=36), nullable=True)) + + +def downgrade(tables): + op.drop_column('messages', 'uuid') diff --git a/data/model/message.py b/data/model/message.py index 9fd8d0992..47b92a485 100644 --- a/data/model/message.py +++ b/data/model/message.py @@ -11,3 +11,9 @@ def create(messages): for message in messages: inserted.append(Messages.create(content=message['content'])) return inserted + +def delete_message(uuids): + """Delete message from the database""" + if not uuids: + return + Messages.delete().where(Messages.uuid << uuids).execute() diff --git a/endpoints/api/superuser.py b/endpoints/api/superuser.py index c235d55bf..61de0d036 100644 --- a/endpoints/api/superuser.py +++ b/endpoints/api/superuser.py @@ -820,12 +820,10 @@ class SuperUserServiceKeyApproval(ApiResource): abort(403) - @resource('/v1/messages') @show_if(features.SUPER_USERS) class SuperUserMessages(ApiResource): """ Resource for getting a list of super user messages """ - schemas = { 'GetMessage': { 'id': 'GetMessage', @@ -838,8 +836,8 @@ class SuperUserMessages(ApiResource): 'itemType': { 'type': 'object', 'properties': { - 'id': { - 'type': 'integer', + 'uuid': { + 'type': 'string', 'description': 'The message id', }, 'content': { @@ -877,6 +875,7 @@ class SuperUserMessages(ApiResource): 'messages': [message_view(m) for m in model.message.get_messages()], } + @require_fresh_login @verify_not_prod @nickname('createMessages') @validate_json_request('CreateMessage') @@ -886,8 +885,29 @@ class SuperUserMessages(ApiResource): if SuperUserPermission().can(): model.message.create([request.get_json()['message']]) return make_response('', 201) + + abort(403) + + +@resource('/v1/message/') +@show_if(features.SUPER_USERS) +class SuperUserMessage(ApiResource): + """ Resource for managing individual messages """ + @require_fresh_login + @verify_not_prod + @nickname('deleteGlobalMessage') + @require_scope(scopes.SUPERUSER) + def delete(self, uuid): + """ Delete a message """ + if SuperUserPermission().can(): + model.message.delete_message([uuid]) + return make_response('', 204) + abort(403) def message_view(message): - return {'id': message.id, 'content': message.content} + return { + 'uuid': message.uuid, + 'content': message.content, + } diff --git a/static/directives/global-message-tab.html b/static/directives/global-message-tab.html new file mode 100644 index 000000000..b4adb5a29 --- /dev/null +++ b/static/directives/global-message-tab.html @@ -0,0 +1,90 @@ + +
+
+
+
+ +
+ + + + + + + + + + + +
Message
+ {{ message.content }} + + + + Delete Message + + +
+
+ + + + + + +
\ No newline at end of file diff --git a/static/js/directives/ui/global-message-tab.js b/static/js/directives/ui/global-message-tab.js new file mode 100644 index 000000000..3816bb69c --- /dev/null +++ b/static/js/directives/ui/global-message-tab.js @@ -0,0 +1,81 @@ +/** + * An element for managing global messages. + */ +angular.module('quay').directive('globalMessageTab', function () { + var directiveDefinitionObject = { + priority: 0, + templateUrl: '/static/directives/global-message-tab.html', + replace: false, + transclude: true, + restrict: 'C', + scope: { + 'isEnabled': '=isEnabled' + }, + controller: function ($scope, $element, ApiService) { + $scope.newMessage = {}; + $scope.creatingMessage = false; + + $scope.showCreateMessage = function () { + $scope.createdMessage = null; + $('#createMessageModal').modal('show'); + }; + + $scope.createNewMessage = function () { + $scope.creatingMessage = true; + $scope.createdMessage = null; + + var errorHandler = ApiService.errorDisplay('Cannot create message', function () { + $scope.creatingMessage = false; + $('#createMessageModal').modal('hide'); + }); + + var data = { + message: $scope.newMessage + }; + + ApiService.createMessages(data, null).then(function (resp) { + $scope.creatingMessage = false; + $scope.createdMessage = {content: $scope.newMessage.content}; + $scope.newMessage = {}; + $scope.loadMessageInternal(); + }, errorHandler) + }; + + $scope.showDeleteMessage = function (uuid) { + $scope.messageToDelete = uuid; + $('#confirmDeleteMessageModal').modal({}); + }; + + $scope.deleteMessage = function (uuid) { + $('#confirmDeleteMessageModal').modal('hide'); + ApiService.deleteGlobalMessage(null, {uuid: uuid}).then(function (resp) { + $scope.loadMessageInternal(); + }, ApiService.errorDisplay('Can not delete message')); + }; + + $scope.loadMessageOfTheDay = function () { + if ($scope.messages) { + return; + } + + $scope.loadMessageInternal(); + }; + + $scope.loadMessageInternal = function () { + ApiService.getMessages().then(function (resp) { + $scope.messages = resp['messages']; + }, function (resp) { + $scope.messages = []; + $scope.messagesErrors = ApiService.getErrorMessage(resp); + }); + }; + + $scope.$watch('isEnabled', function (value) { + if (value) { + $scope.loadMessageInternal(); + } + }); + } + }; + return directiveDefinitionObject; +}); diff --git a/static/js/pages/superuser.js b/static/js/pages/superuser.js index f5b6d19a2..50636337b 100644 --- a/static/js/pages/superuser.js +++ b/static/js/pages/superuser.js @@ -31,8 +31,12 @@ $scope.csrf_token = encodeURIComponent(window.__token); $scope.currentConfig = null; $scope.serviceKeysActive = false; + $scope.globalMessagesActive = false; $scope.takeOwnershipInfo = null; + $scope.loadMessageOfTheDay = function () { + $scope.globalMessagesActive = true; + }; $scope.configurationSaved = function(config) { $scope.currentConfig = config; $scope.requiresRestart = true; @@ -69,7 +73,7 @@ var errorHandler = ApiService.errorDisplay('Cannot load system logs. Please contact support.', function() { callback(false); - }) + }); ApiService.getSystemLogs(null, params, /* background */true).then(function(resp) { $scope.debugLogs = resp['logs']; @@ -95,7 +99,7 @@ ApiService.getChangeLog().then(function(resp) { $scope.changeLog = resp; }, ApiService.errorDisplay('Cannot load change log. Please contact support.')) - } + }; $scope.loadUsageLogs = function() { $scope.logsCounter++; diff --git a/static/partials/super-user.html b/static/partials/super-user.html index ab640736b..3b8892468 100644 --- a/static/partials/super-user.html +++ b/static/partials/super-user.html @@ -41,6 +41,10 @@ tab-init="loadConfig()"> +
@@ -50,6 +54,12 @@ configuration-saved="configurationSaved(config)">
+ +
+
+
+ +
@@ -269,7 +279,7 @@
- +