diff --git a/lib/main/tests/projects.py b/lib/main/tests/projects.py index dadf9e1f89..9884e727b6 100644 --- a/lib/main/tests/projects.py +++ b/lib/main/tests/projects.py @@ -216,24 +216,43 @@ class ProjectsTest(BaseTest): # ===================================================================== # TEAMS USER MEMBERSHIP - team_users = '/api/v1/teams/1/users/' - - # can add users to teams - print Team.objects.all() - raise Exception("STOP") - - # can remove users from teams + team = Team.objects.filter(organization__pk = 2)[0] + team_users = '/api/v1/teams/%s/users/' % (team.pk) + for x in team.users.all(): + team.users.remove(x) + team.save() # can list uses on teams + self.get(team_users, expect=401) + self.get(team_users, expect=401, auth=self.get_invalid_credentials()) + self.get(team_users, expect=403, auth=self.get_nobody_credentials()) + self.get(team_users, expect=403, auth=self.get_other_credentials()) + self.get(team_users, expect=200, auth=self.get_normal_credentials()) + self.get(team_users, expect=200, auth=self.get_super_credentials()) - # from a user, can see what teams they are on + # can add users to teams + all_users = self.get('/api/v1/users/', expect=200, auth=self.get_super_credentials()) + for x in all_users['results']: + self.post(team_users, data=x, expect=403, auth=self.get_nobody_credentials()) + self.post(team_users, data=x, expect=204, auth=self.get_normal_credentials()) + + self.assertEqual(Team.objects.get(pk=team.pk).users.count(), 4) + + # can remove users from teams + for x in all_users['results']: + y = dict(id=x['id'], disassociate=1) + self.post(team_users, data=y, expect=403, auth=self.get_nobody_credentials()) + self.post(team_users, data=y, expect=204, auth=self.get_normal_credentials()) + + self.assertEquals(Team.objects.get(pk=team.pk).users.count(), 0) + + # from a user, can see what teams they are on (related resource) + print "TEAMS?" + print User.objects.get(username = 'other').teams.all() # from a user, can see what projects they can see based on team association # though this resource doesn't do anything else - # ===================================================================== - # ADDING ORGANIZATIONS TO TEAMS - # ===================================================================== # CREDENTIALS diff --git a/lib/main/views.py b/lib/main/views.py index 06046d4913..e7b635ee42 100644 --- a/lib/main/views.py +++ b/lib/main/views.py @@ -192,6 +192,28 @@ class TeamsDetail(BaseDetail): serializer_class = TeamSerializer permission_classes = (CustomRbac,) +class TeamsUsersList(BaseSubList): + + model = User + serializer_class = UserSerializer + permission_classes = (CustomRbac,) + parent_model = Team + relationship = 'users' + postable = True + inject_primary_key_on_post_as = 'team' + severable = True + + def _get_queryset(self): + # FIXME: audit all BaseSubLists to check for permissions on the original object too + 'team members can see the whole team, as can org admins or superusers' + team = Team.objects.get(pk=self.kwargs['pk']) + base = team.users.all() + if self.request.user.is_superuser or self.request.user in team.organization.admins.all(): + return base + if self.request.user in team.users.all(): + return base + raise PermissionDenied() + class ProjectsList(BaseList): model = Project diff --git a/lib/urls.py b/lib/urls.py index 1d238cc53a..a8d067601d 100644 --- a/lib/urls.py +++ b/lib/urls.py @@ -47,6 +47,7 @@ views_ProjectsOrganizationsList = views.ProjectsOrganizationsList.as_view() # team service views_TeamsList = views.TeamsList.as_view() views_TeamsDetail = views.TeamsDetail.as_view() +views_TeamsUsersList = views.TeamsUsersList.as_view() # inventory service views_InventoryList = views.InventoryList.as_view() @@ -112,6 +113,7 @@ urlpatterns = patterns('', # api/v1/teams/ url(r'^api/v1/teams/$', views_TeamsList), url(r'^api/v1/teams/(?P[0-9]+)/$', views_TeamsDetail), + url(r'^api/v1/teams/(?P[0-9]+)/users/$', views_TeamsUsersList), # api/v1/teams/N/ # api/v1/teams/N/users/