feat(notifications): notify membership access changes
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from core.serializers.base import BaseModelSerializer
|
||||
from apps.workspaces.models import Workspace, WorkspaceMembership
|
||||
from core.serializers.mini import UserMiniSerializer
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.notifications.membership_events import notify_workspace_membership_added
|
||||
from apps.users.models import User
|
||||
from core.serializers.base import BaseModelSerializer
|
||||
from apps.workspaces.models import Workspace, WorkspaceMembership
|
||||
from core.serializers.mini import UserMiniSerializer
|
||||
|
||||
|
||||
class WorkspaceMemberInputSerializer(serializers.Serializer):
|
||||
@@ -34,26 +36,41 @@ class WorkspaceSerializer(BaseModelSerializer):
|
||||
).first()
|
||||
return getattr(membership, "role", None)
|
||||
|
||||
def create(self, validated_data):
|
||||
members_data = validated_data.pop('members', [])
|
||||
|
||||
workspace = super().create(validated_data)
|
||||
|
||||
memberships_to_create = []
|
||||
for member in members_data:
|
||||
memberships_to_create.append(
|
||||
def create(self, validated_data):
|
||||
members_data = validated_data.pop('members', [])
|
||||
|
||||
workspace = super().create(validated_data)
|
||||
|
||||
memberships_to_create = []
|
||||
for member in members_data:
|
||||
memberships_to_create.append(
|
||||
WorkspaceMembership(
|
||||
workspace=workspace,
|
||||
user_id=member['user_id'],
|
||||
role=member['role'],
|
||||
is_active=True
|
||||
)
|
||||
)
|
||||
|
||||
if memberships_to_create:
|
||||
WorkspaceMembership.objects.bulk_create(memberships_to_create)
|
||||
|
||||
return workspace
|
||||
)
|
||||
|
||||
if memberships_to_create:
|
||||
WorkspaceMembership.objects.bulk_create(memberships_to_create)
|
||||
request = self.context.get("request")
|
||||
actor = getattr(request, "user", None)
|
||||
if actor and actor.is_authenticated:
|
||||
users_by_id = User.objects.in_bulk(
|
||||
[member["user_id"] for member in members_data]
|
||||
)
|
||||
for member in members_data:
|
||||
recipient = users_by_id.get(member["user_id"])
|
||||
if recipient:
|
||||
notify_workspace_membership_added(
|
||||
actor=actor,
|
||||
recipient=recipient,
|
||||
workspace=workspace,
|
||||
role=member["role"],
|
||||
)
|
||||
|
||||
return workspace
|
||||
|
||||
|
||||
class WorkspaceMembershipSerializer(BaseModelSerializer):
|
||||
|
||||
@@ -5,11 +5,17 @@ from rest_framework.response import Response
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from apps.workspaces.api.permissions import IsWorkspaceOwner, IsWorkspaceAdmin
|
||||
from apps.workspaces.api.serializers import WorkspaceMembershipSerializer, WorkspaceSerializer
|
||||
from apps.workspaces.api.filters import WorkspaceFilter, WorkspaceMembershipFilter
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from apps.notifications.membership_events import (
|
||||
notify_workspace_membership_added,
|
||||
notify_workspace_membership_deactivated,
|
||||
notify_workspace_membership_removed,
|
||||
notify_workspace_membership_role_changed,
|
||||
)
|
||||
from apps.workspaces.api.permissions import IsWorkspaceOwner, IsWorkspaceAdmin
|
||||
from apps.workspaces.api.serializers import WorkspaceMembershipSerializer, WorkspaceSerializer
|
||||
from apps.workspaces.api.filters import WorkspaceFilter, WorkspaceMembershipFilter
|
||||
from apps.workspaces.models import Workspace, WorkspaceMembership
|
||||
from core.paginations.limit_offset import CustomLimitOffsetPagination
|
||||
|
||||
@@ -79,7 +85,7 @@ class WorkspaceMembershipViewSet(ModelViewSet):
|
||||
|
||||
return [IsAuthenticated()]
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""
|
||||
Overridden to check permissions manually.
|
||||
Because the membership object doesn't exist yet, standard DRF object-level
|
||||
@@ -101,4 +107,75 @@ class WorkspaceMembershipViewSet(ModelViewSet):
|
||||
status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
|
||||
return super().create(request, *args, **kwargs)
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
membership = serializer.save()
|
||||
notify_workspace_membership_added(
|
||||
actor=request.user,
|
||||
recipient=membership.user,
|
||||
workspace=membership.workspace,
|
||||
role=membership.role,
|
||||
)
|
||||
return Response(
|
||||
WorkspaceMembershipSerializer(membership, context=self.get_serializer_context()).data,
|
||||
status=status.HTTP_201_CREATED,
|
||||
)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
partial = kwargs.pop("partial", False)
|
||||
membership = self.get_object()
|
||||
previous_role = membership.role
|
||||
previous_is_active = membership.is_active
|
||||
|
||||
serializer = self.get_serializer(membership, data=request.data, partial=partial)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
updated_membership = serializer.save()
|
||||
|
||||
if not previous_is_active and updated_membership.is_active:
|
||||
notify_workspace_membership_added(
|
||||
actor=request.user,
|
||||
recipient=updated_membership.user,
|
||||
workspace=updated_membership.workspace,
|
||||
role=updated_membership.role,
|
||||
)
|
||||
elif previous_is_active and not updated_membership.is_active:
|
||||
notify_workspace_membership_deactivated(
|
||||
actor=request.user,
|
||||
recipient=updated_membership.user,
|
||||
workspace=updated_membership.workspace,
|
||||
role=previous_role,
|
||||
)
|
||||
elif previous_role != updated_membership.role:
|
||||
notify_workspace_membership_role_changed(
|
||||
actor=request.user,
|
||||
recipient=updated_membership.user,
|
||||
workspace=updated_membership.workspace,
|
||||
previous_role=previous_role,
|
||||
new_role=updated_membership.role,
|
||||
)
|
||||
|
||||
return Response(
|
||||
WorkspaceMembershipSerializer(
|
||||
updated_membership,
|
||||
context=self.get_serializer_context(),
|
||||
).data,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
def partial_update(self, request, *args, **kwargs):
|
||||
kwargs["partial"] = True
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
membership = self.get_object()
|
||||
recipient = membership.user
|
||||
workspace = membership.workspace
|
||||
role = membership.role
|
||||
membership.delete()
|
||||
notify_workspace_membership_removed(
|
||||
actor=request.user,
|
||||
recipient=recipient,
|
||||
workspace=workspace,
|
||||
role=role,
|
||||
)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
Reference in New Issue
Block a user