Update admin theme/layout and refresh README details.

Align the project baseline with the latest admin interface styling and layout structure while documenting setup and usage updates in README.
This commit is contained in:
vlad
2026-07-14 17:12:28 +03:00
commit 86cc3fa541
278 changed files with 19416 additions and 0 deletions
+132
View File
@@ -0,0 +1,132 @@
from __future__ import annotations
from datetime import UTC, datetime
from sqlalchemy import delete, select
from app.core.database import session_scope
from app.modules.auth.models import EmailVerificationToken, PasswordResetToken, RefreshToken
def _detach(db, instance):
db.refresh(instance)
db.expunge(instance)
return instance
def create_refresh_token(
user_id: str,
token_hash: str,
family_id: str,
expires_at: datetime,
) -> RefreshToken:
with session_scope() as db:
token = RefreshToken(
user_id=user_id,
token_hash=token_hash,
family_id=family_id,
expires_at=expires_at,
)
db.add(token)
db.flush()
return _detach(db, token)
def get_refresh_token(token_hash: str) -> RefreshToken | None:
with session_scope() as db:
token = db.scalar(select(RefreshToken).where(RefreshToken.token_hash == token_hash))
if not token:
return None
return _detach(db, token)
def revoke_refresh_token(token_hash: str) -> RefreshToken | None:
with session_scope() as db:
token = db.scalar(select(RefreshToken).where(RefreshToken.token_hash == token_hash))
if not token:
return None
token.revoked_at = datetime.now(UTC)
db.flush()
return _detach(db, token)
def revoke_user_families(user_id: str) -> None:
with session_scope() as db:
tokens = db.scalars(
select(RefreshToken).where(
RefreshToken.user_id == user_id,
RefreshToken.revoked_at.is_(None),
)
).all()
now = datetime.now(UTC)
for token in tokens:
token.revoked_at = now
def revoke_family_tokens(family_id: str) -> None:
with session_scope() as db:
tokens = db.scalars(
select(RefreshToken).where(
RefreshToken.family_id == family_id,
RefreshToken.revoked_at.is_(None),
)
).all()
now = datetime.now(UTC)
for token in tokens:
token.revoked_at = now
def create_email_verification_token(user_id: str, token_hash: str, expires_at: datetime) -> None:
with session_scope() as db:
db.execute(
delete(EmailVerificationToken).where(
EmailVerificationToken.user_id == user_id,
EmailVerificationToken.used_at.is_(None),
)
)
db.add(EmailVerificationToken(user_id=user_id, token_hash=token_hash, expires_at=expires_at))
def get_email_verification_token(token_hash: str) -> EmailVerificationToken | None:
with session_scope() as db:
token = db.scalar(
select(EmailVerificationToken).where(EmailVerificationToken.token_hash == token_hash)
)
if not token:
return None
return _detach(db, token)
def mark_email_verification_token_used(token_hash: str) -> None:
with session_scope() as db:
token = db.scalar(
select(EmailVerificationToken).where(EmailVerificationToken.token_hash == token_hash)
)
if token:
token.used_at = datetime.now(UTC)
def create_password_reset_token(user_id: str, token_hash: str, expires_at: datetime) -> None:
with session_scope() as db:
db.execute(
delete(PasswordResetToken).where(
PasswordResetToken.user_id == user_id,
PasswordResetToken.used_at.is_(None),
)
)
db.add(PasswordResetToken(user_id=user_id, token_hash=token_hash, expires_at=expires_at))
def get_password_reset_token(token_hash: str) -> PasswordResetToken | None:
with session_scope() as db:
token = db.scalar(select(PasswordResetToken).where(PasswordResetToken.token_hash == token_hash))
if not token:
return None
return _detach(db, token)
def mark_password_reset_token_used(token_hash: str) -> None:
with session_scope() as db:
token = db.scalar(select(PasswordResetToken).where(PasswordResetToken.token_hash == token_hash))
if token:
token.used_at = datetime.now(UTC)