Add FCM device registration and Gitea bug reporter
This commit is contained in:
+29
-1
@@ -30,6 +30,11 @@ from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.exception_handlers import request_validation_exception_handler
|
||||
from feature_schema import FEATURE_SCHEMA
|
||||
import push_devices
|
||||
import bug_reporter
|
||||
from i18n import (
|
||||
LANGUAGE_COOKIE, current_language, current_page, gettext as _,
|
||||
language_url, safe_return_path, format_time, format_datetime,
|
||||
@@ -484,7 +489,7 @@ def ensure_schema():
|
||||
|
||||
with get_db_connection() as connection:
|
||||
with connection.cursor() as cursor:
|
||||
for statement in statements:
|
||||
for statement in [*statements, *FEATURE_SCHEMA]:
|
||||
cursor.execute(statement)
|
||||
|
||||
if INITIAL_ADMIN_USERNAME and INITIAL_ADMIN_PASSWORD:
|
||||
@@ -528,6 +533,13 @@ async def lifespan(_app: FastAPI):
|
||||
app = FastAPI(title="MetalCircle", lifespan=lifespan)
|
||||
|
||||
|
||||
@app.exception_handler(RequestValidationError)
|
||||
async def safe_validation_error(request: Request, exc: RequestValidationError):
|
||||
if request.url.path.startswith('/api/push/'):
|
||||
return JSONResponse({'error': 'invalid_device'}, status_code=422)
|
||||
return await request_validation_exception_handler(request, exc)
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def security_controls(request: Request, call_next):
|
||||
if COOKIE_SECURE and request.url.path not in {"/impressum", "/datenschutz"}:
|
||||
@@ -554,6 +566,8 @@ async def security_controls(request: Request, call_next):
|
||||
bucket_name, limit, window = "account", 10, 60 * 60
|
||||
elif path.startswith("/messages/"):
|
||||
bucket_name, limit, window = "messages", 30, 60
|
||||
elif path == '/bug-report':
|
||||
bucket_name, limit, window = 'bug_reports', 10, 60 * 60
|
||||
elif any(part in path for part in ("/photos", "/patches")) or path in {"/profile", "/concerts"}:
|
||||
bucket_name, limit, window = "uploads", 20, 60 * 60
|
||||
else:
|
||||
@@ -588,6 +602,7 @@ async def require_login(request: Request, call_next):
|
||||
or request.url.path.startswith("/register/")
|
||||
or request.url.path.startswith("/password-reset")
|
||||
or request.url.path in {"/impressum", "/datenschutz"}
|
||||
or request.url.path == '/api/push/session'
|
||||
or request.url.path.startswith("/language/")
|
||||
or request.url.path == "/profile/export"
|
||||
or request.url.path.startswith("/static/")
|
||||
@@ -597,6 +612,8 @@ async def require_login(request: Request, call_next):
|
||||
if get_current_user(request):
|
||||
return await call_next(request)
|
||||
|
||||
if request.url.path.startswith('/api/push/'):
|
||||
return JSONResponse({'error': 'authentication_required'}, status_code=401)
|
||||
return login_redirect("/")
|
||||
|
||||
|
||||
@@ -2475,6 +2492,7 @@ def login_page(request: Request, next: str = "/"):
|
||||
|
||||
@app.post("/login")
|
||||
def login(
|
||||
request: Request,
|
||||
username: str = Form(...),
|
||||
password: str = Form(...),
|
||||
next: str = Form("/"),
|
||||
@@ -2508,6 +2526,12 @@ def login(
|
||||
status_code=401,
|
||||
)
|
||||
|
||||
# Replacing a login revokes the previous session and its push-device bindings.
|
||||
old_token = request.cookies.get(SESSION_COOKIE)
|
||||
if old_token:
|
||||
with get_db_connection() as connection:
|
||||
connection.execute('DELETE FROM sessions WHERE token_hash=%s', (hash_token(old_token),))
|
||||
connection.commit()
|
||||
response = RedirectResponse(next_path, status_code=303)
|
||||
return attach_session(response, create_session(row[0]))
|
||||
|
||||
@@ -5087,3 +5111,7 @@ def search_venues(q: str):
|
||||
unique_results[key] = venue
|
||||
|
||||
return list(unique_results.values())[:10]
|
||||
|
||||
|
||||
push_devices.register_routes(app, get_db_connection, get_current_user, SESSION_COOKIE)
|
||||
bug_reporter.register_routes(app, templates, get_db_connection, get_current_user)
|
||||
|
||||
Reference in New Issue
Block a user