|
1 | 1 | """This file and its contents are licensed under the Apache License 2.0. Please see the included NOTICE for copyright information and LICENSE for a copy of the license. |
2 | 2 | """ |
3 | 3 | import logging |
| 4 | +from typing import Any |
4 | 5 |
|
5 | 6 | from core.feature_flags import flag_set |
6 | 7 | from core.middleware import enforce_csrf_checks |
| 8 | +from core.permissions import ViewClassPermission, all_permissions |
7 | 9 | from core.utils.common import load_func |
8 | 10 | from django.conf import settings |
9 | 11 | from django.contrib import auth |
10 | 12 | from django.contrib.auth.decorators import login_required |
11 | 13 | from django.core.exceptions import PermissionDenied |
| 14 | +from django.http import Http404 |
12 | 15 | from django.shortcuts import redirect, render, reverse |
13 | 16 | from django.utils.http import is_safe_url |
14 | 17 | from organizations.forms import OrganizationSignupForm |
15 | 18 | from organizations.models import Organization |
| 19 | +from rest_framework import generics, status |
16 | 20 | from rest_framework.authtoken.models import Token |
| 21 | +from rest_framework.exceptions import MethodNotAllowed |
| 22 | +from rest_framework.permissions import IsAuthenticated |
| 23 | +from rest_framework.request import Request |
| 24 | +from rest_framework.response import Response |
17 | 25 | from users import forms |
18 | 26 | from users.functions import login, proceed_registration |
| 27 | +from users.models import User |
| 28 | +from users.serializers import UserSerializer |
| 29 | + |
| 30 | +HasObjectPermission = load_func(settings.USER_PERM) |
19 | 31 |
|
20 | 32 | logger = logging.getLogger() |
21 | 33 |
|
@@ -149,3 +161,32 @@ def user_account(request): |
149 | 161 | 'users/user_account.html', |
150 | 162 | {'settings': settings, 'user': user, 'user_profile_form': form, 'token': token}, |
151 | 163 | ) |
| 164 | + |
| 165 | + |
| 166 | +class UserSoftDeleteView(generics.RetrieveDestroyAPIView): |
| 167 | + permission_required = ViewClassPermission( |
| 168 | + DELETE=all_permissions.organizations_change, |
| 169 | + ) |
| 170 | + queryset = User.objects.all() |
| 171 | + serializer_class = UserSerializer |
| 172 | + permission_classes = (IsAuthenticated, HasObjectPermission) |
| 173 | + |
| 174 | + def get_object(self) -> User: |
| 175 | + pk = self.kwargs[self.lookup_field] |
| 176 | + # only fetch & delete user if they are in the same organization as the calling user |
| 177 | + try: |
| 178 | + user = self.queryset.filter(active_organization=self.request.user.active_organization).get(pk=pk) |
| 179 | + except User.DoesNotExist: |
| 180 | + raise Http404('User could not be found in organization') |
| 181 | + |
| 182 | + return user |
| 183 | + |
| 184 | + def destroy(self, request: Request, *args: Any, **kwargs: Any) -> Response: |
| 185 | + user = self.get_object() |
| 186 | + |
| 187 | + self.check_object_permissions(self.request, user) |
| 188 | + if self.kwargs[self.lookup_field] == self.request.user.pk: |
| 189 | + raise MethodNotAllowed('User cannot delete self') |
| 190 | + |
| 191 | + user.soft_delete() |
| 192 | + return Response(status=status.HTTP_204_NO_CONTENT) |
0 commit comments