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
|
import re
from datetime import datetime, UTC
from urllib.parse import urlsplit
from uuid import uuid4, UUID, uuid7
from sqlalchemy import DateTime
from sqlmodel import SQLModel, Field, Relationship
from starlette.authentication import BaseUser
from authentication.mixins import OAuth2ClientMixin, OAuth2AuthorizationCodeMixin, OAuth2TokenMixin
from authentication.utils import bcrypt_sha256_hash
class BaseModel(SQLModel):
id: UUID | None = Field(primary_key=True, default_factory=uuid7)
created: datetime = Field(
default_factory=lambda: datetime.now(tz=UTC),
sa_type=DateTime(timezone=True),
)
updated: datetime = Field(
default=None,
nullable=True,
sa_column_kwargs={
'onupdate': lambda: datetime.now(tz=UTC),
},
sa_type=DateTime(timezone=True),
)
class User(BaseModel, BaseUser, table=True):
username: str = Field(unique=True, index=True)
password: str = Field(nullable=False)
email: str
def set_password(self, value):
self.password = bcrypt_sha256_hash(value)
def is_authenticated(self) -> bool:
return True
class Session(BaseModel, table=True):
user_id: UUID = Field(foreign_key='user.id', exclude=True)
user: User = Relationship()
class ClientApplication(BaseModel, OAuth2ClientMixin, table=True):
name: str
def check_redirect_uri(self, redirect_uri: str) -> bool:
return any(
re.fullmatch(re.escape(str(pattern)).replace(r"\*", r"\d+"), redirect_uri)
for pattern in self.redirect_uris
)
class AuthCode(BaseModel, OAuth2AuthorizationCodeMixin, table=True):
user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE")
user: User = Relationship()
class AuthToken(BaseModel, OAuth2TokenMixin, table=True):
user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE")
user: User = Relationship()
|