159 lines
6.1 KiB
JavaScript
159 lines
6.1 KiB
JavaScript
/*
|
|
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
|
*
|
|
* 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.framework.conf')
|
|
.service('horizon.framework.conf.permissions.service', Permissions);
|
|
|
|
Permissions.$inject = ['$q'];
|
|
|
|
/**
|
|
* @ngdoc service
|
|
* @name horizon.framework.conf.permissions
|
|
* @module horizon.framework.conf
|
|
*
|
|
* This service provides a common set of a promise based permission checking that
|
|
* can be applied to various entities in horizon. In the most basic case,
|
|
* this code executes the allowed() function (if it exists) on
|
|
* items passed in and returns the promise which will either resolve
|
|
* if the item should be allowed or reject if it should not be allowed.
|
|
* An example of an item passed in might be a hz-dynamic-table column spec.
|
|
* See that code for an example of permissionService in use.
|
|
*
|
|
* Horizon is technically a set of application agnostic widgets and utilities
|
|
* that can be used for various applications. The OpenStack Dashboard is
|
|
* an implementation that uses these widgets. Many of these widgets, such
|
|
* as hz-dynamic-table may need to be displayed based on a variety of permissions
|
|
* that are application specific and that are more simply expressed in a declarative
|
|
* matter rather than functional code such as the allowed function. This service
|
|
* provides this capability by allowing applications to decorate this service and
|
|
* override the extendedPermissions function.
|
|
*
|
|
* In the openstack dashboard additional checks beyond the simple allowed() function
|
|
* are added to this service in the app.core.conf permissionsDecorator,
|
|
* including policies, services and settings.
|
|
*/
|
|
function Permissions($q) {
|
|
var service = {
|
|
checkAllowed: checkAllowed,
|
|
checkAll: checkAll,
|
|
extendedPermissions: extendedPermissions
|
|
};
|
|
|
|
return service;
|
|
|
|
/**
|
|
* If this input configItem has an allowed function, this will execute it and return
|
|
* the promise. Otherwise it will return a resolved promise.
|
|
*/
|
|
function checkAllowed(configItem) {
|
|
if (angular.isFunction(configItem.allowed)) {
|
|
return configItem.allowed();
|
|
} else {
|
|
return $q.when(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* On the given configItem, this will get configItem.allowed and get each
|
|
* additional property matching a permission defined in extended permissions.
|
|
* All of the promises will then be run using $q.all. If all promises resolve
|
|
* then this will resolve. Otherwise, this will reject.
|
|
*
|
|
* When the input to any given permission is an array, each element will be
|
|
* treated as a distinct permission and a single promise resolver will be invoked for
|
|
* each input element.
|
|
*
|
|
* @example
|
|
*
|
|
* In openstack dashboard, each of the policies in the below array will result in a distinct
|
|
* policy check and all of the policies must pass in order for this to permit (resolve) the
|
|
* permissions check.
|
|
*
|
|
* configItem.policies = [{ rules: [["identity", "identity:get_project"]] }, { <rule 2>}]
|
|
*/
|
|
function checkAll(configItem) {
|
|
var promises = [];
|
|
promises = promises.concat(getConfigurationPromises(configItem));
|
|
promises.push(checkAllowed(configItem));
|
|
return $q.all(promises);
|
|
}
|
|
|
|
/*
|
|
* This defines all additional permissions that can be defined on the input configItem
|
|
* of checkAll. This is a function that returns an object definition where
|
|
* each property on the object is the name of a permission that can be set on
|
|
* the configItem in order have permission to access / use whatever is being requested.
|
|
* The value of each property should be a promise that can resolve a single instance of that
|
|
* permission. When the input to any given permission is an array, each element will be
|
|
* treated as a distinct input and a single promise resolver will be invoked for
|
|
* each input element.
|
|
*
|
|
* Since this is part of the horizon framework, it defaults to returning an empty object.
|
|
* However, individual applications can decorate this service and override this
|
|
* function to provide common permissions for their application.
|
|
*
|
|
* @example
|
|
*
|
|
* Openstack Dashboard may set permissions for required policies, services, or settings
|
|
* (amongst other items). To do this, the service would be decorated like the following:
|
|
*
|
|
function decorator($delegate, policy, serviceCatalog, settings) {
|
|
var permissionsService = $delegate;
|
|
|
|
permissionsService.extendedPermissions = extendedPermissions;
|
|
|
|
function extendedPermissions() {
|
|
return {
|
|
policies: policy.ifAllowed,
|
|
services: serviceCatalog.ifTypeEnabled,
|
|
settings: settings.ifEnabled
|
|
};
|
|
}
|
|
|
|
return $delegate;
|
|
}
|
|
}
|
|
*/
|
|
function extendedPermissions() {
|
|
return {};
|
|
}
|
|
|
|
function getConfigurationPromises(configItem) {
|
|
|
|
var promises = [];
|
|
|
|
angular.forEach(service.extendedPermissions, checkPermissions);
|
|
|
|
function checkPermissions(permissionResolver, permissionName) {
|
|
var permissionInput = configItem[permissionName];
|
|
if (angular.isArray(permissionInput)) {
|
|
angular.forEach(permissionInput, function addPermissionCheck(singlePermissionInput) {
|
|
promises.push(permissionResolver(singlePermissionInput));
|
|
});
|
|
} else if (angular.isDefined(permissionInput)) {
|
|
promises.push(permissionResolver(permissionInput));
|
|
}
|
|
}
|
|
|
|
return promises;
|
|
}
|
|
|
|
}
|
|
})();
|