aboutsummaryrefslogtreecommitdiff
path: root/app/app_account.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/app_account.py')
-rw-r--r--app/app_account.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/app/app_account.py b/app/app_account.py
new file mode 100644
index 0000000..3f4869d
--- /dev/null
+++ b/app/app_account.py
@@ -0,0 +1,87 @@
1# UGE / L2 / Intro to relational databases / Python project prototype
2# Author: Pacien TRAN-GIRARD
3# Licence: EUPL-1.2
4
5from fastapi import APIRouter, Depends, Request, Form, status
6
7from passlib.context import CryptContext
8import re
9
10from embrace.exceptions import IntegrityError
11from psycopg2.errors import UniqueViolation
12
13from app_sessions import UserSession
14from app_database import db_transaction
15
16
17# Password hashing context.
18# Handles proper salting and migration automatically.
19password_ctx = CryptContext(schemes=['bcrypt'], deprecated='auto')
20
21username_pattern = re.compile(r'^[a-zA-Z0-9-_]{4,16}$')
22
23router = APIRouter()
24
25
26@router.get('/')
27def homepage(
28 session: UserSession=Depends(UserSession),
29):
30 if session.is_logged_in():
31 return 'Welcome!'
32
33 return 'Homepage here.'
34
35
36@router.post('/account/register')
37def account_register(
38 session: UserSession=Depends(UserSession),
39 username: str=Form(...),
40 password: str=Form(...),
41):
42 try:
43 if username_pattern.match(username) is None:
44 return 'error: Invalid username format.'
45
46 if not 4 <= len(password) <= 32:
47 return 'error: Invalid password length.'
48
49 hash = password_ctx.hash(password)
50 with db_transaction() as tx:
51 user = tx.create_account(username=username, password_hash=hash)
52
53 session.login(user.id)
54 return 'Account succesfully created. Welcome!'
55
56 except IntegrityError as exception:
57 if isinstance(exception.__cause__, UniqueViolation):
58 return 'error: This username is already taken.'
59 else:
60 raise exception
61
62
63@router.post('/account/login')
64def session_login(
65 session: UserSession=Depends(UserSession),
66 username: str=Form(...),
67 password: str=Form(...),
68):
69 with db_transaction() as tx:
70 user = tx.fetch_account_username(username=username)
71
72 if user is not None and password_ctx.verify(password, user.password_hash):
73 session.login(user.id)
74 return 'Welcome back!'
75 else:
76 return 'error: Invalid credentials.'
77
78
79@router.post('/account/logout')
80def session_logout(
81 session: UserSession=Depends(UserSession),
82):
83 if session.is_logged_in():
84 session.logout()
85 return 'You have been successfully logged out.'
86
87 return 'Nothing to do'