Merge "Clarifying user roles in various places."
This commit is contained in:
commit
e0ecc22728
@ -262,6 +262,11 @@ def role_list(request):
|
||||
return keystoneclient(request, admin=True).roles.list()
|
||||
|
||||
|
||||
def roles_for_user(request, user, project):
|
||||
return keystoneclient(request, admin=True).roles.roles_for_user(user,
|
||||
project)
|
||||
|
||||
|
||||
def add_tenant_user_role(request, tenant_id, user_id, role_id):
|
||||
""" Adds a role for a user on a tenant. """
|
||||
return keystoneclient(request, admin=True).roles.add_user_role(user_id,
|
||||
@ -289,6 +294,7 @@ def get_default_role(request):
|
||||
try:
|
||||
roles = keystoneclient(request, admin=True).roles.list()
|
||||
except:
|
||||
roles = []
|
||||
exceptions.handle(request)
|
||||
for role in roles:
|
||||
if role.id == default or role.name == default:
|
||||
|
@ -4,6 +4,7 @@ from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import api
|
||||
from horizon import exceptions
|
||||
from horizon import tables
|
||||
|
||||
from ..users.tables import UsersTable
|
||||
@ -70,16 +71,16 @@ class TenantFilterAction(tables.FilterAction):
|
||||
|
||||
|
||||
class TenantsTable(tables.DataTable):
|
||||
id = tables.Column('id', verbose_name=_('Id'))
|
||||
name = tables.Column('name', verbose_name=_('Name'))
|
||||
description = tables.Column(lambda obj: getattr(obj, 'description', None),
|
||||
verbose_name=_('Description'))
|
||||
id = tables.Column('id', verbose_name=_('Project ID'))
|
||||
enabled = tables.Column('enabled', verbose_name=_('Enabled'), status=True)
|
||||
|
||||
class Meta:
|
||||
name = "tenants"
|
||||
verbose_name = _("Projects")
|
||||
row_actions = (EditLink, UsageLink, ViewMembersLink, ModifyQuotasLink,
|
||||
row_actions = (ViewMembersLink, EditLink, UsageLink, ModifyQuotasLink,
|
||||
DeleteTenantsAction)
|
||||
table_actions = (TenantFilterAction, CreateLink, DeleteTenantsAction)
|
||||
|
||||
@ -97,12 +98,29 @@ class RemoveUserAction(tables.BatchAction):
|
||||
api.keystone.remove_tenant_user(request, tenant_id, user_id)
|
||||
|
||||
|
||||
class ProjectUserRolesColumn(tables.Column):
|
||||
def get_raw_data(self, user):
|
||||
request = self.table._meta.request
|
||||
try:
|
||||
roles = api.keystone.roles_for_user(request,
|
||||
user.id,
|
||||
self.table.kwargs["tenant_id"])
|
||||
except:
|
||||
roles = []
|
||||
exceptions.handle(request,
|
||||
_("Unable to retrieve role information."))
|
||||
return ", ".join([role.name for role in roles])
|
||||
|
||||
|
||||
class TenantUsersTable(UsersTable):
|
||||
roles = ProjectUserRolesColumn("roles", verbose_name=_("Roles"))
|
||||
|
||||
class Meta:
|
||||
name = "tenant_users"
|
||||
verbose_name = _("Users For Project")
|
||||
table_actions = (RemoveUserAction,)
|
||||
row_actions = (RemoveUserAction,)
|
||||
columns = ("name", "email", "id", "roles", "enabled")
|
||||
|
||||
|
||||
class AddUserAction(tables.LinkAction):
|
||||
@ -122,3 +140,4 @@ class AddUsersTable(UsersTable):
|
||||
verbose_name = _("Add New Users")
|
||||
table_actions = ()
|
||||
row_actions = (AddUserAction,)
|
||||
columns = ("name", "email", "id", "enabled")
|
||||
|
@ -67,12 +67,17 @@ class TenantsViewTests(test.BaseAdminViewTests):
|
||||
def test_modify_users(self):
|
||||
self.mox.StubOutWithMock(api.keystone, 'tenant_get')
|
||||
self.mox.StubOutWithMock(api.keystone, 'user_list')
|
||||
self.mox.StubOutWithMock(api.keystone, 'roles_for_user')
|
||||
api.keystone.tenant_get(IgnoreArg(), self.tenant.id, admin=True) \
|
||||
.AndReturn(self.tenant)
|
||||
api.keystone.user_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.users.list())
|
||||
api.keystone.user_list(IsA(http.HttpRequest), self.tenant.id) \
|
||||
.AndReturn([self.user])
|
||||
api.keystone.roles_for_user(IsA(http.HttpRequest),
|
||||
self.user.id,
|
||||
self.tenant.id) \
|
||||
.AndReturn(self.roles.list())
|
||||
self.mox.ReplayAll()
|
||||
url = reverse('horizon:syspanel:projects:users',
|
||||
args=(self.tenant.id,))
|
||||
|
@ -72,6 +72,13 @@ class CreateUserForm(BaseUserForm):
|
||||
required=False,
|
||||
widget=forms.PasswordInput(render_value=False))
|
||||
tenant_id = forms.ChoiceField(label=_("Primary Project"))
|
||||
role_id = forms.ChoiceField(label=_("Role"))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
roles = kwargs.pop('roles')
|
||||
super(CreateUserForm, self).__init__(*args, **kwargs)
|
||||
role_choices = [(role.id, role.name) for role in roles]
|
||||
self.fields['role_id'].choices = role_choices
|
||||
|
||||
# We have to protect the entire "data" dict because it contains the
|
||||
# password and confirm_password strings.
|
||||
@ -89,12 +96,10 @@ class CreateUserForm(BaseUserForm):
|
||||
_('User "%s" was successfully created.')
|
||||
% data['name'])
|
||||
try:
|
||||
default_role = api.keystone.get_default_role(request)
|
||||
if default_role:
|
||||
api.add_tenant_user_role(request,
|
||||
data['tenant_id'],
|
||||
new_user.id,
|
||||
default_role.id)
|
||||
api.add_tenant_user_role(request,
|
||||
data['tenant_id'],
|
||||
new_user.id,
|
||||
data['role_id'])
|
||||
except:
|
||||
exceptions.handle(request,
|
||||
_('Unable to add user to primary project.'))
|
||||
|
@ -103,12 +103,12 @@ class UsersTable(tables.DataTable):
|
||||
("true", True),
|
||||
("false", False)
|
||||
)
|
||||
id = tables.Column('id', verbose_name=_('ID'))
|
||||
name = tables.Column('name', verbose_name=_('User Name'))
|
||||
email = tables.Column('email', verbose_name=_('Email'))
|
||||
# Default tenant is not returned from Keystone currently.
|
||||
#default_tenant = tables.Column('default_tenant',
|
||||
# verbose_name=_('Default Project'))
|
||||
id = tables.Column('id', verbose_name=_('User ID'))
|
||||
enabled = tables.Column('enabled', verbose_name=_('Enabled'),
|
||||
status=True,
|
||||
status_choices=STATUS_CHOICES,
|
||||
|
@ -46,7 +46,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
@test.create_stubs({api: ('user_create',
|
||||
'tenant_list',
|
||||
'add_tenant_user_role'),
|
||||
api.keystone: ('get_default_role',)})
|
||||
api.keystone: ('get_default_role',
|
||||
'role_list')})
|
||||
def test_create(self):
|
||||
user = self.users.get(id="1")
|
||||
role = self.roles.first()
|
||||
@ -58,6 +59,7 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
user.password,
|
||||
self.tenant.id,
|
||||
True).AndReturn(user)
|
||||
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
|
||||
api.keystone.get_default_role(IgnoreArg()).AndReturn(role)
|
||||
api.add_tenant_user_role(IgnoreArg(), self.tenant.id, user.id, role.id)
|
||||
|
||||
@ -68,17 +70,22 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
'email': user.email,
|
||||
'password': user.password,
|
||||
'tenant_id': self.tenant.id,
|
||||
'role_id': self.roles.first().id,
|
||||
'confirm_password': user.password}
|
||||
res = self.client.post(USER_CREATE_URL, formData)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertMessageCount(success=1)
|
||||
|
||||
@test.create_stubs({api: ('tenant_list',)})
|
||||
@test.create_stubs({api: ('tenant_list',),
|
||||
api.keystone: ('role_list', 'get_default_role')})
|
||||
def test_create_with_password_mismatch(self):
|
||||
user = self.users.get(id="1")
|
||||
|
||||
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
|
||||
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
|
||||
api.keystone.get_default_role(IgnoreArg()) \
|
||||
.AndReturn(self.roles.first())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -87,17 +94,22 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
'email': user.email,
|
||||
'password': user.password,
|
||||
'tenant_id': self.tenant.id,
|
||||
'role_id': self.roles.first().id,
|
||||
'confirm_password': "doesntmatch"}
|
||||
|
||||
res = self.client.post(USER_CREATE_URL, formData)
|
||||
|
||||
self.assertFormError(res, "form", None, ['Passwords do not match.'])
|
||||
|
||||
@test.create_stubs({api: ('tenant_list',)})
|
||||
@test.create_stubs({api: ('tenant_list',),
|
||||
api.keystone: ('role_list', 'get_default_role')})
|
||||
def test_create_validation_for_password_too_short(self):
|
||||
user = self.users.get(id="1")
|
||||
|
||||
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
|
||||
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
|
||||
api.keystone.get_default_role(IgnoreArg()) \
|
||||
.AndReturn(self.roles.first())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -107,6 +119,7 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
'email': user.email,
|
||||
'password': 'four',
|
||||
'tenant_id': self.tenant.id,
|
||||
'role_id': self.roles.first().id,
|
||||
'confirm_password': 'four'}
|
||||
|
||||
res = self.client.post(USER_CREATE_URL, formData)
|
||||
@ -115,11 +128,15 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
res, "form", 'password',
|
||||
['Password must be between 8 and 18 characters.'])
|
||||
|
||||
@test.create_stubs({api: ('tenant_list',)})
|
||||
@test.create_stubs({api: ('tenant_list',),
|
||||
api.keystone: ('role_list', 'get_default_role')})
|
||||
def test_create_validation_for_password_too_long(self):
|
||||
user = self.users.get(id="1")
|
||||
|
||||
api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
|
||||
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
|
||||
api.keystone.get_default_role(IgnoreArg()) \
|
||||
.AndReturn(self.roles.first())
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -129,6 +146,7 @@ class UsersViewTests(test.BaseAdminViewTests):
|
||||
'email': user.email,
|
||||
'password': 'MoreThanEighteenChars',
|
||||
'tenant_id': self.tenant.id,
|
||||
'role_id': self.roles.first().id,
|
||||
'confirm_password': 'MoreThanEighteenChars'}
|
||||
|
||||
res = self.client.post(USER_CREATE_URL, formData)
|
||||
|
@ -18,7 +18,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import operator
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
@ -33,9 +33,6 @@ from .forms import CreateUserForm, UpdateUserForm
|
||||
from .tables import UsersTable
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IndexView(tables.DataTableView):
|
||||
table_class = UsersTable
|
||||
template_name = 'syspanel/users/index.html'
|
||||
@ -85,3 +82,20 @@ class CreateView(forms.ModalFormView):
|
||||
'confirm_password'))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(CreateView, self).dispatch(*args, **kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(CreateView, self).get_form_kwargs()
|
||||
try:
|
||||
roles = api.keystone.role_list(self.request)
|
||||
except:
|
||||
redirect = reverse("horizon:syspanel:users:index")
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to retrieve user roles."),
|
||||
redirect=redirect)
|
||||
roles.sort(key=operator.attrgetter("id"))
|
||||
kwargs['roles'] = roles
|
||||
return kwargs
|
||||
|
||||
def get_initial(self):
|
||||
default_role = api.keystone.get_default_role(self.request)
|
||||
return {'role_id': getattr(default_role, "id", None)}
|
||||
|
Loading…
Reference in New Issue
Block a user