Fix unauthorized exception when using member user to access angular users panel
When a member role user go to angular users panel, it will be raised unauthorized exception since the user has no access to get users list. It should be add a policy check mechanism at the panel. Change-Id: I9cfa1aeab27aca1631322d8c0b3e6a7a930d9cfe Closes-Bug: #1694127
This commit is contained in:
parent
946ecea7b7
commit
dc9a6a33ea
@ -123,7 +123,7 @@ class User(generic.View):
|
|||||||
"""
|
"""
|
||||||
if id == 'current':
|
if id == 'current':
|
||||||
id = request.user.id
|
id = request.user.id
|
||||||
return api.keystone.user_get(request, id).to_dict()
|
return api.keystone.user_get(request, id, admin=False).to_dict()
|
||||||
|
|
||||||
@rest_utils.ajax()
|
@rest_utils.ajax()
|
||||||
def delete(self, request, id):
|
def delete(self, request, id):
|
||||||
@ -487,7 +487,7 @@ class Project(generic.View):
|
|||||||
@rest_utils.ajax()
|
@rest_utils.ajax()
|
||||||
def get(self, request, id):
|
def get(self, request, id):
|
||||||
"""Get a specific project by id."""
|
"""Get a specific project by id."""
|
||||||
return api.keystone.tenant_get(request, id).to_dict()
|
return api.keystone.tenant_get(request, id, admin=False).to_dict()
|
||||||
|
|
||||||
@rest_utils.ajax()
|
@rest_utils.ajax()
|
||||||
def delete(self, request, id):
|
def delete(self, request, id):
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
'$q',
|
'$q',
|
||||||
'horizon.app.core.openstack-service-api.keystone',
|
'horizon.app.core.openstack-service-api.keystone',
|
||||||
'horizon.app.core.detailRoute',
|
'horizon.app.core.detailRoute',
|
||||||
|
'horizon.app.core.openstack-service-api.policy',
|
||||||
'horizon.app.core.openstack-service-api.settings'
|
'horizon.app.core.openstack-service-api.settings'
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -30,7 +31,7 @@
|
|||||||
* @ngdoc factory
|
* @ngdoc factory
|
||||||
* @name horizon.dashboard.identity.users.service
|
* @name horizon.dashboard.identity.users.service
|
||||||
*/
|
*/
|
||||||
function userService($q, keystone, detailRoute, settings) {
|
function userService($q, keystone, detailRoute, policy, settings) {
|
||||||
return {
|
return {
|
||||||
getDetailsPath: getDetailsPath,
|
getDetailsPath: getDetailsPath,
|
||||||
getUserPromise: getUserPromise,
|
getUserPromise: getUserPromise,
|
||||||
@ -57,9 +58,25 @@
|
|||||||
* Returns a promise for the users data.
|
* Returns a promise for the users data.
|
||||||
*/
|
*/
|
||||||
function getUsersPromise(params) {
|
function getUsersPromise(params) {
|
||||||
return keystone.getUsers(params).then(modifyResponse);
|
var rules = [['identity', 'identity:list_users']];
|
||||||
|
// Check whether the user has the privilege of list_users, if so, retrieve
|
||||||
|
// all the users, otherwise only retrieve the current login user details.
|
||||||
|
return policy.ifAllowed({ rules: rules }).then(policySuccess, policyFailed);
|
||||||
|
|
||||||
|
function policySuccess() {
|
||||||
|
return keystone.getUsers(params).then(modifyResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
function policyFailed() {
|
||||||
|
// In case that a user doesn't have a privilege of list_users.
|
||||||
|
return keystone.getUser('current').then(modifyResponse);
|
||||||
|
}
|
||||||
|
|
||||||
function modifyResponse(response) {
|
function modifyResponse(response) {
|
||||||
|
if (!angular.isArray(response.data.items)) {
|
||||||
|
// the result of getUser is not array.
|
||||||
|
response.data.items = [angular.copy(response.data)];
|
||||||
|
}
|
||||||
return {data: {items: response.data.items.map(modifyItem)}};
|
return {data: {items: response.data.items.map(modifyItem)}};
|
||||||
|
|
||||||
function modifyItem(item) {
|
function modifyItem(item) {
|
||||||
|
@ -17,12 +17,13 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
describe('Identity user service', function() {
|
describe('Identity user service', function() {
|
||||||
var service, keystone, scope, settings, $q, detailRoute;
|
var service, keystone, policy, scope, settings, $q, detailRoute;
|
||||||
|
|
||||||
beforeEach(module('horizon.dashboard.identity.users'));
|
beforeEach(module('horizon.dashboard.identity.users'));
|
||||||
beforeEach(inject(function($injector, _$q_) {
|
beforeEach(inject(function($injector, _$q_) {
|
||||||
service = $injector.get('horizon.dashboard.identity.users.service');
|
service = $injector.get('horizon.dashboard.identity.users.service');
|
||||||
keystone = $injector.get('horizon.app.core.openstack-service-api.keystone');
|
keystone = $injector.get('horizon.app.core.openstack-service-api.keystone');
|
||||||
|
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||||
settings = $injector.get('horizon.app.core.openstack-service-api.settings');
|
settings = $injector.get('horizon.app.core.openstack-service-api.settings');
|
||||||
detailRoute = $injector.get('horizon.app.core.detailRoute');
|
detailRoute = $injector.get('horizon.app.core.detailRoute');
|
||||||
scope = $injector.get('$rootScope').$new();
|
scope = $injector.get('$rootScope').$new();
|
||||||
@ -37,16 +38,21 @@
|
|||||||
describe('getUsersPromise', function() {
|
describe('getUsersPromise', function() {
|
||||||
|
|
||||||
it("provides a promise", function() {
|
it("provides a promise", function() {
|
||||||
var deferred = $q.defer();
|
var deferredGetUser = $q.defer();
|
||||||
spyOn(keystone, 'getUsers').and.returnValue(deferred.promise);
|
var deferredGetUsers = $q.defer();
|
||||||
|
var deferredPolicy = $q.defer();
|
||||||
|
spyOn(keystone, 'getUser').and.returnValue(deferredGetUser.promise);
|
||||||
|
spyOn(keystone, 'getUsers').and.returnValue(deferredGetUsers.promise);
|
||||||
|
spyOn(policy, 'ifAllowed').and.returnValue(deferredPolicy.promise);
|
||||||
|
|
||||||
var result = service.getUsersPromise();
|
var result = service.getUsersPromise();
|
||||||
deferred.resolve({data: {items: [{id: '1', name: 'puff'}]}});
|
deferredGetUser.resolve({data: {id: '1', name: 'puff'}});
|
||||||
|
deferredGetUsers.resolve({data: {items: [{id: '1234', name: 'test_user1'}]}});
|
||||||
|
deferredPolicy.resolve({"allowed": true});
|
||||||
|
|
||||||
scope.$apply();
|
scope.$apply();
|
||||||
|
|
||||||
expect(keystone.getUsers).toHaveBeenCalled();
|
expect(keystone.getUsers).toHaveBeenCalled();
|
||||||
expect(result.$$state.value.data.items[0].name).toBe('puff');
|
expect(result.$$state.value.data.items[0].name).toBe('test_user1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,7 +48,8 @@ class KeystoneRestTestCase(test.TestCase):
|
|||||||
response = keystone.User().get(request, 'the_id')
|
response = keystone.User().get(request, 'the_id')
|
||||||
self.assertStatusCode(response, 200)
|
self.assertStatusCode(response, 200)
|
||||||
self.assertEqual(response.json, {"name": "Ni!"})
|
self.assertEqual(response.json, {"name": "Ni!"})
|
||||||
self.mock_user_get.assert_called_once_with(request, 'the_id')
|
self.mock_user_get.assert_called_once_with(
|
||||||
|
request, 'the_id', admin=False)
|
||||||
|
|
||||||
@test.create_mocks({api.keystone: ['user_get']})
|
@test.create_mocks({api.keystone: ['user_get']})
|
||||||
def test_user_get_current(self):
|
def test_user_get_current(self):
|
||||||
@ -57,7 +58,8 @@ class KeystoneRestTestCase(test.TestCase):
|
|||||||
response = keystone.User().get(request, 'current')
|
response = keystone.User().get(request, 'current')
|
||||||
self.assertStatusCode(response, 200)
|
self.assertStatusCode(response, 200)
|
||||||
self.assertEqual(response.json, {"name": "Ni!"})
|
self.assertEqual(response.json, {"name": "Ni!"})
|
||||||
self.mock_user_get.assert_called_once_with(request, 'current_id')
|
self.mock_user_get.assert_called_once_with(
|
||||||
|
request, 'current_id', admin=False)
|
||||||
|
|
||||||
@test.create_mocks({api.keystone: ['user_list']})
|
@test.create_mocks({api.keystone: ['user_list']})
|
||||||
def test_user_get_list(self):
|
def test_user_get_list(self):
|
||||||
@ -519,7 +521,8 @@ class KeystoneRestTestCase(test.TestCase):
|
|||||||
response = keystone.Project().get(request, 'the_id')
|
response = keystone.Project().get(request, 'the_id')
|
||||||
self.assertStatusCode(response, 200)
|
self.assertStatusCode(response, 200)
|
||||||
self.assertEqual(response.json, {"name": "Ni!"})
|
self.assertEqual(response.json, {"name": "Ni!"})
|
||||||
self.mock_tenant_get.assert_called_once_with(request, 'the_id')
|
self.mock_tenant_get.assert_called_once_with(
|
||||||
|
request, 'the_id', admin=False)
|
||||||
|
|
||||||
def test_project_get_list(self):
|
def test_project_get_list(self):
|
||||||
self._test_project_get_list(
|
self._test_project_get_list(
|
||||||
|
Loading…
Reference in New Issue
Block a user