## Copyright © 2026 Olaf Kolkman ## SPDX-License-Identifier: GPL-3.0-or-later from urllib.parse import quote from urllib.error import HTTPError from fastapi import APIRouter, Depends, HTTPException from fastapi.responses import RedirectResponse from starlette.requests import Request from backend.app.api.dependencies import get_current_user from backend.app.services.mastodon_oauth import finish_authorization, start_authorization from backend.app.core.errors import public_error, redacted_error, request_id import logging router = APIRouter() logger = logging.getLogger(__name__) @router.get('/oauth/start') def oauth_start(request: Request, instance: str = 'mastodon.social', user: dict = Depends(get_current_user)): try: authorization_url = start_authorization(user['id'], instance) except HTTPError as error: retry_after = error.headers.get('Retry-After') if error.headers else None headers = {'Retry-After': retry_after} if retry_after else None raise HTTPException( status_code=error.code, detail=f'Mastodon returned HTTP {error.code} while registering LinkLog. Try again later.', headers=headers, ) from error except Exception as error: logger.error('Mastodon registration failed request_id=%s error=%s', request_id(request), redacted_error(error)) raise HTTPException(status_code=502, detail=public_error(request, 'Could not register with Mastodon.')) from error return {'authorization_url': authorization_url} @router.get('/oauth/callback') def oauth_callback(request: Request, code: str | None = None, state: str | None = None, error: str | None = None): if error or not code or not state: return RedirectResponse(f'/profile?mastodon_error={quote(error or "Authorization was cancelled")}') try: finish_authorization(code, state) except Exception as callback_error: logger.error('Mastodon callback failed request_id=%s error=%s', request_id(request), redacted_error(callback_error)) return RedirectResponse(f'/profile?mastodon_error={quote(public_error(request, "Could not complete Mastodon authorization."))}') return RedirectResponse('/profile?mastodon=connected')