import hashlib from datetime import datetime, timezone from fastapi import APIRouter, Depends, HTTPException, Request, Response from sqlalchemy.orm import Session from ..db import get_db from ..models import InviteToken, User from ..security import hash_password, make_session_value, set_session router = APIRouter(prefix="/auth/invite", tags=["invites"]) def get_invite(token: str, db: Session): token_hash = hashlib.sha256(token.encode()).hexdigest() invite = db.query(InviteToken).filter(InviteToken.token_hash == token_hash).first() expires_at = invite.expires_at if invite else None if expires_at and expires_at.tzinfo is None: expires_at = expires_at.replace(tzinfo=timezone.utc) if not invite or invite.used_at or expires_at <= datetime.now(timezone.utc): raise HTTPException(410, "invite is invalid or expired") user = db.query(User).filter(User.id == invite.user_id, User.disabled == False).first() if not user: raise HTTPException(410, "invite is invalid or expired") return invite, user @router.get("/{token}") def invite_info(token: str, db: Session = Depends(get_db)): _invite, user = get_invite(token, db) return {"valid": True, "display_name": user.display_name, "email": user.email, "role": user.role} @router.post("/{token}") def accept_invite(token: str, data: dict, resp: Response, db: Session = Depends(get_db)): invite, user = get_invite(token, db) password = data.get("password") or "" if len(password) < 8: raise HTTPException(400, "password too short (min 8)") user.password_hash = hash_password(password) invite.used_at = datetime.now(timezone.utc) db.add(user) db.add(invite) db.commit() set_session(resp, make_session_value(user.id)) return {"ok": True}