David Prince
production: clean source snapshot — no history bloat
71b4454
Raw
History Blame Contribute Delete
2.64 kB
import os
import hashlib
import asyncpg
from fastapi import HTTPException
from pydantic import BaseModel
import app_part1
from app_part1 import app
SECRET_KEY = os.environ.get("DOLOR3V_SECRET_KEY", "dev-secret-change-me")
IN_MEMORY_USERS = {}
def hash_password(password: str) -> str:
return hashlib.sha256((password + SECRET_KEY).encode()).hexdigest()
class UserCreateRequest(BaseModel):
email: str
password: str
name: str
class UserLoginRequest(BaseModel):
email: str
password: str
USERS_TABLE_SQL = "CREATE TABLE IF NOT EXISTS dolor3v_users (id SERIAL PRIMARY KEY, email TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, name TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now())"
@app.post("/v1/auth/register")
async def register_user(req: UserCreateRequest):
password_hash = hash_password(req.password)
if app_part1.db_pool is not None:
try:
async with app_part1.db_pool.acquire() as conn:
await conn.execute(USERS_TABLE_SQL)
row = await conn.fetchrow(
"INSERT INTO dolor3v_users (email, password_hash, name) VALUES ($1, $2, $3) RETURNING id, email, name",
req.email, password_hash, req.name
)
return {"user": dict(row), "token": f"user_{row['id']}"}
except asyncpg.UniqueViolationError:
raise HTTPException(status_code=400, detail="Email already exists")
if req.email in IN_MEMORY_USERS:
raise HTTPException(status_code=400, detail="Email already exists")
user_id = len(IN_MEMORY_USERS) + 1
IN_MEMORY_USERS[req.email] = {"id": user_id, "email": req.email, "password_hash": password_hash, "name": req.name}
return {"user": {"id": user_id, "email": req.email, "name": req.name}, "token": f"user_{user_id}"}
@app.post("/v1/auth/login")
async def login_user(req: UserLoginRequest):
password_hash = hash_password(req.password)
if app_part1.db_pool is not None:
async with app_part1.db_pool.acquire() as conn:
row = await conn.fetchrow("SELECT id, email, name FROM dolor3v_users WHERE email = $1 AND password_hash = $2", req.email, password_hash)
if not row:
raise HTTPException(status_code=401, detail="Invalid credentials")
return {"user": dict(row), "token": f"user_{row['id']}"}
user = IN_MEMORY_USERS.get(req.email)
if not user or user["password_hash"] != password_hash:
raise HTTPException(status_code=401, detail="Invalid credentials")
return {"user": {"id": user["id"], "email": user["email"], "name": user["name"]}, "token": f"user_{user['id']}"}