feat: add Tink API request logger
All checks were successful
Build and Deploy / deploy (push) Successful in 21s
All checks were successful
Build and Deploy / deploy (push) Successful in 21s
- TinkClient now accepts on_request callback; all API methods log via shared _get/_post helpers (method, url, req/resp body, status, timing) - _logger(sess) helper creates a session-bound callback (max 50 entries) - All route handlers pass _logger(sess) to _client() - New GET /demo/log — shows all API calls in reverse-chronological order, collapsible req/resp bodies, status + duration badges - New POST /demo/log/clear — clears the log - Navbar gets 'API Log' link (always visible) - _ctx() now applied to ALL template responses (steps 1–6)
This commit is contained in:
@@ -326,7 +326,7 @@ async def step4(request: Request):
|
||||
result = demo_data.MOCK_ACCOUNTS
|
||||
else:
|
||||
try:
|
||||
client = _client()
|
||||
client = _client(log_cb=_logger(sess))
|
||||
result = await client.list_accounts(user_token)
|
||||
# Fall back to demo data if no accounts connected yet
|
||||
if not result.get("accounts"):
|
||||
@@ -335,8 +335,7 @@ async def step4(request: Request):
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
|
||||
return templates.TemplateResponse("step.html", {
|
||||
"request": request,
|
||||
return templates.TemplateResponse("step.html", _ctx(request, {
|
||||
"step": 4,
|
||||
"title": "Konti",
|
||||
"subtitle": "Account List with Balances",
|
||||
@@ -349,7 +348,7 @@ async def step4(request: Request):
|
||||
"is_demo": is_demo or (result == demo_data.MOCK_ACCOUNTS),
|
||||
"next_step": 5,
|
||||
"prev_step": 3,
|
||||
})
|
||||
}))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -376,7 +375,7 @@ async def step5(request: Request, account_id: Optional[str] = None):
|
||||
result = demo_data.MOCK_TRANSACTIONS
|
||||
else:
|
||||
try:
|
||||
client = _client()
|
||||
client = _client(log_cb=_logger(sess))
|
||||
result = await client.list_transactions(user_token, account_id=account_id)
|
||||
if not result.get("transactions"):
|
||||
result = demo_data.MOCK_TRANSACTIONS
|
||||
@@ -384,8 +383,7 @@ async def step5(request: Request, account_id: Optional[str] = None):
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
|
||||
return templates.TemplateResponse("step.html", {
|
||||
"request": request,
|
||||
return templates.TemplateResponse("step.html", _ctx(request, {
|
||||
"step": 5,
|
||||
"title": "Transaktioner",
|
||||
"subtitle": "Transaction History",
|
||||
@@ -398,7 +396,7 @@ async def step5(request: Request, account_id: Optional[str] = None):
|
||||
"is_demo": is_demo or (result == demo_data.MOCK_TRANSACTIONS),
|
||||
"next_step": 6,
|
||||
"prev_step": 4,
|
||||
})
|
||||
}))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -445,7 +443,7 @@ async def step6(request: Request):
|
||||
}
|
||||
else:
|
||||
try:
|
||||
client = _client()
|
||||
client = _client(log_cb=_logger(sess))
|
||||
app_token_resp = await client.get_app_token(scope="user:create")
|
||||
app_token = app_token_resp.get("access_token", "")
|
||||
|
||||
@@ -460,7 +458,6 @@ async def step6(request: Request):
|
||||
except Exception as e:
|
||||
err_str = str(e)
|
||||
if "404" in err_str:
|
||||
# Sandbox doesn't expose webhook management — show sample data instead
|
||||
result_webhooks = {"note": "Webhook API ikke tilgængeligt i sandbox — kun i produktion"}
|
||||
webhook_registered = {
|
||||
"url": webhook_url,
|
||||
@@ -470,8 +467,7 @@ async def step6(request: Request):
|
||||
else:
|
||||
error = err_str
|
||||
|
||||
return templates.TemplateResponse("step6.html", {
|
||||
"request": request,
|
||||
return templates.TemplateResponse("step6.html", _ctx(request, {
|
||||
"step": 6,
|
||||
"title": "Webhooks & Events",
|
||||
"subtitle": "Real-time Event Notifications",
|
||||
@@ -485,7 +481,28 @@ async def step6(request: Request):
|
||||
"app_base_url": s.app_base_url,
|
||||
"next_step": None,
|
||||
"prev_step": 5,
|
||||
})
|
||||
}))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# API Request Log
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@router.get("/demo/log", response_class=HTMLResponse)
|
||||
async def api_log(request: Request):
|
||||
sess = _session(request)
|
||||
log = sess.get("api_log", [])
|
||||
return templates.TemplateResponse("log.html", _ctx(request, {
|
||||
"log": list(reversed(log)), # newest first
|
||||
"log_count": len(log),
|
||||
}))
|
||||
|
||||
|
||||
@router.post("/demo/log/clear")
|
||||
async def clear_log(request: Request):
|
||||
sess = _session(request)
|
||||
sess["api_log"] = []
|
||||
return RedirectResponse("/demo/log", status_code=303)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user