Browse Source

Create org users api

David Burke 4 years ago
parent
commit
a6ebe5f79e

+ 1 - 3
glitchtip/settings.py

@@ -306,9 +306,7 @@ ACCOUNT_USER_MODEL_USERNAME_FIELD = None
 OLD_PASSWORD_FIELD_ENABLED = True
 LOGOUT_ON_PASSWORD_CHANGE = False
 
-REST_AUTH_SERIALIZERS = {
-    "USER_DETAILS_SERIALIZER": "users.serializers.UserDetailsSerializer"
-}
+REST_AUTH_SERIALIZERS = {"USER_DETAILS_SERIALIZER": "users.serializers.UserSerializer"}
 
 # Show/Hide social auth. All or nothing at this time.
 ENABLE_SOCIAL_AUTH = env.bool("ENABLE_SOCIAL_AUTH", False)

+ 17 - 5
organizations_ext/serializers/serializers.py

@@ -1,14 +1,12 @@
+from rest_framework import serializers
 from projects.serializers.base_serializers import ProjectReferenceWithMemberSerializer
+from users.serializers import UserSerializer
 from .base_serializers import OrganizationReferenceSerializer
+from ..models import OrganizationUser
 
 
 class OrganizationSerializer(OrganizationReferenceSerializer):
     pass
-    # def create(self, validated_data):
-    #     user = self.context["request"].user
-    #     return create_organization(
-    #         user, validated_data["name"], validated_data.get("slug"),
-    #     )
 
 
 class OrganizationDetailSerializer(OrganizationSerializer):
@@ -16,3 +14,17 @@ class OrganizationDetailSerializer(OrganizationSerializer):
 
     class Meta(OrganizationSerializer.Meta):
         fields = OrganizationSerializer.Meta.fields + ("projects",)
+
+
+class OrganizationUserSerializer(serializers.ModelSerializer):
+    user = UserSerializer()
+    role = serializers.SerializerMethodField()
+    roleName = serializers.CharField(source="get_role_display")
+    dateCreated = serializers.DateTimeField(source="created")
+
+    class Meta:
+        model = OrganizationUser
+        fields = ("role", "id", "user", "roleName", "dateCreated")
+
+    def get_role(self, obj):
+        return obj.get_role_display().lower()

+ 20 - 0
organizations_ext/tests/tests.py

@@ -65,3 +65,23 @@ class OrganizationsAPITestCase(APITestCase):
         self.assertEqual(
             OrganizationUser.objects.filter(organization__name=data["name"]).count(), 1
         )
+
+
+class OrganizationUsersAPITestCase(APITestCase):
+    def setUp(self):
+        self.user = baker.make("users.user")
+        self.organization = baker.make("organizations_ext.Organization")
+        self.organization.add_user(self.user)
+        self.client.force_login(self.user)
+        self.users_url = reverse(
+            "organization-users-list",
+            kwargs={"organization_slug": self.organization.slug},
+        )
+        self.members_url = reverse(
+            "organization-members-list",
+            kwargs={"organization_slug": self.organization.slug},
+        )
+
+    def test_organization_users_list(self):
+        res = self.client.get(self.users_url)
+        self.assertContains(res, self.user.email)

+ 11 - 3
organizations_ext/urls.py

@@ -2,9 +2,12 @@ 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
+from .views import (
+    OrganizationViewSet,
+    OrganizationUserViewSet,
+    OrganizationMemberViewSet,
+)
 
 router = BulkSimpleRouter()
 router.register(r"organizations", OrganizationViewSet)
