gisaf-backend/src/gisaf/models/authentication.py
2024-12-15 19:19:35 +01:00

100 lines
2.6 KiB
Python

from datetime import datetime
from sqlmodel import Field, SQLModel, Relationship, String
from pydantic import BaseModel
from gisaf.models.metadata import gisaf_admin
class UserRoleLink(SQLModel, table=True):
__tablename__: str = "roles_users" # type: ignore
__table_args__ = gisaf_admin.table_args
user_id: int | None = Field(
default=None, foreign_key=gisaf_admin.table("user.id"), primary_key=True
)
role_id: int | None = Field(
default=None, foreign_key=gisaf_admin.table("role.id"), primary_key=True
)
class UserBase(SQLModel):
username: str
email: str
disabled: bool | None = False
class User(UserBase, table=True):
__table_args__ = gisaf_admin.table_args
id: int = Field(primary_key=True)
username: str = Field(String(255), unique=True, index=True)
email: str = Field(sa_type=String(50), unique=True)
password: str = Field(sa_type=String(255))
active: bool = True
confirmed_at: datetime | None = None
last_login_at: datetime | None = None
current_login_at: datetime | None = None
last_login_ip: str | None = Field(sa_type=String(255), default=None)
current_login_ip: str | None = Field(sa_type=String(255), default=None)
login_count: int = 0
roles: list["Role"] = Relationship(back_populates="users", link_model=UserRoleLink)
def can_view(self, model) -> bool:
role = getattr(model, "viewable_role", None)
if role:
return self.has_role(role)
else:
return True
def has_role(self, role: str) -> bool:
return role in (role.name for role in self.roles)
class RoleBase(SQLModel):
name: str = Field(unique=True)
class RoleWithDescription(RoleBase):
description: str | None
class Role(RoleWithDescription, table=True):
__table_args__ = gisaf_admin.table_args
id: int | None = Field(default=None, primary_key=True)
users: list[User] = Relationship(back_populates="roles", link_model=UserRoleLink)
class UserReadNoRoles(UserBase):
id: int
email: str | None # type: ignore
class RoleRead(RoleBase):
id: int
users: list[UserReadNoRoles] = []
class RoleReadNoUsers(RoleBase):
id: int
class UserRead(UserBase):
id: int
email: str | None # type: ignore
roles: list[RoleReadNoUsers] = []
def can_view(self, model) -> bool:
role = getattr(model, "viewable_role", None)
if role:
return self.has_role(role)
else:
return True
def has_role(self, role: str) -> bool:
return role in (role.name for role in self.roles)
# class ACL(BaseModel):
# user_id: int
# role_ids: list[int]