diff --git a/VERSION b/VERSION index 3d55c7a..91a5166 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3.25 +2.3.26 diff --git a/app/modules/invoice_error_finder/frontend/views.py b/app/modules/invoice_error_finder/frontend/views.py index 9f4e560..a495aa4 100644 --- a/app/modules/invoice_error_finder/frontend/views.py +++ b/app/modules/invoice_error_finder/frontend/views.py @@ -4,10 +4,11 @@ Invoice Error Finder frontend views. import logging from typing import Any, Dict -from fastapi import APIRouter, Request +from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates +from app.core.auth_dependencies import require_permission from app.core.database import execute_query logger = logging.getLogger(__name__) @@ -39,7 +40,10 @@ def _fetch_customers() -> list: @router.get("/invoice-error-finder", response_class=HTMLResponse) -async def dashboard(request: Request): +async def dashboard( + request: Request, + current_user: dict = Depends(require_permission("invoice_error_finder.view")), +): return templates.TemplateResponse( "modules/invoice_error_finder/templates/dashboard.html", { @@ -49,7 +53,10 @@ async def dashboard(request: Request): @router.get("/invoice-error-finder/issues", response_class=HTMLResponse) -async def issues_list(request: Request): +async def issues_list( + request: Request, + current_user: dict = Depends(require_permission("invoice_error_finder.view")), +): return templates.TemplateResponse( "modules/invoice_error_finder/templates/issues.html", { diff --git a/app/modules/invoice_error_finder/templates/dashboard.html b/app/modules/invoice_error_finder/templates/dashboard.html index 0f9f933..9e51b49 100644 --- a/app/modules/invoice_error_finder/templates/dashboard.html +++ b/app/modules/invoice_error_finder/templates/dashboard.html @@ -151,7 +151,22 @@ async function loadDashboard() { try { const res = await fetch('/api/v1/invoice-error-finder/dashboard'); - if (!res.ok) throw new Error('Kunne ikke hente dashboard'); + if (!res.ok) { + let detail = 'Kunne ikke hente dashboard'; + try { + const payload = await res.json(); + if (res.status === 403) { + detail = 'Du mangler adgang til Faktura-fejl-finder'; + } else if (payload?.detail) { + detail = payload.detail; + } + } catch (error) { + if (res.status === 403) { + detail = 'Du mangler adgang til Faktura-fejl-finder'; + } + } + throw new Error(detail); + } const data = await res.json(); document.getElementById('missingLineCount').textContent = data.missing_line?.count ?? 0; diff --git a/migrations/210_invoice_error_finder_import_permission_repair.sql b/migrations/210_invoice_error_finder_import_permission_repair.sql new file mode 100644 index 0000000..2de2987 --- /dev/null +++ b/migrations/210_invoice_error_finder_import_permission_repair.sql @@ -0,0 +1,17 @@ +-- Repair migration: ensure invoice error finder import permission exists on older prod databases +-- and is granted to the intended operator groups. + +INSERT INTO permissions (code, description, category) +VALUES ( + 'invoice_error_finder.run_import', + 'Trigger invoice/error data imports', + 'invoice_error_finder' +) +ON CONFLICT (code) DO NOTHING; + +INSERT INTO group_permissions (group_id, permission_id) +SELECT g.id, p.id +FROM groups g +JOIN permissions p ON p.code = 'invoice_error_finder.run_import' +WHERE g.name IN ('Administrators', 'Managers') +ON CONFLICT DO NOTHING; diff --git a/static/js/bottom-bar.js b/static/js/bottom-bar.js index 1600968..5a9e2f1 100644 --- a/static/js/bottom-bar.js +++ b/static/js/bottom-bar.js @@ -649,7 +649,7 @@ // Primary source: active drift events filtered client-side by blacklist. const [eventsRes, blacklistRes] = await Promise.all([ - fetch('/api/v1/drift/events?status=active&limit=500', { + fetch('/api/v1/drift/events?status=active&limit=200', { credentials: 'include', headers: { 'Accept': 'application/json' } }),