Browse Source

Added members viewset to organizations
Add users is incomplete

David Burke 4 years ago
parent
commit
9e819e9030
4 changed files with 61 additions and 6 deletions
  1. 2 0
      organizations_ext/urls.py
  2. 5 3
      users/serializers.py
  3. 32 1
      users/test.py
  4. 22 2
      users/views.py

+ 2 - 0
organizations_ext/urls.py

@@ -2,6 +2,7 @@ from django.urls import path, include
 from rest_framework_nested import routers
 from issues.views import IssueViewSet
 from teams.views import NestedTeamViewSet
+from users.views import UserViewSet
 from glitchtip.routers import BulkSimpleRouter
 from .views import OrganizationViewSet
 
@@ -15,6 +16,7 @@ organizations_router.register(r"issues", IssueViewSet, basename="organization-is
 organizations_router.register(
     r"teams", NestedTeamViewSet, basename="organization-teams"
 )
+organizations_router.register(r"members", UserViewSet, basename="organization-members")
 
 urlpatterns = [
     path("", include(router.urls)),

+ 5 - 3
users/serializers.py

@@ -5,14 +5,16 @@ from .models import User
 
 
 class UserSerializer(serializers.ModelSerializer):
-    lastLogin = serializers.DateTimeField(source="last_login")
+    lastLogin = serializers.DateTimeField(source="last_login", read_only=True)
     isSuperuser = serializers.BooleanField(source="is_superuser")
     identities = SocialAccountSerializer(
         source="socialaccount_set", many=True, read_only=True
     )
     isActive = serializers.BooleanField(source="is_active")
-    dateJoined = serializers.DateTimeField(source="created")
-    hasPasswordAuth = serializers.BooleanField(source="has_usable_password")
+    dateJoined = serializers.DateTimeField(source="created", read_only=True)
+    hasPasswordAuth = serializers.BooleanField(
+        source="has_usable_password", read_only=True
+    )
 
     class Meta:
         model = User

+ 32 - 1
users/test.py

@@ -3,7 +3,7 @@ from rest_framework.test import APITestCase
 from model_bakery import baker
 from glitchtip import test_utils  # pylint: disable=unused-import
 from organizations_ext.models import OrganizationUserRole
-from .models import UserProjectAlert
+from .models import UserProjectAlert, User
 
 
 class OrganizationsAPITestCase(APITestCase):
@@ -52,6 +52,37 @@ class UsersTestCase(APITestCase):
         res = self.client.get(url)
         self.assertContains(res, self.user.email)
 
+    def test_organization_members_list(self):
+        other_user = baker.make("users.user")
+        other_organization = baker.make("organizations_ext.Organization")
+        other_organization.add_user(other_user, OrganizationUserRole.ADMIN)
+
+        user2 = baker.make("users.User")
+        self.organization.add_user(user2, OrganizationUserRole.MEMBER)
+        url = reverse("organization-members-list", args=[self.organization.slug])
+        res = self.client.get(url)
+        self.assertContains(res, user2.email)
+        self.assertNotContains(res, other_user.email)
+
+        # Can't view members of groups you don't belong to
+        url = reverse("organization-members-list", args=[other_organization.slug])
+        res = self.client.get(url)
+        self.assertNotContains(res, other_user.email)
+
+    def test_organization_members_create(self):
+        url = reverse("organization-members-list", args=[self.organization.slug])
+        data = {
+            "email": "new@example.com",
+            "role": "member",
+            "teams": [],
+            "user": "new@example.com",
+        }
+        res = self.client.post(url, data)
+        self.assertEqual(res.status_code, 201)
+        # TODO pending functionality
+        # self.assertTrue(res.data["pending"])
+        User.objects.get(pk=res.data["id"])
+
     def test_notifications_retrieve(self):
         url = reverse("user-detail", args=["me"]) + "notifications/"
         res = self.client.get(url)

+ 22 - 2
users/views.py

@@ -2,16 +2,26 @@ from rest_framework import status, viewsets
 from rest_framework.decorators import action
 from rest_framework.response import Response
 from rest_framework.exceptions import ValidationError
+from organizations_ext.models import Organization
 from .models import User, UserProjectAlert
 from .serializers import UserSerializer, UserNotificationsSerializer
 
 
-class UserViewSet(viewsets.ReadOnlyModelViewSet):
+class UserViewSet(viewsets.ModelViewSet):
     queryset = User.objects.all()
     serializer_class = UserSerializer
 
     def get_queryset(self):
-        return super().get_queryset().filter(id=self.request.user.id)
+        queryset = super().get_queryset()
+        organization_slug = self.kwargs.get("organization_slug")
+        if organization_slug:
+            queryset = queryset.filter(
+                organizations_ext_organization__slug=organization_slug,
+                organizations_ext_organization__users=self.request.user,
+            )
+        else:
+            queryset = queryset.filter(id=self.request.user.id)
+        return queryset
 
     def get_object(self):
         pk = self.kwargs.get("pk")
@@ -19,6 +29,16 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
             return self.request.user
         return super().get_object()
 
+    def perform_create(self, serializer):
+        organization_slug = self.kwargs.get("organization_slug")
+        try:
+            organization = Organization.objects.get(slug=organization_slug)
+        except Organization.DoesNotExist:
+            raise ValidationError("Organization does not exist")
+        # TODO deal with organization and users who aren't set up yet
+        user = serializer.save()
+        return user
+
     @action(detail=True, methods=["get", "post", "put"])
     def notifications(self, request, pk=None):
         user = self.get_object()