email verification responses

This commit is contained in:
Jack Case
2025-11-15 15:45:05 +00:00
parent cfd54eca5e
commit 6724a903eb
2 changed files with 39 additions and 4 deletions

View File

@@ -71,7 +71,7 @@ def insert_slop(urls: list[ParseResult], engine: Engine, user: User | None = Non
session.commit() session.commit()
def get_user(email, engine): def get_user(email, engine) -> User:
query = select(User).where(User.email == email) query = select(User).where(User.email == email)
with Session(engine) as session: with Session(engine) as session:
@@ -84,3 +84,9 @@ def create_user(email, password_hash, engine):
with Session(engine) as session: with Session(engine) as session:
session.add(user) session.add(user)
session.commit() session.commit()
def verify_user_email(user: User, engine):
with Session(engine) as session:
session.add(user)
user.email_verified = True
session.commit()

View File

@@ -15,6 +15,7 @@ import uvicorn
from fastapi import Body, Depends, FastAPI, Form, HTTPException, Header from fastapi import Body, Depends, FastAPI, Form, HTTPException, Header
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse
from pydantic import AfterValidator, Base64Str from pydantic import AfterValidator, Base64Str
@@ -32,7 +33,7 @@ from uuid import uuid4
from slopserver.settings import settings from slopserver.settings import settings
from slopserver.models import Domain, Path, User from slopserver.models import Domain, Path, User
from slopserver.models import SlopReport, SignupForm, altcha_validator from slopserver.models import SlopReport, SignupForm, altcha_validator
from slopserver.db import select_slop, insert_slop, get_user, create_user from slopserver.db import select_slop, insert_slop, get_user, create_user, verify_user_email
app = FastAPI() app = FastAPI()
@@ -109,6 +110,13 @@ def verify_auth_token(token: str):
except: except:
raise HTTPException(status_code=401, detail="invalid access token") raise HTTPException(status_code=401, detail="invalid access token")
def verify_verification_token(token: str):
try:
token = jwt.decode(token, TOKEN_SECRET, ALGO)
return token
except:
raise HTTPException(status_code=404, detail="invalid verification URL")
@app.post("/report") @app.post("/report")
def report_slop(report: SlopReport, bearer: Annotated[str, AfterValidator(verify_auth_token), Header()]): def report_slop(report: SlopReport, bearer: Annotated[str, AfterValidator(verify_auth_token), Header()]):
user = get_token_user(bearer) user = get_token_user(bearer)
@@ -141,10 +149,31 @@ def signup_form(form_data: Annotated[SignupForm, Form()]):
# send verification email # send verification email
# create a jwt encoding the username and a time limit to be the verification URL # create a jwt encoding the username and a time limit to be the verification URL
token = generate_verification_token(form_data.email)
return token
@app.get("/verify") @app.get("/verify")
def verify_email(token: str): def verify_email(token: Annotated[str, AfterValidator(verify_verification_token)]):
get_user() user = get_user(token["sub"], DB_ENGINE)
if not user:
raise HTTPException(status_code=404, detail="invalid verification URL")
if user.email_verified:
raise HTTPException(status_code=404, detail="already verified")
verify_user_email(user, DB_ENGINE)
html = f"""
<html>
<head>
</head>
<body>
<p>{token["sub"]} verified. You may log in now.</p>
</body>
</html>
"""
return HTMLResponse(content=html, status_code=200)
@app.get("/altcha-challenge") @app.get("/altcha-challenge")