1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
from typing import Annotated
from urllib.parse import urlencode
from fastapi import APIRouter, Depends
from fastapi.responses import HTMLResponse
from generalresearch.models.thl.wallet.cashout_method import CashoutRequestInfo
from jb.api.auth import get_authenticated_user
from jb.api.cashout_token import consume_cashout_token, create_cashout_token
from jb.config import settings
from jb.managers.email_manager import send_cashout_confirmation_email
from jb.managers.thl import user_cashout_request
from jb.models.auth import User
from jb.models.wallet import CashoutConfirmation, CashoutRequest, PendingCashout
from jb.settings import render_base_html
wallet_router = APIRouter(prefix="/wallet", tags=["Wallet"])
@wallet_router.post("/cashout/request/")
def request_cashout(
body: CashoutRequest,
user: Annotated[User, Depends(get_authenticated_user)],
) -> dict[str, str]:
"""Email the authenticated user a link confirming the requested amount."""
token = create_cashout_token(
PendingCashout(
product_user_id=user.product_user_id,
amount=body.amount,
cashout_method_id=body.cashout_method_id,
)
)
query = urlencode({"token": token})
confirmation_link = f"{settings.base_url}wallet/cashout/confirm/?{query}"
if settings.debug:
return {"confirmation_link": confirmation_link}
send_cashout_confirmation_email(email=str(user.email), token=token)
return {"detail": "Confirmation sent. Check your inbox to finish the cashout."}
@wallet_router.get(
"/cashout/confirm/", response_class=HTMLResponse, include_in_schema=False
)
def cashout_confirmation_page() -> HTMLResponse:
"""Serve the SPA without consuming the token; email prefetches are harmless."""
return HTMLResponse(
render_base_html(),
headers={
"Cache-Control": "no-store",
"Referrer-Policy": "no-referrer",
"X-Robots-Tag": "noindex, nofollow",
},
)
@wallet_router.post("/cashout/confirm/", response_model=CashoutRequestInfo)
def confirm_cashout(
body: CashoutConfirmation,
) -> CashoutRequestInfo:
cashout = consume_cashout_token(body.token)
return user_cashout_request(
product_user_id=cashout.product_user_id,
amount=cashout.amount,
cashout_method_id=cashout.cashout_method_id,
)
|