diff --git a/accounts/tests/__init__.py b/accounts/tests/__init__.py index 4187043..80d6cf2 100644 --- a/accounts/tests/__init__.py +++ b/accounts/tests/__init__.py @@ -1,4 +1,5 @@ from .register import * from .login import * +from .logout import * from .edit import * from .delete import * \ No newline at end of file diff --git a/accounts/tests/delete.py b/accounts/tests/delete.py index f7cfc47..438d6d1 100644 --- a/accounts/tests/delete.py +++ b/accounts/tests/delete.py @@ -21,12 +21,17 @@ class DeleteTest(TestCase): def test_normal_delete(self): - response: HttpResponse = self.client.delete(self.url) + response: HttpResponse = self.client.delete(self.url, {"password": self.password}, content_type='application/json') response_text: str = response.content.decode("utf-8") self.assertEqual(response_text, '"user deleted"') + def test_wrong_pass(self): + response: HttpResponse = self.client.delete(self.url, {"password": "cacaman a frapper"}, content_type='application/json') + errors: dict = eval(response.content) + self.assertDictEqual(errors, {"password": ["Password wrong."]}) + def test_no_logged(self): self.client.logout() - response: HttpResponse = self.client.post(self.url) + response: HttpResponse = self.client.delete(self.url, {"password": self.password}, content_type='application/json') errors: dict = eval(response.content) self.assertDictEqual(errors, {"detail":"Authentication credentials were not provided."}) \ No newline at end of file diff --git a/accounts/views/delete.py b/accounts/views/delete.py index 0a3265c..30b4c7c 100644 --- a/accounts/views/delete.py +++ b/accounts/views/delete.py @@ -8,5 +8,12 @@ class DeleteView(APIView): permission_classes = (permissions.IsAuthenticated,) authentication_classes = (SessionAuthentication,) def delete(self, request: HttpRequest): + data: dict = request.data + + password: str = data["password"] + if (password is None): + return Response({"password": ["This field may not be blank."]}) + if (request.user.check_password(password) == False): + return Response({"password": ["Password wrong."]}) request.user.delete() return Response("user deleted", status=status.HTTP_200_OK) \ No newline at end of file diff --git a/accounts/views/edit.py b/accounts/views/edit.py index 8325b06..7741e3f 100644 --- a/accounts/views/edit.py +++ b/accounts/views/edit.py @@ -12,6 +12,9 @@ class EditView(APIView): permission_classes = (permissions.IsAuthenticated,) authentication_classes = (SessionAuthentication,) + def get(self, request: HttpRequest): + return Response({"username": request.user.username}) + def patch(self, request: HttpRequest): data: dict = request.data diff --git a/frontend/static/js/api/account.js b/frontend/static/js/api/account.js new file mode 100644 index 0000000..d2b590a --- /dev/null +++ b/frontend/static/js/api/account.js @@ -0,0 +1,59 @@ +class Account +{ + constructor (client) + { + this.client = client; + } + + async create(username, password) + { + let response = await this.client._post("/api/accounts/register", {username: username, password: password}); + let response_data = await response.json() + + if (response_data == "user created") + { + this._logged = true; + return null; + } + return response_data + } + + async delete(password) + { + let response = await this.client._delete("/api/accounts/delete", {password: password}); + let response_data = await response.json(); + + if (response_data === "user deleted") + this.client._logged = false; + return response_data; + } + + async get() + { + let response = await this.client._get("/api/accounts/edit"); + let response_data = await response.json(); + + if (JSON.stringify(response_data) == JSON.stringify({'detail': 'Authentication credentials were not provided.'})) + { + console.log("error, client is not logged"); + return null; + } + return response_data; + } + + async update(data, password) + { + data.password = password; + let response = await this.client._patch_json("/api/accounts/edit", data); + let response_data = await response.json(); + + if (JSON.stringify(response_data) == JSON.stringify({'detail': 'Authentication credentials were not provided.'})) + { + console.log("error, client is not logged"); + return null; + } + return response_data; + } +} + +export { Account } \ No newline at end of file diff --git a/frontend/static/js/api/accounts.js b/frontend/static/js/api/accounts.js deleted file mode 100644 index 154a563..0000000 --- a/frontend/static/js/api/accounts.js +++ /dev/null @@ -1,15 +0,0 @@ -class Accounts -{ - constructor (client) - { - this.client = client; - } - - async create(username, password) - { - let response = await this.client._post("/api/accounts/register", {username: username, password: password}); - return response - } -} - -export { Accounts } \ No newline at end of file diff --git a/frontend/static/js/api/client.js b/frontend/static/js/api/client.js index b0a5439..fa0d94d 100644 --- a/frontend/static/js/api/client.js +++ b/frontend/static/js/api/client.js @@ -1,11 +1,21 @@ -import { Accounts } from "./accounts.js"; +import { Account } from "./account.js"; + +function getCookie(name) +{ + let cookie = {}; + document.cookie.split(';').forEach(function(el) { + let split = el.split('='); + cookie[split[0].trim()] = split.slice(1).join("="); + }) + return cookie[name]; +} class Client { constructor(url) { this._url = url; - this.accounts = new Accounts(this); + this.account = new Account(this); this._logged = undefined; } @@ -30,6 +40,33 @@ class Client method: "POST", headers: { "Content-Type": "application/json", + "X-CSRFToken": getCookie("csrftoken"), + }, + body: JSON.stringify(data), + }); + return response; + } + + async _delete(uri, data) + { + let response = await fetch(this._url + uri, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + "X-CSRFToken": getCookie("csrftoken"), + }, + body: JSON.stringify(data), + }); + return response; + } + + async _patch_json(uri, data) + { + let response = await fetch(this._url + uri, { + method: "PATCH", + headers: { + "X-CSRFToken": getCookie("csrftoken"), + "Content-Type": "application/json", }, body: JSON.stringify(data), }); diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index 47255df..e923833 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -10,6 +10,7 @@ import LogoutView from "./views/accounts/LogoutView.js"; import { Client } from "./api/client.js"; import AbstractRedirectView from "./views/AbstractRedirectView.js"; +import MeView from "./views/MeView.js"; let client = new Client(location.protocol + "//" + location.host) @@ -42,6 +43,7 @@ const router = async (uri = "") => { { path: "/register", view: RegisterView }, { path: "/chat", view: Chat }, { path: "/home", view: HomeView }, + { path: "/me", view: MeView }, ]; // Test each route for potential match diff --git a/frontend/static/js/views/HomeView.js b/frontend/static/js/views/HomeView.js index 5f9f3fb..d9fd194 100644 --- a/frontend/static/js/views/HomeView.js +++ b/frontend/static/js/views/HomeView.js @@ -9,6 +9,7 @@ export default class extends AbstractAuthentificateView { async getHtml() { return `