diff --git a/lemur/authorities/schemas.py b/lemur/authorities/schemas.py index 3012d9b2..773778fb 100644 --- a/lemur/authorities/schemas.py +++ b/lemur/authorities/schemas.py @@ -11,7 +11,7 @@ from marshmallow import fields, validates_schema from marshmallow import validate from marshmallow.exceptions import ValidationError -from lemur.schemas import PluginSchema, ExtensionSchema, AssociatedAuthoritySchema, AssociatedRoleSchema +from lemur.schemas import PluginInputSchema, ExtensionSchema, AssociatedAuthoritySchema, AssociatedRoleSchema from lemur.common.schema import LemurInputSchema, LemurOutputSchema from lemur.common import validators @@ -33,7 +33,7 @@ class AuthorityInputSchema(LemurInputSchema): country = fields.String(missing=lambda: current_app.config.get('LEMUR_DEFAULT_COUNTRY')) state = fields.String(missing=lambda: current_app.config.get('LEMUR_DEFAULT_STATE')) - plugin = fields.Nested(PluginSchema) + plugin = fields.Nested(PluginInputSchema) # signing related options type = fields.String(validate=validate.OneOf(['root', 'subca']), missing='root') diff --git a/lemur/certificates/schemas.py b/lemur/certificates/schemas.py index 6bdf03e4..711fc9d9 100644 --- a/lemur/certificates/schemas.py +++ b/lemur/certificates/schemas.py @@ -11,7 +11,7 @@ from marshmallow import fields, validates_schema from marshmallow.exceptions import ValidationError from lemur.schemas import AssociatedAuthoritySchema, AssociatedDestinationSchema, AssociatedCertificateSchema, \ - AssociatedNotificationSchema, PluginSchema, ExtensionSchema + AssociatedNotificationSchema, PluginInputSchema, ExtensionSchema from lemur.common.schema import LemurInputSchema, LemurOutputSchema from lemur.common import validators @@ -89,7 +89,7 @@ class CertificateUploadInputSchema(LemurInputSchema): class CertificateExportInputSchema(LemurInputSchema): - export = fields.Nested(PluginSchema) + export = fields.Nested(PluginInputSchema) certificate_input_schema = CertificateInputSchema() diff --git a/lemur/destinations/schemas.py b/lemur/destinations/schemas.py index 0ee49693..2545bf71 100644 --- a/lemur/destinations/schemas.py +++ b/lemur/destinations/schemas.py @@ -6,22 +6,31 @@ .. moduleauthor:: Kevin Glisson """ -from marshmallow import fields +from marshmallow import fields, post_dump from lemur.common.schema import LemurInputSchema, LemurOutputSchema -from lemur.schemas import PluginSchema +from lemur.schemas import PluginInputSchema, PluginOutputSchema class DestinationInputSchema(LemurInputSchema): + id = fields.Integer() label = fields.String(required=True) - options = fields.Dict(required=True) - description = fields.String() - plugin = fields.Nested(PluginSchema, required=True) + description = fields.String(required=True) + active = fields.Boolean() + plugin = fields.Nested(PluginInputSchema, required=True) class DestinationOutputSchema(LemurOutputSchema): + id = fields.Integer() label = fields.String() - options = fields.Dict(dump_to='destination_options') description = fields.String() + active = fields.Boolean() + plugin = fields.Nested(PluginOutputSchema) + options = fields.List(fields.Dict()) + + @post_dump + def fill_object(self, data): + data['plugin']['pluginOptions'] = data['options'] + return data destination_input_schema = DestinationInputSchema() diff --git a/lemur/destinations/views.py b/lemur/destinations/views.py index f27d435e..f975a2d5 100644 --- a/lemur/destinations/views.py +++ b/lemur/destinations/views.py @@ -148,7 +148,7 @@ class DestinationsList(AuthenticatedResource): :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error """ - return service.create(data['label'], data['plugin']['slug'], data['plugin']['pluginOptions'], data['description']) + return service.create(data['label'], data['plugin']['slug'], data['plugin']['plugin_options'], data['description']) class Destinations(AuthenticatedResource): @@ -265,7 +265,7 @@ class Destinations(AuthenticatedResource): :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error """ - return service.update(destination_id, data['label'], data['plugin']['pluginOptions'], data['description']) + return service.update(destination_id, data['label'], data['plugin']['plugin_options'], data['description']) @admin_permission.require(http_exception=403) def delete(self, destination_id): diff --git a/lemur/notifications/schemas.py b/lemur/notifications/schemas.py index df6d961a..b1510cd6 100644 --- a/lemur/notifications/schemas.py +++ b/lemur/notifications/schemas.py @@ -5,28 +5,33 @@ :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ -from marshmallow import fields +from marshmallow import fields, post_dump from lemur.common.schema import LemurInputSchema, LemurOutputSchema -from lemur.schemas import PluginSchema, AssociatedCertificateSchema +from lemur.schemas import PluginInputSchema, PluginOutputSchema, AssociatedCertificateSchema class NotificationInputSchema(LemurInputSchema): + id = fields.Integer() label = fields.String(required=True) - options = fields.Dict(required=True) description = fields.String() active = fields.Boolean() - plugin = fields.Nested(PluginSchema, required=True) - certificates = fields.Nested(AssociatedCertificateSchema, many=True) + plugin = fields.Nested(PluginInputSchema, required=True) + certificates = fields.Nested(AssociatedCertificateSchema, many=True, missing=[]) class NotificationOutputSchema(LemurOutputSchema): id = fields.Integer() label = fields.String() description = fields.String() - options = fields.Dict(dump_to='notification_options') active = fields.Boolean() - plugin = fields.Nested(PluginSchema) - certificates = fields.Nested(AssociatedCertificateSchema, many=True) + options = fields.List(fields.Dict()) + plugin = fields.Nested(PluginOutputSchema) + certificates = fields.Nested(AssociatedCertificateSchema, many=True, missing=[]) + + @post_dump + def fill_object(self, data): + data['plugin']['pluginOptions'] = data['options'] + return data notification_input_schema = NotificationInputSchema() diff --git a/lemur/notifications/views.py b/lemur/notifications/views.py index c8960238..9d7d411d 100644 --- a/lemur/notifications/views.py +++ b/lemur/notifications/views.py @@ -217,7 +217,7 @@ class NotificationsList(AuthenticatedResource): return service.create( data['label'], data['plugin']['slug'], - data['plugin']['pluginOptions'], + data['plugin']['plugin_options'], data['description'], data['certificates'] ) diff --git a/lemur/plugins/bases/notification.py b/lemur/plugins/bases/notification.py index 36e94ef3..410e65ec 100644 --- a/lemur/plugins/bases/notification.py +++ b/lemur/plugins/bases/notification.py @@ -45,7 +45,7 @@ class ExpirationNotificationPlugin(NotificationPlugin): ] @property - def options(self): + def plugin_options(self): return list(self.default_options) + self.additional_options def send(self): diff --git a/lemur/roles/schemas.py b/lemur/roles/schemas.py index fd8d919e..eb204f38 100644 --- a/lemur/roles/schemas.py +++ b/lemur/roles/schemas.py @@ -11,6 +11,7 @@ from lemur.schemas import AssociatedUserSchema, AssociatedAuthoritySchema class RoleInputSchema(LemurInputSchema): + id = fields.Integer() name = fields.String(required=True) username = fields.String() password = fields.String() @@ -20,6 +21,7 @@ class RoleInputSchema(LemurInputSchema): class RoleOutputSchema(LemurOutputSchema): + id = fields.Integer() name = fields.String() username = fields.String() password = fields.String() diff --git a/lemur/roles/service.py b/lemur/roles/service.py index 151167e6..e4d4b394 100644 --- a/lemur/roles/service.py +++ b/lemur/roles/service.py @@ -113,4 +113,4 @@ def render(args): terms = filt.split(';') query = database.filter(query, Role, terms) - database.sort_and_page(query, Role, args) + return database.sort_and_page(query, Role, args) diff --git a/lemur/schemas.py b/lemur/schemas.py index 0e5e5aeb..d7dba5b4 100644 --- a/lemur/schemas.py +++ b/lemur/schemas.py @@ -17,7 +17,7 @@ from lemur.notifications.models import Notification from lemur.users.models import User from lemur.common import validators -from lemur.common.schema import LemurSchema, LemurInputSchema +from lemur.common.schema import LemurSchema, LemurInputSchema, LemurOutputSchema from lemur.plugins import plugins @@ -96,18 +96,26 @@ class AssociatedUserSchema(LemurInputSchema): return User.query.filter(User.id == data['id']).one() -class PluginSchema(LemurInputSchema): - plugin_options = fields.Dict() - slug = fields.String() +class PluginInputSchema(LemurInputSchema): + plugin_options = fields.List(fields.Dict()) + slug = fields.String(required=True) title = fields.String() description = fields.String() @post_load def get_object(self, data, many=False): - if many: - return [plugins.get(plugin['slug']) for plugin in data] - else: - return plugins.get(data['slug']) + data['plugin_object'] = plugins.get(data['slug']) + return data + + +class PluginOutputSchema(LemurOutputSchema): + id = fields.Integer() + label = fields.String() + description = fields.String() + active = fields.Boolean() + plugin_options = fields.List(fields.Dict()) + slug = fields.String() + title = fields.String() class BaseExtensionSchema(LemurSchema): diff --git a/lemur/sources/schemas.py b/lemur/sources/schemas.py index 9309bccb..34dbf119 100644 --- a/lemur/sources/schemas.py +++ b/lemur/sources/schemas.py @@ -5,27 +5,32 @@ :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ -from marshmallow import fields +from marshmallow import fields, post_dump -from lemur.schemas import PluginSchema +from lemur.schemas import PluginInputSchema, PluginOutputSchema from lemur.common.schema import LemurInputSchema, LemurOutputSchema class SourceInputSchema(LemurInputSchema): + id = fields.Integer() label = fields.String(required=True) - options = fields.Dict(load_from='sourceOptions', required=True) description = fields.String() - plugin = fields.Nested(PluginSchema) + plugin = fields.Nested(PluginInputSchema) active = fields.Boolean() class SourceOutputSchema(LemurOutputSchema): + id = fields.Integer() label = fields.String() - options = fields.Dict(dump_to='sourceOptions') description = fields.String() - plugin = fields.Nested(PluginSchema) + plugin = fields.Nested(PluginOutputSchema) + options = fields.List(fields.Dict()) fields.Boolean() + @post_dump + def fill_object(self, data): + data['plugin']['pluginOptions'] = data['options'] + return data source_input_schema = SourceInputSchema() sources_output_schema = SourceOutputSchema(many=True) diff --git a/lemur/sources/views.py b/lemur/sources/views.py index 6cdcef72..94acef6a 100644 --- a/lemur/sources/views.py +++ b/lemur/sources/views.py @@ -151,7 +151,7 @@ class SourcesList(AuthenticatedResource): :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error """ - return service.create(data['label'], data['plugin']['slug'], data['plugin']['pluginOptions'], data['description']) + return service.create(data['label'], data['plugin']['slug'], data['plugin']['plugin_options'], data['description']) class Sources(AuthenticatedResource): @@ -271,7 +271,7 @@ class Sources(AuthenticatedResource): :reqheader Authorization: OAuth token to authenticate :statuscode 200: no error """ - return service.update(source_id, data['label'], data['plugin']['pluginOptions'], data['description']) + return service.update(source_id, data['label'], data['plugin']['plugin_options'], data['description']) @admin_permission.require(http_exception=403) def delete(self, source_id): diff --git a/lemur/static/app/angular/destinations/destination/destination.js b/lemur/static/app/angular/destinations/destination/destination.js index 2681a154..5b35d515 100644 --- a/lemur/static/app/angular/destinations/destination/destination.js +++ b/lemur/static/app/angular/destinations/destination/destination.js @@ -2,7 +2,7 @@ angular.module('lemur') - .controller('DestinationsCreateController', function ($scope, $modalInstance, PluginService, DestinationService, LemurRestangular){ + .controller('DestinationsCreateController', function ($scope, $uibModalInstance, PluginService, DestinationService, LemurRestangular, toaster){ $scope.destination = LemurRestangular.restangularizeElement(null, {}, 'destinations'); PluginService.getByType('destination').then(function (plugins) { @@ -10,24 +10,38 @@ angular.module('lemur') }); $scope.save = function (destination) { - DestinationService.create(destination).then(function () { - $modalInstance.close(); + DestinationService.create(destination).then( + function () { + toaster.pop({ + type: 'success', + title: destination.label, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: destination.label, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); }); }; $scope.cancel = function () { - $modalInstance.dismiss('cancel'); + $uibModalInstance.dismiss('cancel'); }; }) - .controller('DestinationsEditController', function ($scope, $modalInstance, DestinationService, DestinationApi, PluginService, editId) { + .controller('DestinationsEditController', function ($scope, $uibModalInstance, DestinationService, DestinationApi, PluginService, toaster, editId) { DestinationApi.get(editId).then(function (destination) { $scope.destination = destination; PluginService.getByType('destination').then(function (plugins) { $scope.plugins = plugins; _.each($scope.plugins, function (plugin) { if (plugin.slug === $scope.destination.pluginName) { - plugin.pluginOptions = $scope.destination.destinationOptions; $scope.destination.plugin = plugin; } }); @@ -35,12 +49,27 @@ angular.module('lemur') }); $scope.save = function (destination) { - DestinationService.update(destination).then(function () { - $modalInstance.close(); - }); + DestinationService.update(destination).then( + function () { + toaster.pop({ + type: 'success', + title: destination.label, + body: 'Successfully Updated!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: destination.label, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { - $modalInstance.dismiss('cancel'); + $uibModalInstance.dismiss('cancel'); }; }); diff --git a/lemur/static/app/angular/destinations/services.js b/lemur/static/app/angular/destinations/services.js index e778a1f3..24b821ac 100644 --- a/lemur/static/app/angular/destinations/services.js +++ b/lemur/static/app/angular/destinations/services.js @@ -3,7 +3,7 @@ angular.module('lemur') .service('DestinationApi', function (LemurRestangular) { return LemurRestangular.all('destinations'); }) - .service('DestinationService', function ($location, DestinationApi, PluginService, toaster) { + .service('DestinationService', function ($location, DestinationApi, PluginService) { var DestinationService = this; DestinationService.findDestinationsByName = function (filterValue) { return DestinationApi.getList({'filter[label]': filterValue}) @@ -13,41 +13,11 @@ angular.module('lemur') }; DestinationService.create = function (destination) { - return DestinationApi.post(destination).then( - function () { - toaster.pop({ - type: 'success', - title: destination.label, - body: 'Successfully created!' - }); - $location.path('destinations'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: destination.label, - body: 'Was not created! ' + response.data.message - }); - }); + return DestinationApi.post(destination); }; DestinationService.update = function (destination) { - return destination.put().then( - function () { - toaster.pop({ - type: 'success', - title: destination.label, - body: 'Successfully updated!' - }); - $location.path('destinations'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: destination.label, - body: 'Was not updated! ' + response.data.message - }); - }); + return destination.put(); }; DestinationService.getPlugin = function (destination) { diff --git a/lemur/static/app/angular/destinations/view/view.js b/lemur/static/app/angular/destinations/view/view.js index cc766ff5..943ff9d1 100644 --- a/lemur/static/app/angular/destinations/view/view.js +++ b/lemur/static/app/angular/destinations/view/view.js @@ -10,7 +10,7 @@ angular.module('lemur') }); }) - .controller('DestinationsViewController', function ($scope, $modal, DestinationApi, DestinationService, ngTableParams, toaster) { + .controller('DestinationsViewController', function ($scope, $uibModal, DestinationApi, DestinationService, ngTableParams, toaster) { $scope.filter = {}; $scope.destinationsTable = new ngTableParams({ page: 1, // show first page @@ -24,9 +24,6 @@ angular.module('lemur') getData: function ($defer, params) { DestinationApi.getList(params.url()).then( function (data) { - _.each(data, function (destination) { - DestinationService.getPlugin(destination); - }); params.total(data.total); $defer.resolve(data); } @@ -50,7 +47,7 @@ angular.module('lemur') }; $scope.edit = function (destinationId) { - var modalInstance = $modal.open({ + var uibModalInstance = $uibModal.open({ animation: true, templateUrl: '/angular/destinations/destination/destination.tpl.html', controller: 'DestinationsEditController', @@ -63,14 +60,14 @@ angular.module('lemur') } }); - modalInstance.result.then(function () { + uibModalInstance.result.then(function () { $scope.destinationsTable.reload(); }); }; $scope.create = function () { - var modalInstance = $modal.open({ + var uibModalInstance = $uibModal.open({ animation: true, controller: 'DestinationsCreateController', templateUrl: '/angular/destinations/destination/destination.tpl.html', @@ -78,7 +75,7 @@ angular.module('lemur') backdrop: 'static' }); - modalInstance.result.then(function () { + uibModalInstance.result.then(function () { $scope.destinationsTable.reload(); }); diff --git a/lemur/static/app/angular/domains/domain/domain.js b/lemur/static/app/angular/domains/domain/domain.js index 45a35bc4..a1ed14d3 100644 --- a/lemur/static/app/angular/domains/domain/domain.js +++ b/lemur/static/app/angular/domains/domain/domain.js @@ -2,13 +2,28 @@ angular.module('lemur') - .controller('DomainsCreateController', function ($scope, $uibModalInstance, PluginService, DomainService, LemurRestangular){ + .controller('DomainsCreateController', function ($scope, $uibModalInstance, PluginService, DomainService, LemurRestangular, toaster){ $scope.domain = LemurRestangular.restangularizeElement(null, {}, 'domains'); $scope.save = function (domain) { - DomainService.create(domain).then(function () { - $uibModalInstance.close(); - }); + DomainService.create(domain).then( + function () { + toaster.pop({ + type: 'success', + title: domain, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: domain, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { @@ -16,15 +31,30 @@ angular.module('lemur') }; }) - .controller('DomainsEditController', function ($scope, $uibModalInstance, DomainService, DomainApi, editId) { + .controller('DomainsEditController', function ($scope, $uibModalInstance, DomainService, DomainApi, toaster, editId) { DomainApi.get(editId).then(function (domain) { $scope.domain = domain; }); $scope.save = function (domain) { - DomainService.update(domain).then(function () { - $uibModalInstance.close(); - }); + DomainService.update(domain).then( + function () { + toaster.pop({ + type: 'success', + title: domain, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: domain, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { diff --git a/lemur/static/app/angular/notifications/notification/notification.js b/lemur/static/app/angular/notifications/notification/notification.js index 5677a4ba..5eb673e2 100644 --- a/lemur/static/app/angular/notifications/notification/notification.js +++ b/lemur/static/app/angular/notifications/notification/notification.js @@ -2,7 +2,7 @@ angular.module('lemur') - .controller('NotificationsCreateController', function ($scope, $uibModalInstance, PluginService, NotificationService, CertificateService, LemurRestangular){ + .controller('NotificationsCreateController', function ($scope, $uibModalInstance, PluginService, NotificationService, CertificateService, LemurRestangular, toaster){ $scope.notification = LemurRestangular.restangularizeElement(null, {}, 'notifications'); PluginService.getByType('notification').then(function (plugins) { @@ -11,12 +11,22 @@ angular.module('lemur') $scope.save = function (notification) { NotificationService.create(notification).then( function () { + toaster.pop({ + type: 'success', + title: notification.label, + body: 'Successfully Created!' + }); $uibModalInstance.close(); - }, - function () { - - } - ); + }, function (response) { + toaster.pop({ + type: 'error', + title: notification.label, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { @@ -26,7 +36,7 @@ angular.module('lemur') $scope.certificateService = CertificateService; }) - .controller('NotificationsEditController', function ($scope, $uibModalInstance, NotificationService, NotificationApi, PluginService, CertificateService, editId) { + .controller('NotificationsEditController', function ($scope, $uibModalInstance, NotificationService, NotificationApi, PluginService, CertificateService, toaster, editId) { NotificationApi.get(editId).then(function (notification) { $scope.notification = notification; PluginService.getByType('notification').then(function (plugins) { @@ -52,9 +62,24 @@ angular.module('lemur') }); $scope.save = function (notification) { - NotificationService.update(notification).then(function () { - $uibModalInstance.close(); - }); + NotificationService.update(notification).then( + function () { + toaster.pop({ + type: 'success', + title: notification.label, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: notification.label, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { diff --git a/lemur/static/app/angular/notifications/services.js b/lemur/static/app/angular/notifications/services.js index 16196c5d..02443701 100644 --- a/lemur/static/app/angular/notifications/services.js +++ b/lemur/static/app/angular/notifications/services.js @@ -17,7 +17,7 @@ angular.module('lemur') }); return LemurRestangular.all('notifications'); }) - .service('NotificationService', function ($location, NotificationApi, PluginService, toaster) { + .service('NotificationService', function ($location, NotificationApi, PluginService) { var NotificationService = this; NotificationService.findNotificationsByName = function (filterValue) { return NotificationApi.getList({'filter[label]': filterValue}) @@ -48,59 +48,15 @@ angular.module('lemur') }; NotificationService.create = function (notification) { - return NotificationApi.post(notification).then( - function () { - toaster.pop({ - type: 'success', - title: notification.label, - body: 'Successfully created!' - }); - $location.path('notifications'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: notification.label, - body: 'Was not created! ' + response.data.message - }); - }); + return NotificationApi.post(notification); }; NotificationService.update = function (notification) { - return notification.put().then( - function () { - toaster.pop({ - type: 'success', - title: notification.label, - body: 'Successfully updated!' - }); - $location.path('notifications'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: notification.label, - body: 'Was not updated! ' + response.data.message - }); - }); + return notification.put(); }; NotificationService.updateActive = function (notification) { - notification.put().then( - function () { - toaster.pop({ - type: 'success', - title: notification.name, - body: 'Successfully updated!' - }); - }, - function (response) { - toaster.pop({ - type: 'error', - title: notification.name, - body: 'Was not updated! ' + response.data.message - }); - }); + notification.put(); }; return NotificationService; }); diff --git a/lemur/static/app/angular/roles/role/role.js b/lemur/static/app/angular/roles/role/role.js index 142db20d..1b4b2476 100644 --- a/lemur/static/app/angular/roles/role/role.js +++ b/lemur/static/app/angular/roles/role/role.js @@ -2,15 +2,30 @@ angular.module('lemur') - .controller('RolesEditController', function ($scope, $uibModalInstance, RoleApi, RoleService, UserService, editId) { + .controller('RolesEditController', function ($scope, $uibModalInstance, RoleApi, RoleService, UserService, toaster, editId) { RoleApi.get(editId).then(function (role) { $scope.role = role; RoleService.getUsers(role); }); $scope.save = function (role) { - RoleService.update(role).then(function () { - $uibModalInstance.close(); + RoleService.update(role).then( + function () { + toaster.pop({ + type: 'success', + title: role.name, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: role.name, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); }); }; @@ -28,14 +43,29 @@ angular.module('lemur') $scope.roleService = RoleService; }) - .controller('RolesCreateController', function ($scope,$uibModalInstance, RoleApi, RoleService, UserService, LemurRestangular) { + .controller('RolesCreateController', function ($scope,$uibModalInstance, RoleApi, RoleService, UserService, LemurRestangular, toaster) { $scope.role = LemurRestangular.restangularizeElement(null, {}, 'roles'); $scope.userService = UserService; $scope.save = function (role) { - RoleService.create(role).then(function () { - $uibModalInstance.close(); - }); + RoleService.create(role).then( + function () { + toaster.pop({ + type: 'success', + title: role.name, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: role.name, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { diff --git a/lemur/static/app/angular/roles/services.js b/lemur/static/app/angular/roles/services.js index 4c68c95d..6735a5ad 100644 --- a/lemur/static/app/angular/roles/services.js +++ b/lemur/static/app/angular/roles/services.js @@ -18,7 +18,7 @@ angular.module('lemur') }); return LemurRestangular.all('roles'); }) - .service('RoleService', function ($location, RoleApi, toaster) { + .service('RoleService', function ($location, RoleApi) { var RoleService = this; RoleService.findRoleByName = function (filterValue) { return RoleApi.getList({'filter[name]': filterValue}) @@ -48,80 +48,18 @@ angular.module('lemur') }; RoleService.create = function (role) { - return RoleApi.post(role).then( - function () { - toaster.pop({ - type: 'success', - title: role.name, - body: 'Has been successfully created!' - }); - }, - function (response) { - toaster.pop({ - type: 'error', - title: role.name, - body: 'Has not been created! ' + response.data.message - }); - }); + return RoleApi.post(role); }; RoleService.update = function (role) { - return role.put().then( - function () { - toaster.pop({ - type: 'success', - title: role.name, - body: 'Successfully updated!' - }); - }, - function (response) { - toaster.pop({ - type: 'error', - title: role.name, - body: 'Was not updated!' + response.data.message - }); - }); + return role.put(); }; RoleService.remove = function (role) { - return role.remove().then( - function () { - toaster.pop({ - type: 'success', - title: role.name, - body: 'Successfully deleted!' - }); - }, - function (response) { - toaster.pop({ - type: 'error', - title: role.name, - body: 'Was not deleted!' + response.data.message - }); - } - ); + return role.remove(); }; RoleService.loadPassword = function (role) { - return role.customGET('credentials').then( - function (response) { - if ( response.password === null) { - toaster.pop({ - type: 'info', - title: role.name, - body: 'Has no password associated' - }); - } else { - role.password = response.password; - role.username = response.username; - } - }, - function () { - toaster.pop({ - type: 'error', - title: role.name, - body: 'You do not have permission to view this password!' - }); - }); + return role.customGET('credentials'); }; }); diff --git a/lemur/static/app/angular/sources/services.js b/lemur/static/app/angular/sources/services.js index d29897d1..e584bbe2 100644 --- a/lemur/static/app/angular/sources/services.js +++ b/lemur/static/app/angular/sources/services.js @@ -3,7 +3,7 @@ angular.module('lemur') .service('SourceApi', function (LemurRestangular) { return LemurRestangular.all('sources'); }) - .service('SourceService', function ($location, SourceApi, PluginService, toaster) { + .service('SourceService', function ($location, SourceApi, PluginService) { var SourceService = this; SourceService.findSourcesByName = function (filterValue) { return SourceApi.getList({'filter[label]': filterValue}) @@ -13,41 +13,11 @@ angular.module('lemur') }; SourceService.create = function (source) { - return SourceApi.post(source).then( - function () { - toaster.pop({ - type: 'success', - title: source.label, - body: 'Successfully created!' - }); - $location.path('sources'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: source.label, - body: 'Was not created! ' + response.data.message - }); - }); + return SourceApi.post(source); }; SourceService.update = function (source) { - return source.put().then( - function () { - toaster.pop({ - type: 'success', - title: source.label, - body: 'Successfully updated!' - }); - $location.path('sources'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: source.label, - body: 'Was not updated! ' + response.data.message - }); - }); + return source.put(); }; SourceService.getPlugin = function (source) { diff --git a/lemur/static/app/angular/sources/source/source.js b/lemur/static/app/angular/sources/source/source.js index 4a1f40b9..6ae256ba 100644 --- a/lemur/static/app/angular/sources/source/source.js +++ b/lemur/static/app/angular/sources/source/source.js @@ -2,7 +2,7 @@ angular.module('lemur') - .controller('SourcesCreateController', function ($scope, $uibModalInstance, PluginService, SourceService, LemurRestangular){ + .controller('SourcesCreateController', function ($scope, $uibModalInstance, PluginService, SourceService, LemurRestangular, toaster){ $scope.source = LemurRestangular.restangularizeElement(null, {}, 'sources'); PluginService.getByType('source').then(function (plugins) { @@ -10,9 +10,24 @@ angular.module('lemur') }); $scope.save = function (source) { - SourceService.create(source).then(function () { - $uibModalInstance.close(); - }); + SourceService.create(source).then( + function () { + toaster.pop({ + type: 'success', + title: source.label, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: source.label, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { @@ -20,14 +35,13 @@ angular.module('lemur') }; }) - .controller('SourcesEditController', function ($scope, $uibModalInstance, SourceService, SourceApi, PluginService, editId) { + .controller('SourcesEditController', function ($scope, $uibModalInstance, SourceService, SourceApi, PluginService, toaster, editId) { SourceApi.get(editId).then(function (source) { $scope.source = source; PluginService.getByType('source').then(function (plugins) { $scope.plugins = plugins; _.each($scope.plugins, function (plugin) { if (plugin.slug === $scope.source.pluginName) { - plugin.pluginOptions = $scope.source.sourceOptions; $scope.source.plugin = plugin; } }); @@ -38,15 +52,29 @@ angular.module('lemur') $scope.plugins = plugins; _.each($scope.plugins, function (plugin) { if (plugin.slug === $scope.source.pluginName) { - plugin.pluginOptions = $scope.source.sourceOptions; $scope.source.plugin = plugin; } }); }); $scope.save = function (source) { - SourceService.update(source).then(function () { - $uibModalInstance.close(); + SourceService.update(source).then( + function () { + toaster.pop({ + type: 'success', + title: source.label, + body: 'Successfully Updated!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: source.label, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); }); }; diff --git a/lemur/static/app/angular/sources/view/view.js b/lemur/static/app/angular/sources/view/view.js index a93b4284..b3dc250e 100644 --- a/lemur/static/app/angular/sources/view/view.js +++ b/lemur/static/app/angular/sources/view/view.js @@ -24,9 +24,6 @@ angular.module('lemur') getData: function ($defer, params) { SourceApi.getList(params.url()).then( function (data) { - _.each(data, function (source) { - SourceService.getPlugin(source); - }); params.total(data.total); $defer.resolve(data); } diff --git a/lemur/static/app/angular/users/services.js b/lemur/static/app/angular/users/services.js index 3075beb3..6c853aa3 100644 --- a/lemur/static/app/angular/users/services.js +++ b/lemur/static/app/angular/users/services.js @@ -20,7 +20,7 @@ angular.module('lemur') }); return LemurRestangular.all('users'); }) - .service('UserService', function ($location, UserApi, AuthenticationApi, toaster) { + .service('UserService', function ($location, UserApi, AuthenticationApi) { var UserService = this; UserService.getCurrentUser = function () { return AuthenticationApi.customGET('me').then(function (user) { @@ -50,40 +50,10 @@ angular.module('lemur') }; UserService.create = function (user) { - return UserApi.post(user).then( - function () { - toaster.pop({ - type: 'success', - title: user.username, - body: 'Has been successfully created!' - }); - $location.path('users'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: user.username, - body: 'Has not been created!' + response.data.message - }); - }); + return UserApi.post(user); }; UserService.update = function (user) { - return user.put().then( - function () { - toaster.pop({ - type: 'success', - title: user.username, - body: 'Has been successfully updated!' - }); - $location.path('users'); - }, - function (response) { - toaster.pop({ - type: 'error', - title: user.username, - body: 'Has not been updated!' + response.data.message - }); - }); + return user.put(); }; }); diff --git a/lemur/static/app/angular/users/user/user.js b/lemur/static/app/angular/users/user/user.js index c9f5393c..c403dd9a 100644 --- a/lemur/static/app/angular/users/user/user.js +++ b/lemur/static/app/angular/users/user/user.js @@ -2,7 +2,7 @@ angular.module('lemur') - .controller('UsersEditController', function ($scope, $uibModalInstance, UserApi, UserService, RoleService, editId) { + .controller('UsersEditController', function ($scope, $uibModalInstance, UserApi, UserService, RoleService, toaster, editId) { UserApi.get(editId).then(function (user) { UserService.getRoles(user); $scope.user = user; @@ -15,9 +15,24 @@ angular.module('lemur') $scope.save = function (user) { - UserService.update(user).then(function () { - $uibModalInstance.close(); - }); + UserService.update(user).then( + function () { + toaster.pop({ + type: 'success', + title: user.username, + body: 'Successfully Updated!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: user.username, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { @@ -30,15 +45,30 @@ angular.module('lemur') }; }) - .controller('UsersCreateController', function ($scope, $uibModalInstance, UserService, LemurRestangular, RoleService) { + .controller('UsersCreateController', function ($scope, $uibModalInstance, UserService, LemurRestangular, RoleService, toaster) { $scope.user = LemurRestangular.restangularizeElement(null, {}, 'users'); $scope.save = UserService.create; $scope.roleService = RoleService; $scope.create = function (user) { - UserService.create(user).then(function () { - $uibModalInstance.close(); - }); + UserService.create(user).then( + function () { + toaster.pop({ + type: 'success', + title: user.username, + body: 'Successfully Created!' + }); + $uibModalInstance.close(); + }, function (response) { + toaster.pop({ + type: 'error', + title: user.username, + body: 'lemur-bad-request', + bodyOutputType: 'directive', + directiveData: response.data, + timeout: 100000 + }); + }); }; $scope.cancel = function () { diff --git a/lemur/static/app/angular/users/view/view.js b/lemur/static/app/angular/users/view/view.js index a79392f9..708302e9 100644 --- a/lemur/static/app/angular/users/view/view.js +++ b/lemur/static/app/angular/users/view/view.js @@ -10,7 +10,7 @@ angular.module('lemur') }); }) - .controller('UsersViewController', function ($scope, $modal, UserApi, UserService, ngTableParams) { + .controller('UsersViewController', function ($scope, $uibModal, UserApi, UserService, ngTableParams) { $scope.filter = {}; $scope.usersTable = new ngTableParams({ page: 1, // show first page @@ -38,7 +38,7 @@ angular.module('lemur') }; $scope.edit = function (userId) { - var modalInstance = $modal.open({ + var uibModalInstance = $uibModal.open({ animation: true, templateUrl: '/angular/users/user/user.tpl.html', controller: 'UsersEditController', @@ -51,14 +51,14 @@ angular.module('lemur') } }); - modalInstance.result.then(function () { + uibModalInstance.result.then(function () { $scope.usersTable.reload(); }); }; $scope.create = function () { - var modalInstance = $modal.open({ + var uibModalInstance = $uibModal.open({ animation: true, controller: 'UsersCreateController', templateUrl: '/angular/users/user/user.tpl.html', @@ -66,7 +66,7 @@ angular.module('lemur') backdrop: 'static' }); - modalInstance.result.then(function () { + uibModalInstance.result.then(function () { $scope.usersTable.reload(); }); diff --git a/lemur/tests/test_roles.py b/lemur/tests/test_roles.py index 37a57155..9514b9ea 100644 --- a/lemur/tests/test_roles.py +++ b/lemur/tests/test_roles.py @@ -73,8 +73,8 @@ def test_role_list_post_(client, token, status): @pytest.mark.parametrize("token,status", [ - (VALID_USER_HEADER_TOKEN, 404), - (VALID_ADMIN_HEADER_TOKEN, 404), + (VALID_USER_HEADER_TOKEN, 200), + (VALID_ADMIN_HEADER_TOKEN, 200), ('', 401) ]) def test_role_list_get(client, token, status): diff --git a/lemur/tests/test_users.py b/lemur/tests/test_users.py index e709d2ce..46d149ca 100644 --- a/lemur/tests/test_users.py +++ b/lemur/tests/test_users.py @@ -75,8 +75,8 @@ def test_user_list_post_(client, token, status): @pytest.mark.parametrize("token,status", [ - (VALID_USER_HEADER_TOKEN, 404), - (VALID_ADMIN_HEADER_TOKEN, 404), + (VALID_USER_HEADER_TOKEN, 200), + (VALID_ADMIN_HEADER_TOKEN, 200), ('', 401) ]) def test_user_list_get(client, token, status): diff --git a/lemur/users/schemas.py b/lemur/users/schemas.py index 6a5bfe7e..dd213f04 100644 --- a/lemur/users/schemas.py +++ b/lemur/users/schemas.py @@ -21,6 +21,7 @@ class UserInputSchema(LemurInputSchema): class UserOutputSchema(LemurOutputSchema): + id = fields.Integer() username = fields.String() email = fields.Email() password = fields.String() diff --git a/lemur/users/service.py b/lemur/users/service.py index 38772ba1..3d5d4a64 100644 --- a/lemur/users/service.py +++ b/lemur/users/service.py @@ -135,4 +135,4 @@ def render(args): terms = filt.split(';') query = database.filter(query, User, terms) - database.sort_and_page(query, User, args) + return database.sort_and_page(query, User, args) diff --git a/lemur/users/views.py b/lemur/users/views.py index 8d76c89a..2f7f43bc 100644 --- a/lemur/users/views.py +++ b/lemur/users/views.py @@ -229,7 +229,7 @@ class CertificateUsers(AuthenticatedResource): self.reqparse = reqparse.RequestParser() super(CertificateUsers, self).__init__() - @validate_schema(None, user_output_schema) + @validate_schema(None, users_output_schema) def get(self, certificate_id): """ .. http:get:: /certificates/1/creator @@ -271,7 +271,7 @@ class RoleUsers(AuthenticatedResource): self.reqparse = reqparse.RequestParser() super(RoleUsers, self).__init__() - @validate_schema(None, user_output_schema) + @validate_schema(None, users_output_schema) def get(self, role_id): """ .. http:get:: /roles/1/users diff --git a/setup.py b/setup.py index 4249ca97..4f4fdeea 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ install_requires = [ 'marshmallow-sqlalchemy==0.8.0', 'marshmallow==2.4.0', 'pycrypto==2.6.1', - 'cryptography==1.3.1', + 'cryptography==1.3.2', 'pyopenssl==0.15.1', 'pyjwt==1.4.0', 'xmltodict==0.9.2',