Various bug fixes. (#314)

This commit is contained in:
kevgliss 2016-05-12 12:38:44 -07:00
parent 9022059dc6
commit a0c8765588
32 changed files with 329 additions and 329 deletions

View File

@ -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')

View File

@ -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()

View File

@ -6,22 +6,31 @@
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
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()

View File

@ -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):

View File

@ -5,28 +5,33 @@
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
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()

View File

@ -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']
)

View File

@ -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):

View File

@ -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()

View File

@ -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)

View File

@ -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):

View File

@ -5,27 +5,32 @@
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
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)

View File

@ -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):

View File

@ -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');
};
});

View File

@ -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) {

View File

@ -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();
});

View File

@ -2,12 +2,27 @@
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 () {
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
});
});
};
@ -16,14 +31,29 @@ 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 () {
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
});
});
};

View File

@ -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,8 +62,23 @@ angular.module('lemur')
});
$scope.save = function (notification) {
NotificationService.update(notification).then(function () {
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
});
});
};

View File

@ -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;
});

View File

@ -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 () {
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,13 +43,28 @@ 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 () {
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
});
});
};

View File

@ -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');
};
});

View File

@ -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) {

View File

@ -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,8 +10,23 @@ angular.module('lemur')
});
$scope.save = function (source) {
SourceService.create(source).then(function () {
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
});
});
};
@ -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 () {
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
});
});
};

View File

@ -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);
}

View File

@ -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();
};
});

View File

@ -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,8 +15,23 @@ angular.module('lemur')
$scope.save = function (user) {
UserService.update(user).then(function () {
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
});
});
};
@ -30,14 +45,29 @@ 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 () {
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
});
});
};

View File

@ -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();
});

View File

@ -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):

View File

@ -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):

View File

@ -21,6 +21,7 @@ class UserInputSchema(LemurInputSchema):
class UserOutputSchema(LemurOutputSchema):
id = fields.Integer()
username = fields.String()
email = fields.Email()
password = fields.String()

View File

@ -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)

View File

@ -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

View File

@ -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',