Initial Switch to V2. Completely Overhauled Backend, Frontend and General Structure.

This commit is contained in:
2026-04-17 14:37:36 +03:00
parent eb773c5531
commit 0a8a42d69b
447 changed files with 70696 additions and 492 deletions

View File

@@ -1,5 +1,5 @@
from pydantic import BaseModel
from typing import Optional
from typing import Any, Dict, Optional
from auth.models import StaffPermissions
@@ -35,3 +35,7 @@ class StaffResponse(BaseModel):
class StaffListResponse(BaseModel):
staff: list[StaffResponse]
total: int
class PreferencesUpdate(BaseModel):
prefs: Dict[str, Any]

23
backend/staff/orm.py Normal file
View File

@@ -0,0 +1,23 @@
from datetime import datetime, timezone
from sqlalchemy import Boolean, Column, DateTime, String
from sqlalchemy.dialects.postgresql import JSONB
from database.postgres import Base
def _now():
return datetime.now(timezone.utc)
class Staff(Base):
__tablename__ = "staff"
id = Column(String(128), primary_key=True) # Firestore doc ID during transition
firestore_id = Column(String(128), unique=True) # same as id during transition
email = Column(String(256), unique=True, nullable=False)
name = Column(String(255), nullable=False)
role = Column(String(64), nullable=False, default="staff")
permissions = Column(JSONB, nullable=False, default=dict)
hashed_password = Column(String(256), nullable=False)
is_active = Column(Boolean, nullable=False, default=True)
created_at = Column(DateTime(timezone=True), nullable=False, default=_now)
updated_at = Column(DateTime(timezone=True), nullable=False, default=_now, onupdate=_now)

View File

@@ -1,10 +1,12 @@
from fastapi import APIRouter, Depends, Query
from typing import Any
from auth.dependencies import get_current_user, require_staff_management
from auth.models import TokenPayload
from staff import service
from staff.models import (
StaffCreate, StaffUpdate, StaffPasswordUpdate,
StaffResponse, StaffListResponse,
PreferencesUpdate,
)
router = APIRouter(prefix="/api/staff", tags=["staff"])
@@ -15,6 +17,22 @@ async def get_current_staff(current_user: TokenPayload = Depends(get_current_use
return await service.get_staff_me(current_user.sub)
@router.get("/me/preferences", response_model=dict)
async def get_preferences(current_user: TokenPayload = Depends(get_current_user)):
"""Return all UI preferences for the current staff member."""
return await service.get_preferences(current_user.sub)
@router.patch("/me/preferences/{page_key}", response_model=dict)
async def update_preferences(
page_key: str,
body: PreferencesUpdate,
current_user: TokenPayload = Depends(get_current_user),
):
"""Merge preference keys for a specific page into the staff member's stored prefs."""
return await service.update_preferences(current_user.sub, page_key, body.prefs)
@router.get("", response_model=StaffListResponse)
async def list_staff(
search: str = Query(None),

View File

@@ -157,6 +157,33 @@ async def update_staff_password(staff_id: str, new_password: str, current_user_r
return {"message": "Password updated successfully"}
async def get_preferences(staff_id: str) -> dict:
"""Return the ui_prefs map for a staff member, defaulting to {} if not set."""
db = get_db()
doc = db.collection("admin_users").document(staff_id).get()
if not doc.exists:
raise NotFoundError("Staff member not found")
return doc.to_dict().get("ui_prefs", {})
async def update_preferences(staff_id: str, page_key: str, prefs: dict) -> dict:
"""Merge a page-level preferences dict into ui_prefs.<page_key> on the staff document.
Only the supplied keys are overwritten — other keys in the same page block survive.
"""
db = get_db()
doc_ref = db.collection("admin_users").document(staff_id)
doc = doc_ref.get()
if not doc.exists:
raise NotFoundError("Staff member not found")
existing_prefs = doc.to_dict().get("ui_prefs", {})
page_prefs = {**existing_prefs.get(page_key, {}), **prefs}
existing_prefs[page_key] = page_prefs
doc_ref.update({"ui_prefs": existing_prefs})
return existing_prefs
async def delete_staff(staff_id: str, current_user_role: str, current_user_id: str) -> dict:
db = get_db()
doc_ref = db.collection("admin_users").document(staff_id)