add(settings): account deletion

This commit is contained in:
AdrienLSH 2024-03-20 10:27:02 +01:00
parent 833f008a2a
commit 19b4730f19
4 changed files with 73 additions and 11 deletions

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-19 13:37+0100\n" "POT-Creation-Date: 2024-03-20 10:25+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -30,6 +30,10 @@ msgstr "Le mot de passe ne correspond pas."
msgid "You dont have permission for this user." msgid "You dont have permission for this user."
msgstr "Vous n'avez pas de permissions pour cet utilisateur." msgstr "Vous n'avez pas de permissions pour cet utilisateur."
#: views/delete.py:19
msgid "Password incorrect."
msgstr "Mot de passe incorrect."
#: views/login.py:23 #: views/login.py:23
msgid "Invalid username or password." msgid "Invalid username or password."
msgstr "Nom d'utilisateur ou mot de passe incorect." msgstr "Nom d'utilisateur ou mot de passe incorect."

View File

@ -4,6 +4,7 @@ from rest_framework.response import Response
from django.contrib.auth import logout from django.contrib.auth import logout
from django.http import HttpRequest from django.http import HttpRequest
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from django.utils.translation import gettext as _
class DeleteView(APIView): class DeleteView(APIView):
@ -15,7 +16,7 @@ class DeleteView(APIView):
password: str = data["password"] password: str = data["password"]
if (request.user.check_password(password) is False): if (request.user.check_password(password) is False):
return Response({"password": ["Password incorrect."]}, return Response({"password": _("Password incorrect.")},
status.HTTP_401_UNAUTHORIZED) status.HTTP_401_UNAUTHORIZED)
request.user.delete() request.user.delete()
logout(request) logout(request)

View File

@ -34,17 +34,14 @@ class Account
*/ */
async delete(password) async delete(password)
{ {
let response = await this.client._delete("/api/accounts/delete", {password: password}); const response = await this.client._delete("/api/accounts/delete", {password: password});
let response_data = await response.json();
if (response.status === 403) if (response.ok) {
{
this.client._update_logged(false); this.client._update_logged(false);
return null; return null;
} }
if (response_data == "user deleted")
this.client._update_logged(false); return await response.json();
return response_data;
} }
/** /**

View File

@ -1,4 +1,4 @@
import {client, lang} from '../index.js'; import {client, lang, navigateTo} from '../index.js';
import {clearElements, fill_errors} from '../utils/formUtils.js' import {clearElements, fill_errors} from '../utils/formUtils.js'
import AbstractAuthenticatedView from './abstracts/AbstractAuthenticatedView.js'; import AbstractAuthenticatedView from './abstracts/AbstractAuthenticatedView.js';
@ -15,6 +15,20 @@ export default class extends AbstractAuthenticatedView
this.avatarInit(); this.avatarInit();
this.usernameInit(); this.usernameInit();
this.passwordInit(); this.passwordInit();
this.deleteInit();
}
deleteInit() {
const deleteInput = document.getElementById('deleteInput');
document.getElementById('deleteModal').addEventListener('shown.bs.modal', _ => {
deleteInput.focus();
});
deleteInput.onkeydown = e => {
if (e.key === 'Enter')
this.deleteAccount();
}
document.getElementById('deleteButton').onclick = this.deleteAccount;
} }
passwordInit() { passwordInit() {
@ -206,6 +220,34 @@ export default class extends AbstractAuthenticatedView
this.displayAvatar(); this.displayAvatar();
} }
async deleteAccount() {
const passwordInput = document.getElementById('deleteInput');
const password = passwordInput.value;
const passwordDetail = document.getElementById('deleteDetail');
passwordInput.classList.remove('is-invalid');
passwordDetail.innerHTML = '';
if (!password.length) {
passwordInput.classList.add('is-invalid');
passwordDetail.innerHTML = lang.get('errorEmptyField');
return;
}
const error = await client.account.delete(password);
if (!error) {
passwordDetail.classList.replace('text-danger', 'text-success');
passwordDetail.innerHTML = 'Account successfully deleted.';
setTimeout(_ => {
bootstrap.Modal.getInstance(document.getElementById('deleteModal')).hide();
navigateTo('/login');
}, 2000);
return;
}
passwordInput.classList.add('is-invalid');
passwordDetail.innerHTML = error['password'];
}
async getHtml() async getHtml()
{ {
const avatarUnchanged = client.me.avatar_url === '/static/avatars/default.avif'; const avatarUnchanged = client.me.avatar_url === '/static/avatars/default.avif';
@ -259,7 +301,25 @@ export default class extends AbstractAuthenticatedView
</div> </div>
</div> </div>
</div> </div>
<button class='btn btn-outline-danger'>Delete account</button> <button class='btn btn-outline-danger' data-bs-toggle='modal' data-bs-target='#deleteModal'>Delete account</button>
<div class='modal fade' id='deleteModal' tabindex='-1'>
<div class='modal-dialog'>
<div class='modal-content'>
<div class='modal-header bg-danger bg-gradient'>
<h1 class='modal-title fs-5'>Are you sure ? This action is permanent !!</h1>
<button class='btn-close' data-bs-dismiss='modal'></button>
</div>
<div class='modal-body'>
<h6 class='form-label'>Please enter your password to confirm deletion:</h6>
<input type='password' class='form-control' id='deleteInput' placeholder='Password'>
<span class='form-text text-danger' id='deleteDetail'></span>
</div>
<div class='modal-footer'>
<button type='button' class='btn btn-secondary' data-bs-dismiss='modal'>Cancel</button>
<button type='button' class='btn btn-danger' id='deleteButton'>Delete account</button>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>