@@ -16,7 +19,12 @@ 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")
+organizations_router.register(
+    r"members", OrganizationMemberViewSet, basename="organization-members"
+)
+organizations_router.register(
+    r"users", OrganizationUserViewSet, basename="organization-users"
+)
 
 urlpatterns = [
     path("", include(router.urls)),

+ 25 - 1
organizations_ext/views.py

@@ -1,8 +1,9 @@
 from rest_framework import viewsets
-from .models import Organization, OrganizationUserRole
+from .models import Organization, OrganizationUserRole, OrganizationUser
 from .serializers.serializers import (
     OrganizationSerializer,
     OrganizationDetailSerializer,
+    OrganizationUserSerializer,
 )
 
 
@@ -27,3 +28,26 @@ class OrganizationViewSet(viewsets.ModelViewSet):
         """ Create organization with current user as owner """
         organization = serializer.save()
         organization.add_user(self.request.user, role=OrganizationUserRole.OWNER)
+
+
+class OrganizationMemberViewSet(viewsets.ReadOnlyModelViewSet):
+    """ All Organization Users including pending """
+
+    queryset = OrganizationUser.objects.all()
+    serializer_class = OrganizationUserSerializer
+
+    def get_queryset(self):
+        if not self.request.user.is_authenticated:
+            return self.queryset.none()
+        queryset = self.queryset.filter(organization__users=self.request.user)
+        organization_slug = self.kwargs.get("organization_slug")
+        if organization_slug:
+            queryset = queryset.filter(organization__slug=organization_slug)
+        return queryset
+
+
+class OrganizationUserViewSet(OrganizationMemberViewSet):
+    """ Organization users - excluding pending invites """
+
+    # def get_queryset(self):
+    # TODO add pending filter

+ 2 - 4
users/admin.py

@@ -6,12 +6,10 @@ from .models import User, UserProjectAlert
 
 class UserAdmin(BaseUserAdmin):
     ordering = ("email",)
+    list_display = ("email", "name")
     fieldsets = (
         (None, {"fields": ("email", "password")}),
-        (
-            _("Personal info"),
-            {"fields": ("first_name", "last_name", "subscribe_by_default")},
-        ),
+        (_("Personal info"), {"fields": ("name", "subscribe_by_default")},),
         (
             _("Permissions"),
             {

+ 26 - 0
users/migrations/0005_auto_20200612_2011.py

@@ -0,0 +1,26 @@
+# Generated by Django 3.0.7 on 2020-06-12 20:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('users', '0004_auto_20200429_2348'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='user',
+            name='first_name',
+        ),
+        migrations.RemoveField(
+            model_name='user',
+            name='last_name',
+        ),
+        migrations.AddField(
+            model_name='user',
+            name='name',
+            field=models.CharField(blank=True, max_length=255, verbose_name='name'),
+        ),
+    ]

+ 1 - 2
users/models.py

@@ -39,8 +39,7 @@ class UserManager(BaseUserManager):
 
 class User(AbstractBaseUser, PermissionsMixin):
     email = models.EmailField(unique=True)
-    first_name = models.CharField(_("first name"), max_length=30, blank=True)
-    last_name = models.CharField(_("last name"), max_length=150, blank=True)
+    name = models.CharField(_("name"), max_length=255, blank=True)
     is_staff = models.BooleanField(
         _("staff status"),
         default=False,

+ 12 - 12
users/serializers.py

@@ -79,6 +79,7 @@ class UserSerializer(serializers.ModelSerializer):
             "identities",
             "id",
             "isActive",
+            "name",
             "dateJoined",
             "hasPasswordAuth",
             "email",
@@ -93,17 +94,16 @@ class UserNotificationsSerializer(serializers.ModelSerializer):
         fields = ("subscribeByDefault",)
 
 
-class UserDetailsSerializer(BaseUserDetailsSerializer):
-    """ Extended UserDetailsSerializer with social account set data """
+# class UserDetailsSerializer(BaseUserDetailsSerializer):
+#     """ Extended UserDetailsSerializer with social account set data """
 
-    socialaccount_set = SocialAccountSerializer(many=True, read_only=True)
+#     socialaccount_set = SocialAccountSerializer(many=True, read_only=True)
 
-    class Meta(BaseUserDetailsSerializer.Meta):
-        fields = (
-            "pk",
-            "email",
-            "first_name",
-            "last_name",
-            "socialaccount_set",
-        )
-        read_only_fields = ("email",)
+#     class Meta(BaseUserDetailsSerializer.Meta):
+#         fields = (
+#             "pk",
+#             "email",
+#             "name",
+#             "socialaccount_set",
+#         )
+#         read_only_fields = ("email",)

+ 14 - 27
users/test.py

@@ -4,7 +4,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, User
+from .models import UserProjectAlert
 
 
 class OrganizationsAPITestCase(APITestCase):
@@ -19,19 +19,6 @@ class OrganizationsAPITestCase(APITestCase):
         self.assertContains(res, "key", status_code=201)
 
 
-class UserDetailsTestCase(APITestCase):
-    def test_user_details(self):
-        """ User details should have email and associated social account providers """
-        user = baker.make("users.user")
-        socialaccount = baker.make("socialaccount.SocialAccount", user=user)
-        self.client.force_login(user)
-        url = reverse("rest_user_details")
-
-        res = self.client.get(url)
-        self.assertContains(res, user.email)
-        self.assertContains(res, socialaccount.provider)
-
-
 class UsersTestCase(APITestCase):
     def setUp(self):
         self.user = baker.make("users.user")
@@ -70,19 +57,19 @@ class UsersTestCase(APITestCase):
         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_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_emails_retrieve(self):
         email_address = baker.make("account.EmailAddress", user=self.user)