119 lines
4.2 KiB
Python
119 lines
4.2 KiB
Python
## Copyright © 2026 Olaf Kolkman
|
|
## SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from fastapi import FastAPI, Request
|
|
import logging
|
|
from uuid import uuid4
|
|
from fastapi.responses import HTMLResponse
|
|
from fastapi.responses import RedirectResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
from fastapi.templating import Jinja2Templates
|
|
from starlette.requests import Request
|
|
|
|
from backend.app.api.admin import router as admin_router
|
|
from backend.app.api.auth import router as auth_router
|
|
from backend.app.api.links import router as links_router
|
|
from backend.app.api.mastodon import router as mastodon_router
|
|
from backend.app.api.public import router as public_router
|
|
from backend.app.api.setup import router as setup_router
|
|
from backend.app.api.setup import has_administrator
|
|
from backend.app.api.user_config import router as user_config_router
|
|
from backend.app.core.config import settings, validate_configuration
|
|
from backend.app.database import AVATARS_DIR
|
|
from backend.app.services.link_service import get_public_profile, list_public_links
|
|
|
|
logging.basicConfig(level=getattr(logging, settings.log_level, logging.INFO))
|
|
validate_configuration(settings)
|
|
|
|
app = FastAPI(title='LinkLog API', version=settings.version)
|
|
|
|
|
|
@app.middleware('http')
|
|
async def add_request_id(request: Request, call_next):
|
|
request.state.request_id = request.headers.get('X-Request-ID') or str(uuid4())
|
|
response = await call_next(request)
|
|
response.headers['X-Request-ID'] = request.state.request_id
|
|
return response
|
|
|
|
app.mount('/static', StaticFiles(directory='frontend/static'), name='static')
|
|
app.mount('/media', StaticFiles(directory=AVATARS_DIR), name='media')
|
|
app.include_router(auth_router, prefix='/api/auth')
|
|
app.include_router(links_router, prefix='/api')
|
|
app.include_router(mastodon_router, prefix='/api/mastodon')
|
|
app.include_router(public_router, prefix='/api/public')
|
|
app.include_router(admin_router, prefix='/api/admin')
|
|
app.include_router(user_config_router, prefix='/api/user')
|
|
app.include_router(setup_router, prefix='/api/setup')
|
|
|
|
templates = Jinja2Templates(directory='frontend/templates')
|
|
|
|
|
|
@app.get('/', response_class=HTMLResponse)
|
|
async def public_root(request: Request):
|
|
if not has_administrator():
|
|
return RedirectResponse('/setup')
|
|
feed = list_public_links()
|
|
return templates.TemplateResponse(request, 'feed.html', {'feed': feed})
|
|
|
|
|
|
@app.get('/admin', response_class=HTMLResponse)
|
|
async def admin_dashboard(request: Request):
|
|
if not has_administrator():
|
|
return RedirectResponse('/setup')
|
|
return templates.TemplateResponse(request, 'admin.html', {})
|
|
|
|
|
|
@app.get('/profile', response_class=HTMLResponse)
|
|
async def user_profile_page(request: Request):
|
|
if not has_administrator():
|
|
return RedirectResponse('/setup')
|
|
return templates.TemplateResponse(request, 'user_profile.html', {})
|
|
|
|
|
|
@app.get('/labels', response_class=HTMLResponse)
|
|
async def labels_page(request: Request):
|
|
if not has_administrator():
|
|
return RedirectResponse('/setup')
|
|
return templates.TemplateResponse(request, 'labels.html', {})
|
|
|
|
|
|
@app.get('/about', response_class=HTMLResponse)
|
|
async def about_page(request: Request):
|
|
return templates.TemplateResponse(request, 'about.html', {})
|
|
|
|
|
|
@app.get('/login', response_class=HTMLResponse)
|
|
async def login_page(request: Request):
|
|
if not has_administrator():
|
|
return RedirectResponse('/setup')
|
|
return templates.TemplateResponse(request, 'login.html', {})
|
|
|
|
|
|
@app.get('/reset-password', response_class=HTMLResponse)
|
|
async def reset_password_page(request: Request):
|
|
return templates.TemplateResponse(request, 'reset-password.html', {})
|
|
|
|
|
|
@app.get('/setup', response_class=HTMLResponse)
|
|
async def setup_page(request: Request):
|
|
if has_administrator():
|
|
return RedirectResponse('/')
|
|
return templates.TemplateResponse(request, 'setup.html', {})
|
|
|
|
|
|
@app.get('/health')
|
|
def health_check():
|
|
return {'status': 'ok'}
|
|
|
|
|
|
@app.get('/{username}', response_class=HTMLResponse)
|
|
@app.get('/{username}/', response_class=HTMLResponse)
|
|
async def public_user_feed(request: Request, username: str):
|
|
feed = list_public_links(username)
|
|
profile = get_public_profile(username)
|
|
return templates.TemplateResponse(
|
|
request,
|
|
'feed.html',
|
|
{'feed': feed, 'profile': profile, 'user_filter': username},
|
|
)
|