# retoor import logging from typing import Annotated from fastapi import Depends, APIRouter, Request from fastapi.responses import HTMLResponse from devplacepy.database import get_table, get_setting, get_int_setting from devplacepy.templating import templates from devplacepy.utils import ( create_session, get_current_user, register_account_async, cookie_secure, ) from devplacepy.seo import base_seo_context from devplacepy.models import SignupForm from devplacepy.config import SECONDS_PER_DAY from devplacepy.responses import respond, action_result, wants_json, json_error from devplacepy.schemas import AuthPageOut from devplacepy.services.audit import record as audit from devplacepy.dependencies import json_or_form logger = logging.getLogger(__name__) router = APIRouter() @router.get("/signup", response_class=HTMLResponse) async def signup_page(request: Request): user = get_current_user(request) if user: return action_result(request, "/feed") seo_ctx = base_seo_context( request, title="Join DevPlace", description="Create your DevPlace account and start connecting with developers.", robots="noindex,nofollow", ) registration_closed = get_setting("registration_open", "1") != "1" return respond( request, "signup.html", { **seo_ctx, "request": request, "page": "signup", "registration_closed": registration_closed, }, model=AuthPageOut, ) @router.post("/signup") async def signup(request: Request, data: Annotated[SignupForm, Depends(json_or_form(SignupForm))]): username = data.username email = data.email.strip().lower() password = data.password if get_setting("registration_open", "1") != "1": if wants_json(request): return json_error(403, "Registration is closed") seo_ctx = base_seo_context( request, title="Join DevPlace", robots="noindex,nofollow" ) return templates.TemplateResponse( request, "signup.html", {**seo_ctx, "request": request, "registration_closed": True}, ) errors = [] users = get_table("users") if users.find_one(username=username): errors.append("Username already taken") if users.find_one(email=email): errors.append("Email already registered") if errors: if wants_json(request): return json_error(400, "; ".join(errors), errors=errors) seo_ctx = base_seo_context( request, title="Join DevPlace", robots="noindex,nofollow" ) return templates.TemplateResponse( request, "signup.html", { **seo_ctx, "request": request, "errors": errors, "username": username, "email": email, }, ) uid, role, is_first = await register_account_async(username, email, password) max_age = max(1, get_int_setting("session_max_age_days", 7)) * SECONDS_PER_DAY token = create_session(uid, max_age) response = action_result(request, "/feed", data={"username": username}) response.set_cookie( key="session", value=token, max_age=max_age, httponly=True, samesite="lax", secure=cookie_secure(request), ) logger.info(f"User {username} signed up") audit.record( request, "auth.signup", user={"uid": uid, "username": username, "role": role}, target_type="user", target_uid=uid, target_label=username, new_value=role, metadata={"first_user": is_first}, summary=f"user {username} registered account", links=[audit.target("user", uid, username)], ) return response