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

@@ -41,3 +41,11 @@ class UserInDB(UserCreate):
class UserListResponse(BaseModel):
users: List[UserInDB]
total: int
class SetPasswordRequest(BaseModel):
password: str
class ResetPasswordRequest(BaseModel):
new_password: str = "Bell1234!" # default reset value

View File

@@ -4,6 +4,7 @@ from auth.models import TokenPayload
from auth.dependencies import require_permission
from users.models import (
UserCreate, UserUpdate, UserInDB, UserListResponse,
SetPasswordRequest, ResetPasswordRequest,
)
from users import service
@@ -95,6 +96,26 @@ async def unassign_device(
return service.unassign_device(user_id, device_id)
@router.post("/{user_id}/set-password", status_code=204)
async def set_password(
user_id: str,
body: SetPasswordRequest,
_user: TokenPayload = Depends(require_permission("app_users", "full_edit")),
):
"""Set a new password for the user via Firebase Auth (requires uid on the user doc)."""
service.set_password(user_id, body.password)
@router.post("/{user_id}/reset-password", status_code=204)
async def reset_password(
user_id: str,
body: ResetPasswordRequest,
_user: TokenPayload = Depends(require_permission("app_users", "full_edit")),
):
"""Reset a user's password to the supplied value (default: Bell1234!)."""
service.set_password(user_id, body.new_password)
@router.post("/{user_id}/photo")
async def upload_photo(
user_id: str,

View File

@@ -2,8 +2,9 @@ from datetime import datetime
from google.cloud.firestore_v1 import DocumentReference
from firebase_admin import auth as firebase_auth
from shared.firebase import get_db, get_bucket
from shared.exceptions import NotFoundError
from shared.exceptions import NotFoundError, ValidationError
from users.models import UserCreate, UserUpdate, UserInDB
COLLECTION = "users"
@@ -252,6 +253,31 @@ def get_user_devices(user_doc_id: str) -> list[dict]:
return devices
def set_password(user_doc_id: str, new_password: str) -> None:
"""Set a Firebase Auth password for a user via their Firestore document ID.
Requires the user document to have a non-empty `uid` field — populated
automatically for users who registered via the Flutter app.
"""
if not new_password or len(new_password) < 6:
raise ValidationError("Password must be at least 6 characters.")
db = get_db()
doc_ref = db.collection(COLLECTION).document(user_doc_id)
doc = doc_ref.get()
if not doc.exists:
raise NotFoundError("User")
uid = doc.to_dict().get("uid", "")
if not uid:
raise ValidationError("This user has no Firebase Auth UID — they may not have signed up via the app yet.")
try:
firebase_auth.update_user(uid, password=new_password)
except Exception as e:
raise RuntimeError(f"Firebase Auth error: {e}")
def upload_photo(user_doc_id: str, file_bytes: bytes, filename: str, content_type: str) -> str:
"""Upload a profile photo to Firebase Storage and update the user's photo_url."""
db = get_db()