-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathauth.py
executable file
·120 lines (105 loc) · 3.42 KB
/
auth.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env python3
"""A module for authentication-related routines.
"""
import bcrypt
from uuid import uuid4
from typing import Union
from sqlalchemy.orm.exc import NoResultFound
from db import DB
from user import User
def _hash_password(password: str) -> bytes:
"""Hashes a password.
"""
return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
def _generate_uuid() -> str:
"""Generates a UUID.
"""
return str(uuid4())
class Auth:
"""Auth class to interact with the authentication database.
"""
def __init__(self):
"""Initializes a new Auth instance.
"""
self._db = DB()
def register_user(self, email: str, password: str) -> User:
"""Adds a new user to the database.
"""
try:
self._db.find_user_by(email=email)
except NoResultFound:
return self._db.add_user(email, _hash_password(password))
raise ValueError("User {} already exists".format(email))
def valid_login(self, email: str, password: str) -> bool:
"""Checks if a user's login details are valid.
"""
user = None
try:
user = self._db.find_user_by(email=email)
if user is not None:
return bcrypt.checkpw(
password.encode("utf-8"),
user.hashed_password,
)
except NoResultFound:
return False
return False
def create_session(self, email: str) -> str:
"""Creates a new session for a user.
"""
user = None
try:
user = self._db.find_user_by(email=email)
except NoResultFound:
return None
if user is None:
return None
session_id = _generate_uuid()
self._db.update_user(user.id, session_id=session_id)
return session_id
def get_user_from_session_id(self, session_id: str) -> Union[User, None]:
"""Retrieves a user based on a given session ID.
"""
user = None
if session_id is None:
return None
try:
user = self._db.find_user_by(session_id=session_id)
except NoResultFound:
return None
return user
def destroy_session(self, user_id: int) -> None:
"""Destroys a session associated with a given user.
"""
if user_id is None:
return None
self._db.update_user(user_id, session_id=None)
def get_reset_password_token(self, email: str) -> str:
"""Generates a password reset token for a user.
"""
user = None
try:
user = self._db.find_user_by(email=email)
except NoResultFound:
user = None
if user is None:
raise ValueError()
reset_token = _generate_uuid()
self._db.update_user(user.id, reset_token=reset_token)
return reset_token
def update_password(self, reset_token: str, password: str) -> None:
"""Updates a user's password given the user's reset token.
"""
user = None
try:
user = self._db.find_user_by(reset_token=reset_token)
except NoResultFound:
user = None
if user is None:
raise ValueError()
new_password_hash = _hash_password(password)
self._db.update_user(
user.id,
hashed_password=new_password_hash,
reset_token=None,
)