mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 18:40:01 -03:30
Partial support for permission editablity through REST. More TBA.
This commit is contained in:
parent
f18f3a339c
commit
b4932ab5a9
@ -168,15 +168,15 @@ class PrimordialModel(models.Model):
|
||||
@classmethod
|
||||
def can_user_administrate(cls, user, obj, data):
|
||||
# FIXME: do we want a seperate method to override put? This is kind of general purpose
|
||||
raise exceptions.NotImplementedError()
|
||||
raise Exception("can_user_administrate needs to be implemented in model subclass")
|
||||
|
||||
@classmethod
|
||||
def can_user_delete(cls, user, obj):
|
||||
raise exceptions.NotImplementedError()
|
||||
raise Exception("can_user_delete needs to be implemented in model subclass")
|
||||
|
||||
@classmethod
|
||||
def can_user_read(cls, user, obj):
|
||||
raise exceptions.NotImplementedError()
|
||||
raise Exception("can_user_read needs to be implemented in model subclass")
|
||||
|
||||
@classmethod
|
||||
def can_user_add(cls, user, data):
|
||||
@ -805,6 +805,37 @@ class Permission(CommonModelNameNotUnique):
|
||||
self.permission_type
|
||||
))
|
||||
|
||||
def get_absolute_url(self):
|
||||
import lib.urls
|
||||
return reverse(lib.urls.views_PermissionsDetail, args=(self.pk,))
|
||||
|
||||
@classmethod
|
||||
def can_user_administrate(cls, user, obj, data):
|
||||
if user.is_superuser:
|
||||
return True
|
||||
# a permission can be administrated by a super
|
||||
# or if a user permission, that an admin of a user's organization
|
||||
# or if a team permission, an admin of that team's organization
|
||||
if obj.user and obj.user.organizations.filter(admins__in = [user]).count() > 0:
|
||||
return True
|
||||
if obj.team and obj.team.organization.admins.filter(user=user).count() > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def can_user_read(cls, user, obj):
|
||||
# a permission can be seen by the assigned user or team
|
||||
# or anyone who can administrate that permission
|
||||
if obj.user and obj.user == user:
|
||||
return True
|
||||
if obj.team and obj.team.users.filter(pk = user.pk).count() > 0:
|
||||
return True
|
||||
return cls.can_user_administrate(user, obj, None)
|
||||
|
||||
@classmethod
|
||||
def can_user_delete(cls, user, obj):
|
||||
return cls.can_user_administrate(user, obj, None)
|
||||
|
||||
# TODO: other job types (later)
|
||||
|
||||
class JobTemplate(CommonModel):
|
||||
|
||||
@ -169,18 +169,42 @@ class TeamSerializer(BaseSerializer):
|
||||
users = reverse(lib.urls.views_TeamsUsersList, args=(obj.pk,)),
|
||||
credentials = reverse(lib.urls.views_TeamsCredentialsList, args=(obj.pk,)),
|
||||
organization = reverse(lib.urls.views_OrganizationsDetail, args=(obj.organization.pk,)),
|
||||
permissions = reverse(lib.urls.views_TeamsPermissionsList, args=(obj.pk,)),
|
||||
)
|
||||
if obj.created_by:
|
||||
res['created_by'] = reverse(lib.urls.views_UsersDetail, args=(obj.created_by.pk,))
|
||||
return res
|
||||
|
||||
class PermissionSerializer(BaseSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
related = serializers.SerializerMethodField('get_related')
|
||||
|
||||
class Meta:
|
||||
model = Permission
|
||||
fields = ( 'url', 'id', 'user', 'team', 'name', 'description', 'creation_date',
|
||||
'project', 'inventory', 'permission_type' )
|
||||
|
||||
def get_related(self, obj):
|
||||
res = dict()
|
||||
if obj.user:
|
||||
res['user'] = reverse(lib.urls.views_UsersDetail, args=(obj.user.pk,))
|
||||
if obj.team:
|
||||
res['team'] = reverse(lib.urls.views_TeamsDetail, args=(obj.team.pk,))
|
||||
if self.project:
|
||||
res['project'] = reverse(lib.urls.views_ProjectsDetail, args=(obj.project.pk,))
|
||||
if self.inventory:
|
||||
res['inventory'] = reverse(lib.urls.views_InventoryDetail, args=(obj.inventory.pk,))
|
||||
if self.created_by:
|
||||
res['created_by'] = reverse(lib.urls.views_UsersDetail, args=(obj.created_by.pk,))
|
||||
|
||||
class CredentialSerializer(BaseSerializer):
|
||||
|
||||
# add the URL and related resources
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
related = serializers.SerializerMethodField('get_related')
|
||||
|
||||
# FIXME: may want to make soem of these filtered based on user accessing
|
||||
# FIXME: may want to make some of these filtered based on user accessing
|
||||
class Meta:
|
||||
model = Credential
|
||||
fields = (
|
||||
@ -228,6 +252,7 @@ class UserSerializer(BaseSerializer):
|
||||
admin_of_organizations = reverse(lib.urls.views_UsersAdminOrganizationsList, args=(obj.pk,)),
|
||||
projects = reverse(lib.urls.views_UsersProjectsList, args=(obj.pk,)),
|
||||
credentials = reverse(lib.urls.views_UsersCredentialsList, args=(obj.pk,)),
|
||||
permissions = reverse(lib.urls.views_UsersPermissionsList, args=(obj.pk,)),
|
||||
)
|
||||
|
||||
def get_absolute_url_override(self, obj):
|
||||
|
||||
@ -386,15 +386,56 @@ class ProjectsTest(BaseTest):
|
||||
|
||||
# =====================================================================
|
||||
# PERMISSIONS
|
||||
|
||||
user = self.other_django_user
|
||||
team = Team.objects.get(pk=1)
|
||||
organization = Organization.objects.get(pk=1)
|
||||
inventory = Inventory.objects.create(
|
||||
name = 'test inventory',
|
||||
organization = organization,
|
||||
created_by = self.super_django_user
|
||||
)
|
||||
project = Project.objects.get(pk=1)
|
||||
|
||||
# can add permissions to a user
|
||||
|
||||
user_permission = dict(
|
||||
name='user can deploy a certain project to a certain inventory',
|
||||
# user=user.pk, # no need to specify, this will be automatically filled in
|
||||
inventory=inventory.pk,
|
||||
project=project.pk,
|
||||
permission_type=PERM_INVENTORY_DEPLOY
|
||||
)
|
||||
team_permission = dict(
|
||||
name='team can deploy a certain project to a certain inventory',
|
||||
# team=team.pk, # no need to specify, this will be automatically filled in
|
||||
inventory=inventory.pk,
|
||||
project=project.pk,
|
||||
permission_type=PERM_INVENTORY_DEPLOY
|
||||
)
|
||||
|
||||
url = '/api/v1/users/%s/permissions/' % user.pk
|
||||
self.post(url, user_permission, expect=201, auth=self.get_super_credentials())
|
||||
|
||||
# can add permissions on a team
|
||||
url = '/api/v1/teams/%s/permissions/' % team.pk
|
||||
self.post(url, team_permission, expect=201, auth=self.get_super_credentials())
|
||||
|
||||
# can list permissions on a user
|
||||
url = '/api/v1/users/%s/permissions/' % user.pk
|
||||
|
||||
# can list permissions on a team
|
||||
url = '/api/v1/teams/%s/permissions/' % team.pk
|
||||
|
||||
# can edit a permission
|
||||
# can remove credentials from a user
|
||||
# can remove credentials from a team
|
||||
|
||||
|
||||
|
||||
# can remove permissions from a user
|
||||
# do need to disassociate, just delete it
|
||||
|
||||
# can remove permissions from a team
|
||||
# do need to disassociate, just delete it
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -266,6 +266,23 @@ class TeamsUsersList(BaseSubList):
|
||||
return base
|
||||
raise PermissionDenied()
|
||||
|
||||
class TeamsPermissionsList(BaseSubList):
|
||||
|
||||
model = Permission
|
||||
serializer_class = PermissionSerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
parent_model = Team
|
||||
relationship = 'permissions'
|
||||
postable = True
|
||||
filter_fields = ('name',)
|
||||
inject_primary_key_on_post_as = 'team'
|
||||
|
||||
def _get_queryset(self):
|
||||
team = Team.objects.get(pk=self.kwargs['pk'])
|
||||
if not Team.can_user_administrate(self.request.user, team, None):
|
||||
raise PermissionDenied()
|
||||
return Permission.objects.filter(team = team)
|
||||
|
||||
|
||||
class TeamsProjectsList(BaseSubList):
|
||||
|
||||
@ -423,6 +440,23 @@ class UsersTeamsList(BaseSubList):
|
||||
raise PermissionDenied()
|
||||
return Team.objects.filter(users__in = [ user ])
|
||||
|
||||
class UsersPermissionsList(BaseSubList):
|
||||
|
||||
model = Permission
|
||||
serializer_class = PermissionSerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
parent_model = User
|
||||
relationship = 'permissions'
|
||||
postable = True
|
||||
filter_fields = ('name',)
|
||||
inject_primary_key_on_post_as = 'user'
|
||||
|
||||
def _get_queryset(self):
|
||||
user = User.objects.get(pk=self.kwargs['pk'])
|
||||
if not UserHelper.can_user_administrate(self.request.user, user, None):
|
||||
raise PermissionDenied()
|
||||
return Permission.objects.filter(user=user)
|
||||
|
||||
class UsersProjectsList(BaseSubList):
|
||||
|
||||
model = Project
|
||||
@ -514,6 +548,11 @@ class CredentialsDetail(BaseDetail):
|
||||
serializer_class = CredentialSerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
|
||||
class PermissionsDetail(BaseDetail):
|
||||
|
||||
model = Permission
|
||||
serializer_class = PermissionSerializer
|
||||
permission_classes = (CustomRbac,)
|
||||
|
||||
class InventoryList(BaseList):
|
||||
|
||||
|
||||
@ -102,6 +102,10 @@ views_TagsDetail = views.TagsDetail.as_view()
|
||||
# credentials service
|
||||
views_CredentialsDetail = views.CredentialsDetail.as_view()
|
||||
|
||||
# permissions
|
||||
views_UsersPermissionsList = views.UsersPermissionsList.as_view()
|
||||
views_TeamsPermissionsList = views.TeamsPermissionsList.as_view()
|
||||
views_PermissionsDetail = views.PermissionsDetail.as_view()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
|
||||
@ -199,8 +203,9 @@ urlpatterns = patterns('',
|
||||
url(r'^api/v1/credentials/(?P<pk>[0-9]+)/$', views_CredentialsDetail),
|
||||
|
||||
# permissions services
|
||||
# ... users
|
||||
# ... teams
|
||||
url(r'^api/v1/users/(?P<pk>[0-9]+)/permissions/$', views_UsersPermissionsList),
|
||||
url(r'^api/v1/teams/(?P<pk>[0-9]+)/permissions/$', views_TeamsPermissionsList),
|
||||
url(r'^api/v1/permissions/(?P<pk>[0-9]+)/$', views_PermissionsDetail),
|
||||
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user