Restrict editor role navigation

This commit is contained in:
Your Name
2026-07-22 22:07:58 +05:00
parent a251a343bd
commit 184ccb55fb
2 changed files with 33 additions and 1 deletions
+29 -1
View File
@@ -16,7 +16,7 @@ from zoneinfo import ZoneInfo
import aiohttp
from fastapi import FastAPI, File, Form, Request, UploadFile, status
from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse
from fastapi.responses import FileResponse, HTMLResponse, JSONResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from loguru import logger
@@ -449,6 +449,34 @@ def base_context(request: Request, user: dict | None, **extra: Any) -> dict[str,
return ctx
EDITOR_ALLOWED_PATHS = (
"/",
"/raw",
"/editor",
"/sources",
"/uploads",
"/logout",
"/login",
"/favi.png",
"/favicon.ico",
"/health",
)
def is_editor_allowed_path(path: str) -> bool:
return any(path == allowed or path.startswith(f"{allowed}/") for allowed in EDITOR_ALLOWED_PATHS if allowed != "/") or path == "/"
@app.middleware("http")
async def restrict_editor_access(request: Request, call_next):
user = await get_current_user(request)
if user and user.get("role") == "editor" and not is_editor_allowed_path(request.url.path):
if request.method == "GET" and not request.headers.get("hx-request"):
return redirect("/raw")
return JSONResponse({"detail": "Forbidden"}, status_code=status.HTTP_403_FORBIDDEN)
return await call_next(request)
def client_ip(request: Request) -> str:
forwarded = request.headers.get("x-forwarded-for", "")
if forwarded:
+4
View File
@@ -178,6 +178,7 @@
<i data-lucide="database" class="w-5 h-5"></i>
Источники
</a>
{% if user.role != "editor" %}
<a href="/workers" class="flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-colors {{ 'bg-app-primary/10 text-app-primary' if 'workers' in request.url.path else 'text-app-textMuted hover:bg-app-surfaceHover hover:text-app-textMain' }}">
<i data-lucide="cpu" class="w-5 h-5"></i>
Воркеры
@@ -190,6 +191,7 @@
<i data-lucide="file-text" class="w-5 h-5"></i>
Логи
</a>
{% endif %}
</nav>
<div class="p-4 border-t border-app-border">
@@ -228,7 +230,9 @@
<a href="/raw" class="block px-3 py-2 rounded-lg text-sm {{ 'bg-app-bg text-app-textMain' if 'raw' in request.url.path else 'text-app-textMuted' }}">Сырые посты</a>
<a href="/editor" class="block px-3 py-2 rounded-lg text-sm {{ 'bg-app-bg text-app-textMain' if 'editor' in request.url.path else 'text-app-textMuted' }}">Редактор</a>
<a href="/sources" class="block px-3 py-2 rounded-lg text-sm {{ 'bg-app-bg text-app-textMain' if 'sources' in request.url.path else 'text-app-textMuted' }}">Источники</a>
{% if user.role != "editor" %}
<a href="/workers" class="block px-3 py-2 rounded-lg text-sm {{ 'bg-app-bg text-app-textMain' if 'workers' in request.url.path else 'text-app-textMuted' }}">Воркеры</a>
{% endif %}
<div class="pt-2 mt-2 border-t border-app-border">
<form method="post" action="/logout" class="m-0">
<input type="hidden" name="csrf_token" value="{{ user.csrf_token }}">