Initial Switch to V2. Completely Overhauled Backend, Frontend and General Structure.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user