Skip to content

Commit

Permalink
Merge pull request #157 from CentreForDigitalHumanities/feature/delet…
Browse files Browse the repository at this point in the history
…e-user

Feature: delete user
  • Loading branch information
XanderVertegaal authored Nov 26, 2024
2 parents 8fc4913 + f503dff commit 086fe2a
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 15 deletions.
3 changes: 3 additions & 0 deletions backend/lettercraft/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
"dj_rest_auth.registration",
"allauth",
"allauth.account",
# Required for deleting accounts, but not actually used,
# cf. https://github.com/iMerica/dj-rest-auth/pull/110.
"allauth.socialaccount",
"revproxy",
"core",
"case_study",
Expand Down
11 changes: 10 additions & 1 deletion backend/user/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from allauth.account.models import EmailConfirmationHMAC
from django.http import HttpRequest, HttpResponseRedirect
from django.contrib.auth import logout
from rest_framework.exceptions import APIException
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.status import HTTP_404_NOT_FOUND
from rest_framework.status import HTTP_404_NOT_FOUND, HTTP_200_OK, HTTP_401_UNAUTHORIZED
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
Expand Down Expand Up @@ -43,10 +44,18 @@ def post(self, request):
except Exception as e:
raise APIException(e)


class DeleteUser(APIView):
permission_classes = [IsAuthenticated]

def delete(self, request: HttpRequest):
user = request.user
if user.is_anonymous:
return Response({"detail": "not authenticated"}, status=HTTP_401_UNAUTHORIZED)
logout(request)
user.delete()
return Response({"detail": "ok"}, status=HTTP_200_OK)


class UserViewSet(ModelViewSet):
permission_classes = [IsAuthenticated]
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/app/services/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ export class AuthService {

public currentUser$ = merge(
this.login.subject.pipe(map(() => undefined)),
this.logout.result$.pipe(map(() => null)),
this.logout.success$.pipe(map(() => null)),
this.deleteUser.success$.pipe(map(() => null)),
this.backendUser$,
this.updateSettingsUser$
).pipe(
Expand Down
40 changes: 27 additions & 13 deletions frontend/src/app/user/user-settings/user-settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
import { ToastService } from "@services/toast.service";
import { usernameValidators } from "../validation";
import { Apollo } from "apollo-angular";
import { Router } from "@angular/router";
import { ModalService } from "@services/modal.service";

type UserSettingsForm = {
[key in keyof UserSettings]: FormControl<UserSettings[key]>;
Expand All @@ -35,10 +37,7 @@ export class UserSettingsComponent implements OnInit {
}),
username: new FormControl<string>("", {
nonNullable: true,
validators: [
Validators.required,
...usernameValidators
],
validators: [Validators.required, ...usernameValidators],
}),
firstName: new FormControl<string>("", {
nonNullable: true,
Expand All @@ -56,17 +55,19 @@ export class UserSettingsComponent implements OnInit {
public deleteUserLoading$ = this.authService.deleteUser.loading$;

constructor(
private router: Router,
private authService: AuthService,
private toastService: ToastService,
private modalService: ModalService,
private destroyRef: DestroyRef,
private apollo: Apollo,
private apollo: Apollo
) {}

ngOnInit(): void {
this.authService.currentUser$
.pipe(
filter((user) => !!user),
takeUntilDestroyed(this.destroyRef),
takeUntilDestroyed(this.destroyRef)
)
.subscribe((user) => {
if (!user) {
Expand All @@ -85,7 +86,6 @@ export class UserSettingsComponent implements OnInit {
});
});


this.authService.deleteUser.error$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => this.toastService.show({
Expand All @@ -96,11 +96,14 @@ export class UserSettingsComponent implements OnInit {

this.authService.deleteUser.success$
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(() => this.toastService.show({
header: "Account deleted",
body: "Your account has been successfully deleted.",
type: "success",
}));
.subscribe(() => {
this.toastService.show({
header: "Account deleted",
body: "Your account has been successfully deleted.",
type: "success",
});
this.router.navigate(["/"]);
});

this.authService.updateSettings.error$
.pipe(takeUntilDestroyed(this.destroyRef))
Expand All @@ -118,7 +121,18 @@ export class UserSettingsComponent implements OnInit {
}

public deleteAccount(): void {
this.authService.deleteUser.subject.next();
this.modalService
.openConfirmationModal({
title: "Delete account",
message:
"Are you sure you want to delete your account? This action cannot be undone.",
})
.then(() => {
this.authService.deleteUser.subject.next();
})
.catch(() => {
// Do nothing on cancel / dismissal.
});
}

public submit(): void {
Expand Down

0 comments on commit 086fe2a

Please sign in to comment.