forked from retoor/devplacepy
chore: remove stale agent reports and add PYTHONDONTWRITEBYTECODE export to Makefile
Delete four stale SEO and style agent report JSON/MD files from agents/reports/ that had zero findings or were superseded. Export PYTHONDONTWRITEBYTECODE=1 in the Makefile so all make targets suppress bytecode generation, and add a `tree` target that lists the repository file tree via git ls-tree. Update AGENTS.md and CLAUDE.md documentation to reflect that routers now form a directory tree mirroring URL paths and that bytecode writing is disabled project-wide.
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
import logging
|
||||
from typing import Annotated
|
||||
from datetime import datetime, timezone
|
||||
from fastapi import APIRouter, Request, Form
|
||||
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 (
|
||||
hash_password,
|
||||
create_session,
|
||||
generate_uid,
|
||||
get_current_user,
|
||||
award_badge,
|
||||
)
|
||||
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
|
||||
|
||||
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, Form()]):
|
||||
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 = generate_uid()
|
||||
is_first = users.count() == 0
|
||||
users.insert(
|
||||
{
|
||||
"uid": uid,
|
||||
"username": username,
|
||||
"email": email,
|
||||
"api_key": generate_uid(),
|
||||
"password_hash": hash_password(password),
|
||||
"bio": "",
|
||||
"location": "",
|
||||
"git_link": "",
|
||||
"website": "",
|
||||
"role": "Admin" if is_first else "Member",
|
||||
"is_active": True,
|
||||
"level": 1,
|
||||
"xp": 0,
|
||||
"stars": 0,
|
||||
"created_at": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
)
|
||||
|
||||
award_badge(uid, "Member")
|
||||
|
||||
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"
|
||||
)
|
||||
logger.info(f"User {username} signed up")
|
||||
role = "Admin" if is_first else "Member"
|
||||
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
|
||||
Reference in New Issue
Block a user