100 lines
2.6 KiB
Python
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]
|
|
|