Add policy checks in images panels
check policy of getting images in: project/images project/ngimages admin/images Only block listing images but not whole panel if failed on policy check. Create, Delete and other actions are controlled by according policys. give a message "Insufficient privilege level to get images." to user if polciy checks failed. Closes-Bug: #1529012 Change-Id: I97ab081425dd56fa7c3208efb58ba8b041eaba24
This commit is contained in:
parent
ea8e7a504a
commit
340e67c17a
|
@ -25,10 +25,12 @@ from django.core.urlresolvers import reverse_lazy
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import messages
|
||||
from horizon import tables
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.images.images import views
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from openstack_dashboard.dashboards.admin.images import forms as project_forms
|
||||
from openstack_dashboard.dashboards.admin.images \
|
||||
|
@ -51,6 +53,10 @@ class IndexView(tables.DataTableView):
|
|||
|
||||
def get_data(self):
|
||||
images = []
|
||||
if not policy.check((("image", "get_images"),), self.request):
|
||||
msg = _("Insufficient privilege level to retrieve image list.")
|
||||
messages.info(self.request, msg)
|
||||
return images
|
||||
filters = self.get_filters()
|
||||
prev_marker = self.request.GET.get(
|
||||
project_tables.AdminImagesTable._meta.prev_pagination_param, None)
|
||||
|
|
|
@ -24,9 +24,11 @@ Views for managing Images and Snapshots.
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import messages
|
||||
from horizon import tables
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard import policy
|
||||
|
||||
from openstack_dashboard.dashboards.project.images.images \
|
||||
import tables as images_tables
|
||||
|
@ -44,6 +46,10 @@ class IndexView(tables.DataTableView):
|
|||
return getattr(self, "_more", False)
|
||||
|
||||
def get_data(self):
|
||||
if not policy.check((("image", "get_images"),), self.request):
|
||||
msg = _("Insufficient privilege level to retrieve image list.")
|
||||
messages.info(self.request, msg)
|
||||
return []
|
||||
prev_marker = self.request.GET.get(
|
||||
images_tables.ImagesTable._meta.prev_pagination_param, None)
|
||||
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
ImagesTableController.$inject = [
|
||||
'$q',
|
||||
'$scope',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.app.core.images.detailsRoute',
|
||||
'horizon.app.core.images.events',
|
||||
'horizon.app.core.images.resourceType',
|
||||
'horizon.app.core.openstack-service-api.glance',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.userSession',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
|
@ -56,10 +58,12 @@
|
|||
function ImagesTableController(
|
||||
$q,
|
||||
$scope,
|
||||
toast,
|
||||
detailsRoute,
|
||||
events,
|
||||
imageResourceType,
|
||||
glance,
|
||||
policy,
|
||||
userSession,
|
||||
typeRegistry,
|
||||
actionResultService,
|
||||
|
@ -77,10 +81,19 @@
|
|||
ctrl.actionResultHandler = actionResultHandler;
|
||||
|
||||
typeRegistry.initActions(imageResourceType, $scope);
|
||||
loadImages();
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
// if user has permission
|
||||
// fetch table data and populate it
|
||||
ctrl.images = [];
|
||||
ctrl.imagesSrc = [];
|
||||
var rules = [['image', 'get_images']];
|
||||
policy.ifAllowed({ rules: rules }).then(loadImages, policyFailed);
|
||||
}
|
||||
|
||||
function loadImages() {
|
||||
ctrl.images = [];
|
||||
ctrl.imagesSrc = [];
|
||||
|
@ -105,6 +118,11 @@
|
|||
applyMetadataDefinitions();
|
||||
}
|
||||
|
||||
function policyFailed() {
|
||||
var msg = gettext('Insufficient privilege level to get images.');
|
||||
toast.add('info', msg);
|
||||
}
|
||||
|
||||
function difference(currentList, otherList, key) {
|
||||
return currentList.filter(filter);
|
||||
|
||||
|
|
|
@ -44,6 +44,17 @@
|
|||
}
|
||||
};
|
||||
|
||||
var policy = { allowed: true };
|
||||
function fakePolicy() {
|
||||
return {
|
||||
then: function(successFn, errorFn) {
|
||||
if (policy.allowed) { successFn(); }
|
||||
else { errorFn(); }
|
||||
}
|
||||
};
|
||||
}
|
||||
function fakeToast() { return { add: angular.noop }; }
|
||||
|
||||
var userSession = {
|
||||
get: function () {
|
||||
return {project_id: '123'};
|
||||
|
@ -68,7 +79,7 @@
|
|||
2: {id: '2', is_public: false, owner: 'not_me', filtered_visibility: 'Shared with Me'}
|
||||
};
|
||||
|
||||
var $scope, controller, detailsRoute;
|
||||
var $scope, controller, toastService, detailsRoute, policyAPI;
|
||||
|
||||
beforeEach(module('ui.bootstrap'));
|
||||
beforeEach(module('horizon.framework'));
|
||||
|
@ -88,9 +99,14 @@
|
|||
|
||||
beforeEach(inject(function ($injector, _$rootScope_) {
|
||||
$scope = _$rootScope_.$new();
|
||||
|
||||
toastService = $injector.get('horizon.framework.widgets.toast.service');
|
||||
policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
controller = $injector.get('$controller');
|
||||
detailsRoute = $injector.get('horizon.app.core.images.detailsRoute');
|
||||
|
||||
spyOn(toastService, 'add').and.callFake(fakeToast);
|
||||
spyOn(policyAPI, 'ifAllowed').and.callFake(fakePolicy);
|
||||
spyOn(glanceAPI, 'getImages').and.callThrough();
|
||||
spyOn(glanceAPI, 'getNamespaces').and.callThrough();
|
||||
spyOn(userSession, 'get').and.callThrough();
|
||||
|
@ -100,6 +116,8 @@
|
|||
|
||||
function createController() {
|
||||
return controller('horizon.app.core.images.table.ImagesController', {
|
||||
toast: toastService,
|
||||
policyAPI: policyAPI,
|
||||
glanceAPI: glanceAPI,
|
||||
userSession: userSession,
|
||||
$q: mockQ,
|
||||
|
@ -113,9 +131,12 @@
|
|||
});
|
||||
|
||||
it('should invoke initialization apis', function() {
|
||||
policy.allowed = true;
|
||||
var ctrl = createController();
|
||||
expect(userSession.get).toHaveBeenCalled();
|
||||
|
||||
expect(policyAPI.ifAllowed).toHaveBeenCalled();
|
||||
expect(glanceAPI.getImages).toHaveBeenCalled();
|
||||
expect(userSession.get).toHaveBeenCalled();
|
||||
expect(ctrl.imagesSrc).toEqual([
|
||||
expectedImages['1'],
|
||||
expectedImages['2']
|
||||
|
@ -186,5 +207,14 @@
|
|||
]);
|
||||
});
|
||||
|
||||
it('should not invoke glance apis if policy fails', function() {
|
||||
policy.allowed = false;
|
||||
createController();
|
||||
|
||||
expect(policyAPI.ifAllowed).toHaveBeenCalled();
|
||||
expect(toastService.add).toHaveBeenCalled();
|
||||
expect(glanceAPI.getImages).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
||||
|
|
Loading…
Reference in New Issue