From 64585b32cf7a2ca56efa416c671b5d44e5b2f4b1 Mon Sep 17 00:00:00 2001 From: "chen.qiaomin@99cloud.net" Date: Wed, 20 Jul 2016 02:41:13 +0000 Subject: [PATCH] Add Angular keystone role creation action Use schema-form to add create action To test set 'roles_panel' to True in settings.py Change-Id: If25574b69a171c8710137f68b2151638b1cdc769 Co-Authored-By: Richard Jones Co-Authored-By: Cindy Lu Partially-Implements: blueprint ng-roles --- .../identity/roles/actions/actions.module.js | 56 +++++++++++ .../roles/actions/create.action.service.js | 92 +++++++++++++++++++ .../actions/create.action.service.spec.js | 92 +++++++++++++++++++ .../dashboard/identity/roles/role.schema.js | 40 ++++++++ .../identity/roles/role.schema.spec.js | 33 +++++++ .../dashboard/identity/roles/roles.module.js | 3 +- 6 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/actions.module.js create mode 100644 openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.js create mode 100644 openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.spec.js create mode 100644 openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.js create mode 100644 openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.spec.js diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/actions.module.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/actions.module.js new file mode 100644 index 0000000000..ced90e6937 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/actions.module.js @@ -0,0 +1,56 @@ +/** + * Copyright 2016 99Cloud + * + * 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. + */ + +(function() { + 'use strict'; + + /** + * @ngdoc overview + * @ngname horizon.dashboard.identity.roles.actions + * + * @description + * Provides all of the actions for roles. + */ + angular + .module('horizon.dashboard.identity.roles.actions', [ + 'horizon.framework.conf' + ]) + .run(registerRoleActions); + + registerRoleActions.$inject = [ + 'horizon.framework.conf.resource-type-registry.service', + 'horizon.dashboard.identity.roles.actions.create.service', + 'horizon.dashboard.identity.roles.resourceType' + ]; + + function registerRoleActions( + registry, + createService, + roleResourceTypeCode + ) { + var roleResourceType = registry.getResourceType(roleResourceTypeCode); + roleResourceType.globalActions + .append({ + id: 'createRoleAction', + service: createService, + template: { + type: 'create', + text: gettext('Create Role') + } + }); + } + +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.js new file mode 100644 index 0000000000..8e1b8cbdb6 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.js @@ -0,0 +1,92 @@ +/** + * Copyright 2016 99Cloud + * + * 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. + */ + +(function() { + 'use strict'; + + angular + .module('horizon.dashboard.identity.roles') + .factory('horizon.dashboard.identity.roles.actions.create.service', createService); + + createService.$inject = [ + 'horizon.dashboard.identity.roles.resourceType', + 'horizon.dashboard.identity.roles.role-schema', + 'horizon.app.core.openstack-service-api.keystone', + 'horizon.app.core.openstack-service-api.policy', + 'horizon.framework.widgets.form.ModalFormService', + 'horizon.framework.util.actions.action-result.service', + 'horizon.framework.util.i18n.gettext', + 'horizon.framework.widgets.toast.service' + ]; + + /** + * @ngDoc factory + * @name horizon.dashboard.identity.roles.actions.create.service + * @Description A service to handle the Create Role modal. + */ + function createService( + resourceType, + schema, + keystoneAPI, + policy, + modalFormService, + actionResultService, + gettext, + toast + ) { + var service = { + allowed: allowed, + perform: perform, + submit: submit + }; + + return service; + + ////////////// + + function allowed() { + return policy.ifAllowed({ rules: [['identity', 'identity:create_role']] }); + } + + function perform() { + var model = {name: ''}; + + var config = { + title: gettext('Create Role'), + schema: schema, + form: ['*'], + model: model + }; + return modalFormService.open(config).then(submit); + } + + function submit(context) { + return keystoneAPI.createRole({name: context.model.name}).then(onSuccess); + } + + function onSuccess(response) { + var role = response.data; + toast.add('success', interpolate( + gettext('Role %s was successfully created.'), [role.name])); + + return actionResultService.getActionResult() + .created(resourceType, role.id) + .result; + } + + } +})(); + diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.spec.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.spec.js new file mode 100644 index 0000000000..13622b4806 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/actions/create.action.service.spec.js @@ -0,0 +1,92 @@ +/** + * Copyright 2016 99Cloud + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use self 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. + */ + +(function() { + 'use strict'; + + describe('horizon.dashboard.identity.roles.actions.create.service', function() { + + var $q, $scope, keystoneAPI, service, modalFormService, policyAPI, resType, toast; + + /////////////////////// + + beforeEach(module('horizon.framework')); + beforeEach(module('horizon.app.core')); + beforeEach(module('horizon.dashboard.identity.roles')); + + beforeEach(inject(function($injector, _$rootScope_, _$q_) { + $scope = _$rootScope_.$new(); + $q = _$q_; + service = $injector.get('horizon.dashboard.identity.roles.actions.create.service'); + toast = $injector.get('horizon.framework.widgets.toast.service'); + modalFormService = $injector.get('horizon.framework.widgets.form.ModalFormService'); + keystoneAPI = $injector.get('horizon.app.core.openstack-service-api.keystone'); + policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy'); + resType = $injector.get('horizon.dashboard.identity.roles.resourceType'); + })); + + it('should check the policy if the user is allowed to create roles', function() { + var deferred = $q.defer(); + spyOn(policyAPI, 'ifAllowed').and.returnValue(deferred.promise); + deferred.resolve({allowed: true}); + var handler = jasmine.createSpyObj('handler', ['success']); + + service.allowed().then(handler.success); + $scope.$apply(); + + expect(handler.success).toHaveBeenCalled(); + var allowed = handler.success.calls.first().args[0]; + + expect(allowed).toBeTruthy(); + expect(policyAPI.ifAllowed).toHaveBeenCalledWith( + { rules: [['identity', 'identity:create_role']] }); + }); + + it('should open the modal with the correct parameters', function() { + var deferred = $q.defer(); + spyOn(modalFormService, 'open').and.returnValue(deferred.promise); + + service.perform(); + + expect(modalFormService.open).toHaveBeenCalled(); + + var config = modalFormService.open.calls.mostRecent().args[0]; + expect(config.model).toBeDefined(); + expect(config.schema).toBeDefined(); + expect(config.form).toBeDefined(); + }); + + it('should submit create role request to keystone', function() { + var deferred = $q.defer(); + spyOn(keystoneAPI, 'createRole').and.returnValue(deferred.promise); + spyOn(toast, 'add').and.callFake(angular.noop); + var handler = jasmine.createSpyObj('handler', ['success']); + + deferred.resolve({data: {name: 'saved', id: '12345'}}); + service.submit({model: {name: 'entered'}}).then(handler.success); + + $scope.$apply(); + + expect(keystoneAPI.createRole).toHaveBeenCalledWith({name: 'entered'}); + expect(toast.add).toHaveBeenCalledWith('success', 'Role saved was successfully created.'); + + expect(handler.success).toHaveBeenCalled(); + var result = handler.success.calls.first().args[0]; + expect(result.created).toEqual([{type: resType, id: '12345'}]); + }); + + }); +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.js new file mode 100644 index 0000000000..20bfc7e675 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.js @@ -0,0 +1,40 @@ +/** + * Copyright 2016 Rackspace + * + * 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. + */ + +(function() { + 'use strict'; + + angular + .module('horizon.dashboard.identity.roles') + .factory('horizon.dashboard.identity.roles.role-schema', schema); + + schema.$inject = [ + 'horizon.framework.util.i18n.gettext' + ]; + + function schema(gettext) { + return { + type: 'object', + properties: { + name: { + title: gettext('Name'), + type: 'string' + } + }, + required: ['name'] + }; + } +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.spec.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.spec.js new file mode 100644 index 0000000000..0d46096c35 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/role.schema.spec.js @@ -0,0 +1,33 @@ +/** + * Copyright 2016 Rackspace + * + * 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. + */ +(function () { + 'use strict'; + + describe('horizon.dashboard.identity.roles.role.schema', function () { + var schema; + + beforeEach(module('horizon.app.core.openstack-service-api')); + beforeEach(module('horizon.dashboard.identity')); + beforeEach(module('horizon.framework')); + beforeEach(inject(function($injector) { + schema = $injector.get('horizon.dashboard.identity.roles.role-schema'); + })); + + it('should define a name property', function() { + expect(schema.properties.name).toBeDefined(); + }); + }); +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/roles.module.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/roles.module.js index 6ca5340fae..b729fb3f1d 100644 --- a/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/roles.module.js +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/roles/roles.module.js @@ -27,7 +27,8 @@ */ angular .module('horizon.dashboard.identity.roles', [ - 'ngRoute' + 'ngRoute', + 'horizon.dashboard.identity.roles.actions' ]) .constant('horizon.dashboard.identity.roles.resourceType', 'OS::Keystone::Role') .run(run)