Compare commits
	
		
			24 Commits
		
	
	
		
			b95bed8894
			...
			9947ea37e2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9947ea37e2 | |||
| 7e34f883aa | |||
| 07d06253ba | |||
| d5e692449b | |||
| 6dc0293455 | |||
| b12c03074a | |||
| 8bce7d33ca | |||
| b5b54a98ba | |||
| 25721bdda8 | |||
| 27044e9bdb | |||
| 3f3ab52a09 | |||
| ffbfe2ddd0 | |||
| 9c59401cf2 | |||
| d490208ffa | |||
| 2a468bcb82 | |||
| 7b6a8ba57b | |||
| 27e75c4497 | |||
| a965adfdce | |||
| c16d281892 | |||
| 56b6f0e138 | |||
| 8202a8b88d | |||
| 6a4e161d71 | |||
| b98371cf70 | |||
| ea42d10ddf | 
| @ -20,6 +20,11 @@ source .env/bin/activate | ||||
| ``` bash | ||||
| pip install -r requirements.txt | ||||
| ``` | ||||
| - Setup database | ||||
| ``` | ||||
| python manage.py runserver makemigrations profiles | ||||
| python manage.py migrate profiles | ||||
| ``` | ||||
| - Start the developpement server | ||||
| ``` | ||||
| python manage.py runserver 0.0.0.0:8000 | ||||
|  | ||||
| @ -1,11 +1,12 @@ | ||||
| from django.urls import path | ||||
|  | ||||
| from .views import register, login, logout, delete, change_password | ||||
| from .views import register, login, logout, delete, change_password, logged | ||||
|  | ||||
| urlpatterns = [ | ||||
|     path("register", register.RegisterView.as_view(), name="register"), | ||||
|     path("login", login.LoginView.as_view(), name="login"), | ||||
|     path("logout", logout.LogoutView.as_view(), name="logout"), | ||||
|     path("logged", logged.LoggedView.as_view(), name="logged"), | ||||
|     path("delete", delete.DeleteView.as_view(), name="delete"), | ||||
|     path("change_password", change_password.ChangePasswordView.as_view(), name="change_password") | ||||
|      | ||||
|  | ||||
							
								
								
									
										16
									
								
								accounts/views/logged.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								accounts/views/logged.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| from rest_framework.views import APIView | ||||
| from rest_framework.response import Response | ||||
| from rest_framework import permissions, status | ||||
| from django.http import HttpRequest | ||||
| from django.contrib.auth import login | ||||
| from rest_framework.authentication import SessionAuthentication | ||||
|  | ||||
| from ..serializers.login import LoginSerializer | ||||
|  | ||||
| class LoggedView(APIView): | ||||
|      | ||||
| 	permission_classes = (permissions.AllowAny,) | ||||
| 	authentication_classes = (SessionAuthentication,) | ||||
|  | ||||
| 	def get(self, request: HttpRequest): | ||||
| 		return Response(str(request.user.is_authenticated), status=status.HTTP_200_OK) | ||||
| @ -8,6 +8,6 @@ from rest_framework.authentication import SessionAuthentication | ||||
| class LogoutView(APIView): | ||||
| 	permission_classes = (permissions.IsAuthenticated,) | ||||
| 	authentication_classes = (SessionAuthentication,) | ||||
| 	def post(self, request: HttpRequest): | ||||
| 	def get(self, request: HttpRequest): | ||||
| 		logout(request) | ||||
| 		return Response("user unlogged", status=status.HTTP_200_OK) | ||||
							
								
								
									
										0
									
								
								chat/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								chat/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										3
									
								
								chat/admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								chat/admin.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| from django.contrib import admin | ||||
|  | ||||
| # Register your models here. | ||||
							
								
								
									
										6
									
								
								chat/apps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								chat/apps.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| from django.apps import AppConfig | ||||
|  | ||||
|  | ||||
| class ChatConfig(AppConfig): | ||||
|     default_auto_field = 'django.db.models.BigAutoField' | ||||
|     name = 'chat' | ||||
							
								
								
									
										36
									
								
								chat/consumers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								chat/consumers.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| import json | ||||
| from channels.generic.websocket import WebsocketConsumer | ||||
| from asgiref.sync import async_to_sync | ||||
|  | ||||
| class ChatConsumer(WebsocketConsumer): | ||||
| 	def connect(self): | ||||
| 		self.room_group_name = 'test' | ||||
|  | ||||
| 		async_to_sync(self.channel_layer.group_add)( | ||||
| 			self.room_group_name, | ||||
| 			self.channel_name | ||||
| 		) | ||||
|  | ||||
| 		self.accept() | ||||
|  | ||||
|  | ||||
| 	def receive(self, text_data): | ||||
| 		text_data_json = json.loads(text_data) | ||||
| 		message = text_data_json['message'] | ||||
|  | ||||
| 		async_to_sync(self.channel_layer.group_send)( | ||||
| 			self.room_group_name, | ||||
| 			{ | ||||
| 				'type':'chat_message', | ||||
| 				'message':message | ||||
| 			} | ||||
| 		) | ||||
|  | ||||
| 	def chat_message(self, event): | ||||
| 		message = event['message'] | ||||
|  | ||||
| 		self.send(text_data=json.dumps({ | ||||
| 			'type':'chat', | ||||
| 			'username':self.scope["user"].username, | ||||
| 			'message':message | ||||
| 		})) | ||||
							
								
								
									
										3
									
								
								chat/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								chat/models.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| from django.db import models | ||||
|  | ||||
| # Create your models here. | ||||
							
								
								
									
										6
									
								
								chat/routing.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								chat/routing.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| from django.urls import re_path | ||||
| from . import consumers | ||||
|  | ||||
| websocket_urlpatterns = [ | ||||
| 	re_path(r'ws/socket-server/', consumers.ChatConsumer.as_asgi()) | ||||
| ] | ||||
							
								
								
									
										3
									
								
								chat/tests.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								chat/tests.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| from django.test import TestCase | ||||
|  | ||||
| # Create your tests here. | ||||
							
								
								
									
										3
									
								
								chat/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								chat/views.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| from django.shortcuts import render | ||||
|  | ||||
| # Create your views here. | ||||
							
								
								
									
										12
									
								
								frontend/static/css/accounts/login.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/static/css/accounts/login.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #app .form { | ||||
| 	background-color: red; | ||||
|     width: 300px; | ||||
|     height: 300px; | ||||
| 	display: grid; | ||||
| 	grid-template-columns: repeat(1, 1fr); | ||||
| 	grid-gap: 10px; | ||||
| 	margin-left: auto; | ||||
|     margin-right: auto; | ||||
| 	margin-top: 90px; | ||||
|     border: 15px black solid; | ||||
| } | ||||
							
								
								
									
										12
									
								
								frontend/static/css/accounts/register.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/static/css/accounts/register.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #app .form { | ||||
| 	background-color: red; | ||||
|     width: 300px; | ||||
|     height: 300px; | ||||
| 	display: grid; | ||||
| 	grid-template-columns: repeat(1, 1fr); | ||||
| 	grid-gap: 10px; | ||||
| 	margin-left: auto; | ||||
|     margin-right: auto; | ||||
| 	margin-top: 90px; | ||||
|     border: 15px black solid; | ||||
| } | ||||
| @ -1,37 +1,9 @@ | ||||
| body { | ||||
|     --nav-width: 200px; | ||||
|     margin: 0 0 0 var(--nav-width); | ||||
|     margin: 10; | ||||
|     font-family: 'Quicksand', sans-serif; | ||||
|     font-size: 18px; | ||||
| } | ||||
|  | ||||
| .nav { | ||||
|     position: fixed; | ||||
|     top: 0; | ||||
|     left: 0; | ||||
|     width: var(--nav-width); | ||||
|     height: 100vh; | ||||
|     background: #222222; | ||||
| } | ||||
|  | ||||
| .nav__link { | ||||
|     display: block; | ||||
|     padding: 12px 18px; | ||||
|     text-decoration: none; | ||||
|     color: #eeeeee; | ||||
|     font-weight: 500; | ||||
| } | ||||
|  | ||||
| .nav__link:hover { | ||||
|     background: rgba(255, 255, 255, 0.05); | ||||
| } | ||||
|  | ||||
| #app { | ||||
|     margin: 2em; | ||||
|     line-height: 1.5; | ||||
|     font-weight: 500; | ||||
| } | ||||
|  | ||||
| a { | ||||
|     color: #009579; | ||||
| } | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								frontend/static/js/api/accounts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								frontend/static/js/api/accounts.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| 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 } | ||||
							
								
								
									
										65
									
								
								frontend/static/js/api/client.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								frontend/static/js/api/client.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| import { Accounts } from "./accounts.js"; | ||||
|  | ||||
| class Client | ||||
| { | ||||
| 	constructor(url) | ||||
| 	{ | ||||
| 		this._url = url; | ||||
| 		this.accounts = new Accounts(this); | ||||
| 		this._logged = undefined; | ||||
| 	} | ||||
|  | ||||
| 	async isAuthentificate() | ||||
| 	{ | ||||
| 		if (this._logged == undefined) | ||||
| 			this.logged = await this._test_logged(); | ||||
| 		return this.logged;	 | ||||
| 	} | ||||
|  | ||||
| 	async _get(uri) | ||||
| 	{ | ||||
| 		let response = await fetch(this._url + uri, { | ||||
| 			method: "GET", | ||||
| 		}); | ||||
| 		return response; | ||||
| 	} | ||||
|  | ||||
|     async _post(uri, data) | ||||
|     { | ||||
|         let response = await fetch(this._url + uri, { | ||||
| 			method: "POST", | ||||
| 			headers: { | ||||
| 				"Content-Type": "application/json", | ||||
| 			},		   | ||||
| 			body: JSON.stringify(data), | ||||
| 		}); | ||||
|         return response; | ||||
|     } | ||||
|  | ||||
| 	async login(username, password) | ||||
| 	{ | ||||
| 		let response = await this._post("/api/accounts/login", {username: username, password: password}) | ||||
| 		let data = await response.json(); | ||||
| 		if (data == "user connected") | ||||
| 		{ | ||||
| 			this.logged = true; | ||||
| 			return null; | ||||
| 		} | ||||
| 		return data; | ||||
| 	} | ||||
|  | ||||
| 	async logout() | ||||
| 	{ | ||||
| 		await this._get("/api/accounts/logout"); | ||||
| 		this.logged = false; | ||||
| 	} | ||||
|  | ||||
| 	async _test_logged() | ||||
| 	{ | ||||
| 		let response = await this._get("/api/accounts/logged"); | ||||
| 		let data = await response.json(); | ||||
| 		return data === "True"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| export {Client} | ||||
| @ -1,7 +1,18 @@ | ||||
| import LoginView from "./views/accounts/LoginView.js"; | ||||
| import Dashboard from "./views/Dashboard.js"; | ||||
| import Posts from "./views/Posts.js"; | ||||
| import PostView from "./views/PostView.js"; | ||||
| import Settings from "./views/Settings.js"; | ||||
| import Chat from "./views/Chat.js"; | ||||
| import HomeView from "./views/HomeView.js"; | ||||
| import RegisterView from "./views/accounts/RegisterView.js"; | ||||
| import LogoutView from "./views/accounts/LogoutView.js"; | ||||
|  | ||||
| import { Client } from "./api/client.js"; | ||||
|  | ||||
| let client = new Client(location.protocol + "//" + location.host) | ||||
|  | ||||
| let lastView = undefined | ||||
|  | ||||
| const pathToRegex = path => new RegExp("^" + path.replace(/\//g, "\\/").replace(/:\w+/g, "(.+)") + "$"); | ||||
|  | ||||
| @ -14,24 +25,29 @@ const getParams = match => { | ||||
|     })); | ||||
| }; | ||||
|  | ||||
| const navigateTo = url => { | ||||
|     history.pushState(null, null, url); | ||||
|     router(); | ||||
| const navigateTo = async (uri) => { | ||||
|     if (await router(uri) === 0) | ||||
|         history.pushState(null, null, uri); | ||||
| }; | ||||
|  | ||||
| const router = async () => { | ||||
| const router = async (uri = "") => { | ||||
|     const routes = [ | ||||
|         { path: "/", view: Dashboard }, | ||||
|         { path: "/posts", view: Posts }, | ||||
|         { path: "/posts/:id", view: PostView }, | ||||
|         { path: "/settings", view: Settings } | ||||
|         { path: "/settings", view: Settings }, | ||||
|         { path: "/login", view: LoginView }, | ||||
|         { path: "/logout", view: LogoutView }, | ||||
|         { path: "/register", view: RegisterView }, | ||||
|         { path: "/chat", view: Chat }, | ||||
|         { path: "/home", view: HomeView }, | ||||
|     ]; | ||||
|  | ||||
|     // Test each route for potential match | ||||
|     const potentialMatches = routes.map(route => { | ||||
|         return { | ||||
|             route: route, | ||||
|             result: location.pathname.match(pathToRegex(route.path)) | ||||
|             result: uri.match(pathToRegex(route.path)) | ||||
|         }; | ||||
|     }); | ||||
|  | ||||
| @ -40,13 +56,24 @@ const router = async () => { | ||||
|     if (!match) { | ||||
|         match = { | ||||
|             route: routes[0], | ||||
|             result: [location.pathname] | ||||
|             result: [uri] | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     const view = new match.route.view(getParams(match)); | ||||
| 	if (lastView !== undefined) | ||||
| 		await lastView.leavePage(); | ||||
|  | ||||
|     document.querySelector("#app").innerHTML = await view.getHtml(); | ||||
|     const view = new match.route.view(getParams(match)); | ||||
| 	lastView = view; | ||||
|  | ||||
|     let content = await view.getHtml(); | ||||
|     if (content == null) | ||||
|         return 1; | ||||
|  | ||||
|         document.querySelector("#app").innerHTML = content | ||||
|  | ||||
| 	await view.postInit(); | ||||
|     return 0; | ||||
| }; | ||||
|  | ||||
| window.addEventListener("popstate", router); | ||||
| @ -55,9 +82,10 @@ document.addEventListener("DOMContentLoaded", () => { | ||||
|     document.body.addEventListener("click", e => { | ||||
|         if (e.target.matches("[data-link]")) { | ||||
|             e.preventDefault(); | ||||
|             navigateTo(e.target.href); | ||||
|             navigateTo(e.target.href.slice(location.origin.length)); | ||||
|         } | ||||
|     }); | ||||
|     router(location.pathname); | ||||
| }); | ||||
|  | ||||
|     router(); | ||||
| }); | ||||
| export { client, navigateTo } | ||||
| @ -3,6 +3,12 @@ export default class { | ||||
|         this.params = params; | ||||
|     } | ||||
|  | ||||
| 	async postInit() { | ||||
| 	} | ||||
|  | ||||
| 	async leavePage() { | ||||
| 	} | ||||
|  | ||||
|     setTitle(title) { | ||||
|         document.title = title; | ||||
|     } | ||||
| @ -10,4 +16,4 @@ export default class { | ||||
|     async getHtml() { | ||||
|         return ""; | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | ||||
							
								
								
									
										57
									
								
								frontend/static/js/views/Chat.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								frontend/static/js/views/Chat.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| import AbstractView from "./AbstractView.js"; | ||||
|  | ||||
| export default class extends AbstractView { | ||||
|     constructor(params) { | ||||
|         super(params); | ||||
|         this.setTitle("Chat"); | ||||
|  | ||||
| 		let url = `ws://${window.location.host}/ws/socket-server/` | ||||
|  | ||||
| 		this.chatSocket = new WebSocket(url) | ||||
| 		this.chatSocket.onmessage = function(e){ | ||||
| 			let data = JSON.parse(e.data) | ||||
| 			console.log('Data:', data) | ||||
| 			if (data.type === 'chat') { | ||||
| 				let messages = document.getElementById('messages') | ||||
|  | ||||
| 				let username = data.username === null || data.username.length <= 0 ? "NoName" : data.username; | ||||
| 				messages.insertAdjacentHTML('beforeend', ` | ||||
| 					<div><p>${username}: ${data.message}</p></div> | ||||
| 				`) | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|     } | ||||
|  | ||||
| 	async postInit() { | ||||
| 		let form = document.getElementById('form') | ||||
| 		form.addEventListener('submit', (e)=> { | ||||
| 			e.preventDefault() | ||||
| 			let message = e.target.message.value | ||||
| 			this.chatSocket.send(JSON.stringify({ | ||||
| 				'message':message | ||||
| 			})) | ||||
| 			form.reset() | ||||
| 		}) | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	async leavePage() { | ||||
| 		this.chatSocket.close(); | ||||
| 	} | ||||
|  | ||||
|     async getHtml() { | ||||
|         return ` | ||||
| 			<h1>Chat</h1> | ||||
|  | ||||
| 			<form id="form"> | ||||
| 				<input type="text" name="message" /> | ||||
| 			</form> | ||||
|  | ||||
| 			<div id="messages"> | ||||
|  | ||||
| 			</div> | ||||
|  | ||||
|         `; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										21
									
								
								frontend/static/js/views/HomeView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								frontend/static/js/views/HomeView.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| import AbstractView from "./AbstractView.js"; | ||||
| import { client, navigateTo } from "../index.js"; | ||||
|  | ||||
| export default class extends AbstractView { | ||||
|     constructor(params) { | ||||
|         super(params); | ||||
|         this.setTitle("Home"); | ||||
| 	} | ||||
|  | ||||
|     async getHtml() { | ||||
|         if (await client.isAuthentificate() === false) | ||||
|         { | ||||
| 			navigateTo("/login"); | ||||
|             return; | ||||
|         } | ||||
|         return ` | ||||
| 			<h1>HOME</h1> | ||||
|             <a href="/logout" class="nav__link" data-link>Logout</a> | ||||
|         `; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										61
									
								
								frontend/static/js/views/accounts/LoginView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								frontend/static/js/views/accounts/LoginView.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| import AbstractView from "../AbstractView.js"; | ||||
| import { client, navigateTo } from "../../index.js"; | ||||
|  | ||||
| async function login() | ||||
| { | ||||
| 	let username = document.getElementById("username").value; | ||||
| 	let password = document.getElementById("password").value; | ||||
| 	 | ||||
| 	let response_data = await client.login(username, password); | ||||
|  | ||||
| 	if (response_data == null) | ||||
| 	{ | ||||
| 		navigateTo("/home"); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	["username", "user", "password"].forEach(error_field => { | ||||
| 		let error_display = document.getElementById(`error_${error_field}`); | ||||
| 		if (error_display != null) | ||||
| 			error_display.innerHTML = ""; | ||||
| 	}); | ||||
|  | ||||
| 	Object.keys(response_data).forEach(error_field => { | ||||
| 		let error_display = document.getElementById(`error_${error_field}`); | ||||
| 		if (error_display != null) | ||||
| 			error_display.innerHTML = response_data[error_field]; | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| export default class extends AbstractView { | ||||
|     constructor(params) { | ||||
|         super(params); | ||||
| 	} | ||||
|  | ||||
| 	async postInit() | ||||
| 	{ | ||||
|         this.setTitle("Login"); | ||||
| 		document.getElementById("button").onclick = login; | ||||
| 	} | ||||
|  | ||||
|     async getHtml() { | ||||
| 		if (await client.isAuthentificate()) | ||||
| 		{ | ||||
| 			navigateTo("/home") | ||||
| 			return; | ||||
| 		} | ||||
|         return ` | ||||
| 			<div class=form> | ||||
| 				<label>Login</label> | ||||
| 				<link rel="stylesheet" href="static/css/accounts/login.css"> | ||||
| 				<input type="text" id="username" placeholder="username"> | ||||
| 				<span id="error_username"></span> | ||||
| 				<input type="password" id="password" placeholder="password"> | ||||
| 				<span id="error_password"></span> | ||||
| 				<input type="button" value="login" id="button"> | ||||
| 				<span id="error_user"></span> | ||||
| 				<a href="/register" class="nav__link" data-link>Register</a> | ||||
| 			</div> | ||||
|         `; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										13
									
								
								frontend/static/js/views/accounts/LogoutView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								frontend/static/js/views/accounts/LogoutView.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| import { client, navigateTo } from "../../index.js"; | ||||
| import AbstractView from "../AbstractView.js"; | ||||
|  | ||||
| export default class extends AbstractView | ||||
| { | ||||
| 	constructor(params) { | ||||
| 		super(params); | ||||
| 		this.setTitle("Logout"); | ||||
| 		if (client.logged) | ||||
| 			client.logout(); | ||||
| 		navigateTo("/login") | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										56
									
								
								frontend/static/js/views/accounts/RegisterView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								frontend/static/js/views/accounts/RegisterView.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| import AbstractView from "../AbstractView.js"; | ||||
| import { client, navigateTo } from "../../index.js"; | ||||
|  | ||||
| async function register() | ||||
| { | ||||
| 	let username = document.getElementById("username").value; | ||||
| 	let password = document.getElementById("password").value; | ||||
| 	 | ||||
| 	let response = await client.accounts.create(username, password); | ||||
| 	let response_data = await response.json(); | ||||
| 	 | ||||
| 	["username", "user", "password"].forEach(error_field => { | ||||
| 		let error_display = document.getElementById(`error_${error_field}`); | ||||
| 		if (error_display != null) | ||||
| 			error_display.innerHTML = ""; | ||||
| 	}); | ||||
|  | ||||
| 	Object.keys(response_data).forEach(error_field => { | ||||
| 		let error_display = document.getElementById(`error_${error_field}`); | ||||
| 		if (error_display != null) | ||||
| 			error_display.innerHTML = response_data[error_field]; | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| export default class extends AbstractView { | ||||
|     constructor(params) { | ||||
|         super(params); | ||||
| 	} | ||||
|  | ||||
| 	async postInit() | ||||
| 	{ | ||||
| 		this.setTitle("register"); | ||||
| 		document.getElementById("button").onclick = register; | ||||
| 	} | ||||
|  | ||||
|     async getHtml() { | ||||
| 		if (await client.isAuthentificate()) | ||||
| 		{ | ||||
| 			navigateTo("/home") | ||||
| 			return; | ||||
| 		} | ||||
|         return ` | ||||
| 			<div class=form> | ||||
| 				<label>Register</label> | ||||
| 				<link rel="stylesheet" href="static/css/accounts/register.css"> | ||||
| 				<input type="text" id="username" placeholder="username"> | ||||
| 				<span id="error_username"></span> | ||||
| 				<input type="password" id="password" placeholder="password"> | ||||
| 				<span id="error_password"></span> | ||||
| 				<input type="button" value="register" id="button"> | ||||
| 				<span id="error_user"></span> | ||||
| 				<a href="/login" class="nav__link" data-link>Login</a> | ||||
| 			</div> | ||||
|         `; | ||||
|     } | ||||
| } | ||||
| @ -12,6 +12,9 @@ | ||||
|         <a href="/" class="nav__link" data-link>Dashboard</a> | ||||
|         <a href="/posts" class="nav__link" data-link>Posts</a> | ||||
|         <a href="/settings" class="nav__link" data-link>Settings</a> | ||||
|         <a href="/login" class="nav__link" data-link>Login</a> | ||||
|         <a href="/register" class="nav__link" data-link>Register</a> | ||||
|         <a href="/chat" class="nav__link" data-link>Chat</a> | ||||
|     </nav> | ||||
|     <div id="app"></div> | ||||
| 	<script type="module" src="{% static 'js/index.js' %}"></script> | ||||
|  | ||||
| @ -2,5 +2,6 @@ from django.shortcuts import render | ||||
|  | ||||
| # Create your views here. | ||||
|  | ||||
|  | ||||
| def index_view(req): | ||||
|     return render(req, 'index.html'); | ||||
|  | ||||
| @ -6,4 +6,5 @@ djangorestframework==3.14.0 | ||||
| install==1.3.5 | ||||
| pytz==2023.3.post1 | ||||
| sqlparse==0.4.4 | ||||
| channels==3.0.5 | ||||
| channels==4.0.0 | ||||
| daphne | ||||
|  | ||||
| @ -8,9 +8,20 @@ https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ | ||||
| """ | ||||
|  | ||||
| import os | ||||
| from channels.routing import ProtocolTypeRouter, URLRouter | ||||
| from channels.auth import AuthMiddlewareStack | ||||
| import chat.routing | ||||
|  | ||||
| from django.core.asgi import get_asgi_application | ||||
|  | ||||
| os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'trancendence.settings') | ||||
|  | ||||
| application = get_asgi_application() | ||||
| application = ProtocolTypeRouter({ | ||||
| 	'http':get_asgi_application(), | ||||
| 	'websocket':AuthMiddlewareStack( | ||||
| 		URLRouter( | ||||
| 			chat.routing.websocket_urlpatterns | ||||
| 		) | ||||
| 	) | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ -38,6 +38,9 @@ CORS_ORIGIN_WHITELIST = ( | ||||
| # Application definition | ||||
|  | ||||
| INSTALLED_APPS = [ | ||||
| 	'channels', | ||||
| 	'daphne', | ||||
|  | ||||
|     'accounts.apps.AccountsConfig', | ||||
|     'profiles.apps.ProfilesConfig', | ||||
|     'frontend.apps.FrontendConfig', | ||||
| @ -52,6 +55,14 @@ INSTALLED_APPS = [ | ||||
|     'django.contrib.staticfiles', | ||||
| ] | ||||
|  | ||||
| ASGI_APPLICATION = 'trancendence.asgi.application' | ||||
|  | ||||
| CHANNEL_LAYERS = { | ||||
| 	'default' :{ | ||||
| 		'BACKEND':'channels.layers.InMemoryChannelLayer' | ||||
| 	} | ||||
| } | ||||
|  | ||||
| MIDDLEWARE = [ | ||||
|     'corsheaders.middleware.CorsMiddleware', | ||||
|     'django.middleware.common.CommonMiddleware', | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	