Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.1.2 on 2023-04-18 18:29

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("users", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="historicaluser",
name="disabled_at",
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name="user",
name="disabled_at",
field=models.DateTimeField(blank=True, null=True),
),
]
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class User(AbstractUser, TimeStampedModel):
"Unselect this instead of deleting accounts."
),
)

disabled_at = models.DateTimeField(null=True, blank=True)
objects = UserManager()
history = HistoricalRecords(excluded_fields=["password"])

Expand All @@ -89,6 +89,12 @@ class Meta:
def activate(self):
self.activated_at = timezone.now()
self.is_active = True
self.disabled_at = None
self.save()

def deactivate(self):
self.is_active = False
self.disabled_at = timezone.now()
self.save()

def can_access_role(self, role):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,16 @@ def test_user_activate():

user.activate()

assert user.is_active
assert user.activated_at
assert user.is_active == True
assert user.activated_at is not None
assert user.disabled_at is None

@pytest.mark.django_db
def test_user_deactivate():
user = UserFactory()

user.activate()
user.deactivate()

assert user.is_active is False
assert user.disabled_at is not None
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
)
from .permissions import IsAdmin, IsUserOrAdmin
from .models import HistoricalUser
from .models import User
from django.utils import timezone


class UserViewSet(DjoserUserViewSet):
Expand All @@ -44,17 +46,7 @@ class UserViewSet(DjoserUserViewSet):
}
search_fields = ["email", "last_name", "first_name"]

def make_role_read_only(self, serializer):
serializer.validated_data.pop('role', None)

def perform_update(self, serializer):
user_being_accessed = self.get_object()
user_making_request = self.request.user
is_same_user = (user_being_accessed == user_making_request)

if is_same_user or user_being_accessed.role == "USER" or user_being_accessed.role == "EDITOR":
self.make_role_read_only(serializer)

serializer.save()

@action(
Expand Down Expand Up @@ -94,7 +86,6 @@ def cancel_change_email_request(self, request, *args, **kwargs):
serialized_user = UserSerializer(user, context={"request": request})
return Response(data=serialized_user.data, status=status.HTTP_200_OK)


@action(
detail=False,
methods=["post"],
Expand Down Expand Up @@ -193,14 +184,45 @@ def invitation(self, request):

user = serializer.save(is_active=False)

# Send invitation email
context = {"user": user}
to = [user.email]
serialized_email = serialize_email(settings.EMAIL.activation(self.request, context), to)
send_email_later.send(serialized_email)

return Response(status=status.HTTP_204_NO_CONTENT)

@action(
detail=True,
methods=["post"],
serializer_class=NullSerializer,
permission_classes=[IsAdmin],
)
def disable(self, request, id):
try:
user = User.objects.get(id=id)
except User.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

user.deactivate()
serialized_user = UserSerializer(user, context={"request": request})
return Response(data=serialized_user.data, status=status.HTTP_200_OK)

@action(
detail=True,
methods=["post"],
serializer_class=NullSerializer,
permission_classes=[IsAdmin],
)
def enable(self, request, id):
try:
user = User.objects.get(id=id)
except User.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

user = User.objects.get(id=id)
user.activate()
serialized_user = UserSerializer(user, context={"request": request})
return Response(data=serialized_user.data, status=status.HTTP_200_OK)

class UserHistoryViewSet(
NestedViewSetMixin, viewsets.GenericViewSet, mixins.ListModelMixin
Expand Down