diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/actions.module.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/actions.module.js new file mode 100644 index 0000000000..22293e216d --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/actions.module.js @@ -0,0 +1,54 @@ +/* + * 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.domains.actions + * + * @description + * Provides all of the actions for domains. + */ + angular.module('horizon.dashboard.identity.domains.actions', [ + 'horizon.dashboard.identity.domains' + ]) + .run(registerDomainActions); + + registerDomainActions.$inject = [ + 'horizon.framework.conf.resource-type-registry.service', + 'horizon.dashboard.identity.domains.actions.create.service', + 'horizon.dashboard.identity.domains.resourceType' + ]; + + function registerDomainActions( + registry, + createDomainService, + domainResourceType + ) { + var resourceType = registry.getResourceType(domainResourceType); + + resourceType.globalActions + .append({ + id: 'createDomainAction', + service: createDomainService, + template: { + text: gettext('Create Domain'), + type: 'create' + } + }); + } + +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/actions.module.spec.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/actions.module.spec.js new file mode 100644 index 0000000000..2e272c447c --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/actions.module.spec.js @@ -0,0 +1,24 @@ +/** + * 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.domains.actions', function () { + it('should exist', function () { + expect(angular.module('horizon.dashboard.identity.domains.actions')).toBeDefined(); + }); + }); + +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/create.service.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/create.service.js new file mode 100644 index 0000000000..eb6f5a7a19 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/create.service.js @@ -0,0 +1,76 @@ +/** + * 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 factory + * @name horizon.dashboard.identity.domains.actions.create.service + * @description + * Service for the domain create modal + */ + angular + .module('horizon.dashboard.identity.domains.actions') + .factory('horizon.dashboard.identity.domains.actions.create.service', createService); + + createService.$inject = [ + '$q', + 'horizon.app.core.openstack-service-api.keystone', + 'horizon.app.core.openstack-service-api.policy', + 'horizon.dashboard.identity.domains.actions.workflow.service', + 'horizon.dashboard.identity.domains.resourceType', + 'horizon.framework.util.actions.action-result.service', + 'horizon.framework.widgets.form.ModalFormService', + 'horizon.framework.widgets.toast.service' + ]; + + function createService( + $q, keystone, policy, workflow, resourceType, actionResult, modal, toast + ) { + + var service = { + allowed: allowed, + perform: perform + }; + + return service; + + /////// + + function allowed() { + return $q.all([ + keystone.canEditIdentity('domain'), + policy.ifAllowed({ rules: [['identity', 'create_domain']] }) + ]); + } + + function perform() { + var config = workflow.init(); + config.title = gettext("Create Domain"); + return modal.open(config).then(submit); + } + + function submit(context) { + return keystone.createDomain(context.model).then(success); + } + + function success(response) { + var domain = response.data; + var message = gettext('Domain %s was successfully created.'); + toast.add('success', interpolate(message, [domain.name])); + return actionResult.getActionResult().created(resourceType, domain.id).result; + } + } +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/create.service.spec.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/create.service.spec.js new file mode 100644 index 0000000000..f6d94b651d --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/create.service.spec.js @@ -0,0 +1,90 @@ +/** + * 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.domains.actions.create.service', function() { + + var service, $scope, $q, modal, keystoneAPI, policyAPI; + var createDomainResponse = { + data: { + id: '1234', + name: 'test', + description: 'desc', + enabled: true + } + }; + + beforeEach(module('horizon.framework')); + beforeEach(module('horizon.app.core')); + beforeEach(module('horizon.dashboard.identity.domains')); + + beforeEach(inject(function($injector, _$rootScope_, _$q_) { + $scope = _$rootScope_.$new(); + $q = _$q_; + + keystoneAPI = $injector.get('horizon.app.core.openstack-service-api.keystone'); + policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy'); + modal = $injector.get('horizon.framework.widgets.form.ModalFormService'); + service = $injector.get('horizon.dashboard.identity.domains.actions.create.service'); + })); + + describe('should open the modal', function() { + it('open the modal', function() { + var deferred = $q.defer(); + deferred.resolve(true); + spyOn(modal, "open").and.returnValue($q.defer().promise); + + service.perform(); + $scope.$apply(); + + expect(modal.open).toHaveBeenCalled(); + }); + + it('should call keystone.createDomain', function() { + var deferred = $q.defer(); + deferred.resolve(true); + spyOn(modal, "open").and.returnValue(deferred.promise); + + var deferredCreateDomain = $q.defer(); + deferredCreateDomain.resolve(createDomainResponse); + spyOn(keystoneAPI, 'createDomain').and.returnValue(deferredCreateDomain.promise); + + service.perform(); + $scope.$apply(); + + expect(keystoneAPI.createDomain).toHaveBeenCalled(); + }); + }); + + describe('allowed', function() { + it('should allow create domain', function() { + var deferred = $q.defer(); + deferred.resolve(true); + spyOn(policyAPI, 'ifAllowed').and.returnValue(deferred.promise); + var deferredCanEdit = $q.defer(); + deferredCanEdit.resolve(true); + spyOn(keystoneAPI, 'canEditIdentity').and.returnValue(deferredCanEdit.promise); + + var allowed = service.allowed(); + + expect(allowed).toBeTruthy(); + expect(keystoneAPI.canEditIdentity).toHaveBeenCalledWith('domain'); + expect(policyAPI.ifAllowed).toHaveBeenCalledWith( + { rules: [['identity', 'create_domain']] }); + }); + }); + }); +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/info.help.html b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/info.help.html new file mode 100644 index 0000000000..47b611c5f6 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/info.help.html @@ -0,0 +1 @@ +

Domains provide separation between users and infrastructure used by different organizations.

diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/workflow.service.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/workflow.service.js new file mode 100644 index 0000000000..0ff2da4f8b --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/workflow.service.js @@ -0,0 +1,112 @@ +/** + * 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 factory + * @name horizon.dashboard.identity.domains.actions.workflow.service + * @ngController + * + * @description + * Workflow for creating/updating domain + */ + angular + .module('horizon.dashboard.identity.domains.actions') + .factory('horizon.dashboard.identity.domains.actions.workflow.service', DomainWorkflow); + + DomainWorkflow.$inject = [ + 'horizon.dashboard.identity.domains.basePath' + ]; + + function DomainWorkflow(basePath) { + + var workflow = { + init: init + }; + + function init() { + var schema = { + type: "object", + properties: { + name: { + title: gettext('Domain Name'), + type: 'string' + }, + description: { + title: gettext('Description'), + type: 'string' + }, + enabled: { + title: gettext('Enabled'), + type: 'boolean', + default: true + } + }, + required: ['name'] + }; + + var form = [ + { + type: 'section', + htmlClass: 'row', + items: [ + { + type: 'section', + htmlClass: 'col-sm-6', + items: [ + { + key: "name" + }, + { + key: "description", + type: "textarea" + }, + { + key: "enabled", + type: "radiobuttons", + titleMap: [ + {value: true, name: gettext("Yes")}, + {value: false, name: gettext("No")} + ] + } + ] + }, + { + type: 'template', + templateUrl: basePath + "actions/workflow/info.help.html" + } + ] + } + ]; + + var model = { + name: "", + description: "", + enabled: true + }; + + var config = { + schema: schema, + form: form, + model: model + }; + + return config; + } + + return workflow; + } +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/workflow.service.spec.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/workflow.service.spec.js new file mode 100644 index 0000000000..4d09c0a663 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/actions/workflow/workflow.service.spec.js @@ -0,0 +1,42 @@ +/** + * 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.domains.actions.workflow.service', function() { + + var workflow; + + beforeEach(module('horizon.framework')); + beforeEach(module('horizon.app.core')); + beforeEach(module('horizon.dashboard.identity.domains')); + + beforeEach(inject(function($injector) { + workflow = $injector.get('horizon.dashboard.identity.domains.actions.workflow.service'); + })); + + function testInitWorkflow() { + var config = workflow.init(); + expect(config.schema).toBeDefined(); + expect(config.form).toBeDefined(); + expect(config.model).toBeDefined(); + return config; + } + + it('should be create workflow config for creation', function() { + testInitWorkflow(); + }); + }); +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/domains.module.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/domains.module.js index b5e918df76..163b7d1721 100644 --- a/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/domains.module.js +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/domains/domains.module.js @@ -28,7 +28,8 @@ angular .module('horizon.dashboard.identity.domains', [ 'ngRoute', - 'horizon.dashboard.identity.domains.details' + 'horizon.dashboard.identity.domains.details', + 'horizon.dashboard.identity.domains.actions' ]) .constant('horizon.dashboard.identity.domains.resourceType', 'OS::Keystone::Domain') .run(run)