Phase 1 securite: permission checks sur tous les routers
- auth: verification is_active au login (compte desactive = bloque) - settings: enforcement backend can_edit(settings) + role/section - servers: can_view/can_edit(servers) sur toutes les routes - planning: can_view/can_edit(planning) sur toutes les routes - specifics: can_view/can_edit(specifics) sur toutes les routes - contacts: rattache au module servers (can_view/can_edit) - campaigns: can_view/can_edit(campaigns) sur toutes les routes manquantes - audit/audit_full: can_view/can_edit(audit) sur toutes les routes - qualys: can_view/can_edit(qualys) sur toutes les routes - safe_patching: perm checks + authentification sur SSE stream - quickwin: can_view/can_edit(campaigns|quickwin) sur toutes les routes 97 points d'injection securises, 0 route sans controle Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5cc10c5b6c
commit
13290c1ebb
@ -18,6 +18,9 @@ async def audit_page(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "audit"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
where = ["1=1"]
|
||||
params = {}
|
||||
@ -223,6 +226,9 @@ async def audit_realtime_save(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "audit"):
|
||||
return RedirectResponse(url="/audit")
|
||||
|
||||
results = getattr(request.app.state, "last_audit_results", None)
|
||||
if not results:
|
||||
@ -238,6 +244,9 @@ async def audit_export_csv(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "audit"):
|
||||
return RedirectResponse(url="/audit")
|
||||
|
||||
where = ["1=1"]
|
||||
params = {}
|
||||
|
||||
@ -4,7 +4,7 @@ from fastapi import APIRouter, Request, Depends, UploadFile, File
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse, StreamingResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy import text
|
||||
from ..dependencies import get_db, get_current_user, get_user_perms, can_view, base_context
|
||||
from ..dependencies import get_db, get_current_user, get_user_perms, can_view, can_edit, base_context
|
||||
from ..services.server_audit_full_service import (
|
||||
import_json_report, get_latest_audits, get_audit_detail,
|
||||
get_flow_map, get_flow_map_for_server, get_app_map,
|
||||
@ -208,6 +208,9 @@ async def audit_full_import(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "audit"):
|
||||
return RedirectResponse(url="/audit-full")
|
||||
|
||||
try:
|
||||
content = await file.read()
|
||||
@ -229,6 +232,9 @@ async def audit_full_patching(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "audit"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
year = int(request.query_params.get("year", "2026"))
|
||||
search = request.query_params.get("q", "").strip()
|
||||
@ -413,6 +419,9 @@ async def patching_export_csv(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "audit"):
|
||||
return RedirectResponse(url="/audit-full")
|
||||
|
||||
import io, csv
|
||||
year = int(request.query_params.get("year", "2026"))
|
||||
@ -484,6 +493,9 @@ async def audit_full_export_csv(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "audit"):
|
||||
return RedirectResponse(url="/audit-full")
|
||||
|
||||
import io, csv
|
||||
filtre = request.query_params.get("filter", "")
|
||||
@ -558,6 +570,9 @@ async def audit_full_flow_map(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "audit"):
|
||||
return RedirectResponse(url="/audit-full")
|
||||
|
||||
domain_filter = request.query_params.get("domain", "")
|
||||
server_filter = request.query_params.get("server", "").strip()
|
||||
@ -648,6 +663,9 @@ async def audit_full_detail(request: Request, audit_id: int, db=Depends(get_db))
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "audit"):
|
||||
return RedirectResponse(url="/audit-full")
|
||||
|
||||
audit = get_audit_detail(db, audit_id)
|
||||
if not audit:
|
||||
|
||||
@ -18,7 +18,7 @@ async def login_page(request: Request):
|
||||
|
||||
@router.post("/login")
|
||||
async def login(request: Request, username: str = Form(...), password: str = Form(...), db=Depends(get_db)):
|
||||
row = db.execute(text("SELECT id, username, password_hash, role FROM users WHERE LOWER(username) = LOWER(:u)"),
|
||||
row = db.execute(text("SELECT id, username, password_hash, role, is_active FROM users WHERE LOWER(username) = LOWER(:u)"),
|
||||
{"u": username}).fetchone()
|
||||
if not row:
|
||||
log_login_failed(db, request, username)
|
||||
@ -26,6 +26,12 @@ async def login(request: Request, username: str = Form(...), password: str = For
|
||||
return templates.TemplateResponse("login.html", {
|
||||
"request": request, "app_name": APP_NAME, "version": APP_VERSION, "error": "Utilisateur inconnu"
|
||||
})
|
||||
if not row.is_active:
|
||||
log_login_failed(db, request, username)
|
||||
db.commit()
|
||||
return templates.TemplateResponse("login.html", {
|
||||
"request": request, "app_name": APP_NAME, "version": APP_VERSION, "error": "Compte desactive"
|
||||
})
|
||||
try:
|
||||
ok = verify_password(password, row.password_hash)
|
||||
except Exception:
|
||||
|
||||
@ -85,7 +85,10 @@ async def campaign_preview(request: Request, db=Depends(get_db),
|
||||
year: int = Query(...), week: int = Query(...)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorise</p>")
|
||||
return HTMLResponse("<p>Non autorise</p>", status_code=401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
servers, planning = get_servers_for_planning(db, year, week)
|
||||
scope = ", ".join(set(f"{p.domain_name} ({p.env_scope})" for p in planning if p.domain_code))
|
||||
return templates.TemplateResponse("partials/campaign_preview.html", {
|
||||
@ -99,6 +102,9 @@ async def campaign_create(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
form = await request.form()
|
||||
year = int(form.get("year", datetime.now().year))
|
||||
week = int(form.get("week_number", 0))
|
||||
@ -128,6 +134,9 @@ async def campaign_detail(request: Request, campaign_id: int, db=Depends(get_db)
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
campaign = get_campaign(db, campaign_id)
|
||||
if not campaign:
|
||||
return RedirectResponse(url="/campaigns")
|
||||
@ -212,6 +221,9 @@ async def session_prereq(request: Request, session_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
validate_prereq(db, session_id, prereq_ssh, prereq_satellite,
|
||||
rollback_method or None, rollback_justif, user.get("sub"))
|
||||
row = db.execute(text("SELECT campaign_id FROM patch_sessions WHERE id = :id"),
|
||||
@ -224,6 +236,9 @@ async def campaign_check_prereqs(request: Request, campaign_id: int, db=Depends(
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url=f"/campaigns/{campaign_id}")
|
||||
checked, auto_excluded = check_prereqs_campaign(db, campaign_id)
|
||||
log_prereq_check(db, request, user, campaign_id, checked, auto_excluded)
|
||||
db.commit()
|
||||
@ -235,6 +250,9 @@ async def session_check_prereq(request: Request, session_id: int, db=Depends(get
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
check_single_prereq(db, session_id)
|
||||
row = db.execute(text("SELECT campaign_id FROM patch_sessions WHERE id = :id"),
|
||||
{"id": session_id}).fetchone()
|
||||
@ -247,6 +265,9 @@ async def session_exclude(request: Request, session_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
exclude_session(db, session_id, reason, detail, user.get("sub"))
|
||||
row = db.execute(text("SELECT campaign_id FROM patch_sessions WHERE id = :id"),
|
||||
{"id": session_id}).fetchone()
|
||||
@ -258,6 +279,9 @@ async def session_restore(request: Request, session_id: int, db=Depends(get_db))
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
restore_session(db, session_id)
|
||||
row = db.execute(text("SELECT campaign_id FROM patch_sessions WHERE id = :id"),
|
||||
{"id": session_id}).fetchone()
|
||||
@ -272,6 +296,9 @@ async def session_take(request: Request, session_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
row = db.execute(text("SELECT campaign_id, intervenant_id, forced_assignment FROM patch_sessions WHERE id = :id"),
|
||||
{"id": session_id}).fetchone()
|
||||
if row.intervenant_id:
|
||||
@ -292,6 +319,9 @@ async def session_release(request: Request, session_id: int, db=Depends(get_db))
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
if is_forced(db, session_id):
|
||||
row = db.execute(text("SELECT campaign_id FROM patch_sessions WHERE id = :id"),
|
||||
{"id": session_id}).fetchone()
|
||||
@ -309,6 +339,9 @@ async def session_assign(request: Request, session_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
oid = int(operator_id) if operator_id else None
|
||||
is_forced_flag = forced == "on"
|
||||
if oid:
|
||||
@ -329,6 +362,9 @@ async def set_op_limit(request: Request, campaign_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url=f"/campaigns/{campaign_id}")
|
||||
set_operator_limit(db, campaign_id, operator_id, max_servers, note or None)
|
||||
return RedirectResponse(url=f"/campaigns/{campaign_id}?msg=limit_set", status_code=303)
|
||||
|
||||
@ -375,6 +411,9 @@ async def assignment_add(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url="/assignments")
|
||||
try:
|
||||
db.execute(text("""
|
||||
INSERT INTO default_assignments (rule_type, rule_value, user_id, priority, note)
|
||||
@ -393,6 +432,9 @@ async def assignment_delete(request: Request, rule_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url="/assignments")
|
||||
db.execute(text("DELETE FROM default_assignments WHERE id = :id"), {"id": rule_id})
|
||||
db.commit()
|
||||
return RedirectResponse(url="/assignments?msg=deleted", status_code=303)
|
||||
@ -406,6 +448,9 @@ async def bulk_take(request: Request, campaign_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
ids = [int(x) for x in session_ids.split(",") if x.strip().isdigit()]
|
||||
limit = get_operator_limit(db, campaign_id, user.get("uid"))
|
||||
current = get_operator_count(db, campaign_id, user.get("uid"))
|
||||
@ -461,6 +506,9 @@ async def session_schedule(request: Request, session_id: int, db=Depends(get_db)
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url="/campaigns")
|
||||
update_session_schedule(db, session_id, date_prevue or None, heure_prevue or None)
|
||||
row = db.execute(text("SELECT campaign_id FROM patch_sessions WHERE id = :id"),
|
||||
{"id": session_id}).fetchone()
|
||||
|
||||
@ -43,6 +43,9 @@ async def contacts_page(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "servers"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
where = ["1=1"]
|
||||
params = {}
|
||||
@ -170,6 +173,9 @@ async def contact_add(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return RedirectResponse(url="/contacts")
|
||||
try:
|
||||
db.execute(text("""
|
||||
INSERT INTO contacts (name, email, role, is_active)
|
||||
@ -188,6 +194,9 @@ async def contact_edit(request: Request, contact_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return RedirectResponse(url="/contacts")
|
||||
updates = []; params = {"id": contact_id}
|
||||
if name: updates.append("name = :n"); params["n"] = name
|
||||
if email: updates.append("email = :e"); params["e"] = email.lower()
|
||||
@ -203,6 +212,9 @@ async def contact_toggle(request: Request, contact_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return RedirectResponse(url="/contacts")
|
||||
db.execute(text("UPDATE contacts SET is_active = NOT is_active WHERE id = :id"), {"id": contact_id})
|
||||
db.commit()
|
||||
return RedirectResponse(url="/contacts?msg=toggled", status_code=303)
|
||||
@ -215,6 +227,9 @@ async def scope_add(request: Request, contact_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return RedirectResponse(url="/contacts")
|
||||
try:
|
||||
db.execute(text("""
|
||||
INSERT INTO contact_scopes (contact_id, scope_type, scope_value, env_scope)
|
||||
@ -231,6 +246,9 @@ async def scope_delete(request: Request, scope_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return RedirectResponse(url="/contacts")
|
||||
db.execute(text("DELETE FROM contact_scopes WHERE id = :id"), {"id": scope_id})
|
||||
db.commit()
|
||||
return RedirectResponse(url="/contacts?msg=scope_deleted", status_code=303)
|
||||
@ -241,6 +259,9 @@ async def contact_delete(request: Request, contact_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return RedirectResponse(url="/contacts")
|
||||
db.execute(text("DELETE FROM contact_scopes WHERE contact_id = :cid"), {"cid": contact_id})
|
||||
db.execute(text("DELETE FROM contacts WHERE id = :cid"), {"cid": contact_id})
|
||||
db.commit()
|
||||
|
||||
@ -84,6 +84,8 @@ async def planning_page(request: Request, db=Depends(get_db),
|
||||
next_week = 1
|
||||
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "planning"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
return templates.TemplateResponse("planning.html", {
|
||||
"request": request, "user": user, "perms": perms, "app_name": APP_NAME,
|
||||
"year": year, "domains": domains, "grid": grid,
|
||||
@ -104,6 +106,9 @@ async def planning_add(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "planning"):
|
||||
return RedirectResponse(url="/planning")
|
||||
|
||||
y = int(year)
|
||||
wn = int(week_number) if week_number else 0
|
||||
@ -146,6 +151,9 @@ async def planning_edit(request: Request, entry_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "planning"):
|
||||
return RedirectResponse(url="/planning")
|
||||
row = db.execute(text("SELECT year FROM patch_planning WHERE id = :id"), {"id": entry_id}).fetchone()
|
||||
cyc = int(cycle) if cycle.strip() else None
|
||||
db.execute(text("""
|
||||
@ -163,6 +171,9 @@ async def planning_delete(request: Request, entry_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "planning"):
|
||||
return RedirectResponse(url="/planning")
|
||||
row = db.execute(text("SELECT year FROM patch_planning WHERE id = :id"), {"id": entry_id}).fetchone()
|
||||
db.execute(text("DELETE FROM patch_planning WHERE id = :id"), {"id": entry_id})
|
||||
db.commit()
|
||||
@ -177,6 +188,9 @@ async def planning_duplicate(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "planning"):
|
||||
return RedirectResponse(url="/planning")
|
||||
|
||||
# Verifier que l'annee cible est vide
|
||||
existing = db.execute(text("SELECT COUNT(*) FROM patch_planning WHERE year = :y"),
|
||||
|
||||
@ -168,6 +168,9 @@ async def qualys_tags_resync(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
result = resync_all_tags(db)
|
||||
msg = "resync_ok" if result["ok"] else "resync_ko"
|
||||
return RedirectResponse(url=f"/qualys/tags?msg={msg}", status_code=303)
|
||||
@ -179,6 +182,9 @@ async def qualys_tag_create(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
result = create_tag_api(db, tag_name.strip())
|
||||
msg = "created" if result["ok"] else "create_error"
|
||||
return RedirectResponse(url=f"/qualys/tags?msg={msg}", status_code=303)
|
||||
@ -189,6 +195,9 @@ async def qualys_tag_delete(request: Request, tag_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
result = delete_tag_api(db, tag_id)
|
||||
msg = "deleted" if result["ok"] else "delete_error"
|
||||
return RedirectResponse(url=f"/qualys/tags?msg={msg}", status_code=303)
|
||||
@ -200,6 +209,9 @@ async def qualys_asset_tag_add(request: Request, asset_id: int, db=Depends(get_d
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
result = add_tag_to_asset_api(db, asset_id, int(tag_id))
|
||||
color = "text-cyber-green" if result["ok"] else "text-cyber-red"
|
||||
return HTMLResponse(f'<span class="text-xs {color}">{result["msg"]}</span>')
|
||||
@ -211,6 +223,9 @@ async def qualys_asset_tag_remove(request: Request, asset_id: int, db=Depends(ge
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
result = remove_tag_from_asset_api(db, asset_id, int(tag_id))
|
||||
color = "text-cyber-green" if result["ok"] else "text-cyber-red"
|
||||
return HTMLResponse(f'<span class="text-xs {color}">{result["msg"]}</span>')
|
||||
@ -228,6 +243,9 @@ async def qualys_bulk_add_tag(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
form = await request.form()
|
||||
ids = [int(x) for x in form.get("asset_ids", "").split(",") if x.strip().isdigit()]
|
||||
tid = int(form.get("tag_id", "0") or "0")
|
||||
@ -244,6 +262,9 @@ async def qualys_bulk_remove_tag(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
form = await request.form()
|
||||
ids = [int(x) for x in form.get("asset_ids", "").split(",") if x.strip().isdigit()]
|
||||
tid = int(form.get("tag_id", "0") or "0")
|
||||
@ -260,6 +281,9 @@ async def qualys_resync_assets(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/search")
|
||||
form = await request.form()
|
||||
ids = [int(x) for x in form.get("asset_ids", "").split(",") if x.strip().isdigit()]
|
||||
ok = 0
|
||||
@ -303,6 +327,9 @@ async def qualys_tags_export(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/tags")
|
||||
tags = db.execute(text("SELECT * FROM qualys_tags ORDER BY name")).fetchall()
|
||||
output = io.StringIO()
|
||||
writer = csv.writer(output, delimiter=";")
|
||||
@ -484,6 +511,9 @@ async def export_no_agent_csv(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/agents")
|
||||
import io, csv as _csv
|
||||
rows = db.execute(text("""
|
||||
SELECT s.hostname, s.os_family, s.etat, d.name as domain, e.name as env, z.name as zone
|
||||
@ -512,6 +542,9 @@ async def export_inactive_csv(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "qualys"):
|
||||
return RedirectResponse(url="/qualys/agents")
|
||||
import io, csv as _csv
|
||||
rows = db.execute(text("""
|
||||
SELECT qa.hostname, qa.os, qa.agent_version, qa.last_checkin, s.etat
|
||||
@ -536,7 +569,10 @@ async def qualys_vulns_detail(request: Request, ip: str, db=Depends(get_db)):
|
||||
"""Retourne le detail des vulns severity 3,4,5 pour une IP (fragment HTMX)"""
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorise</p>")
|
||||
return HTMLResponse("<p>Non autorise</p>", status_code=401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "qualys"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
|
||||
# Cache 10 min
|
||||
from ..services import cache as _cache
|
||||
@ -693,7 +729,10 @@ async def qualys_vulns_detail(request: Request, ip: str, db=Depends(get_db)):
|
||||
async def qualys_asset_detail(request: Request, asset_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorisé</p>")
|
||||
return HTMLResponse("<p>Non autorisé</p>", status_code=401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "qualys"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
|
||||
asset = db.execute(text("SELECT * FROM qualys_assets WHERE qualys_asset_id = :aid"),
|
||||
{"aid": asset_id}).fetchone()
|
||||
|
||||
@ -108,6 +108,9 @@ async def quickwin_config_save(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns") and not can_edit(perms, "quickwin"):
|
||||
return RedirectResponse(url="/quickwin/config")
|
||||
if server_id:
|
||||
upsert_server_config(db, server_id, general_excludes.strip(),
|
||||
specific_excludes.strip(), notes.strip())
|
||||
@ -120,6 +123,9 @@ async def quickwin_config_delete(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns") and not can_edit(perms, "quickwin"):
|
||||
return RedirectResponse(url="/quickwin/config")
|
||||
if config_id:
|
||||
delete_server_config(db, config_id)
|
||||
return RedirectResponse(url="/quickwin/config?msg=deleted", status_code=303)
|
||||
@ -133,6 +139,9 @@ async def quickwin_config_bulk_add(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns") and not can_edit(perms, "quickwin"):
|
||||
return RedirectResponse(url="/quickwin/config")
|
||||
ids = [int(x) for x in server_ids.split(",") if x.strip().isdigit()]
|
||||
for sid in ids:
|
||||
upsert_server_config(db, sid, general_excludes.strip(), "", "")
|
||||
@ -189,6 +198,9 @@ async def quickwin_detail(request: Request, run_id: int, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns") and not can_view(perms, "quickwin"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
run = get_run(db, run_id)
|
||||
if not run:
|
||||
@ -265,6 +277,9 @@ async def quickwin_entry_update(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return JSONResponse({"error": "unauthorized"}, 401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns") and not can_edit(perms, "quickwin"):
|
||||
return JSONResponse({"error": "forbidden"}, 403)
|
||||
body = await request.json()
|
||||
entry_id = body.get("id")
|
||||
field = body.get("field")
|
||||
@ -280,6 +295,9 @@ async def quickwin_inject_yum(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return JSONResponse({"error": "unauthorized"}, 401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return JSONResponse({"error": "forbidden"}, 403)
|
||||
body = await request.json()
|
||||
if not isinstance(body, list):
|
||||
return JSONResponse({"error": "expected list"}, 400)
|
||||
@ -293,5 +311,8 @@ async def quickwin_prod_check(request: Request, run_id: int, db=Depends(get_db))
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return JSONResponse({"error": "unauthorized"}, 401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns") and not can_view(perms, "quickwin"):
|
||||
return JSONResponse({"error": "forbidden"}, 403)
|
||||
ok = can_start_prod(db, run_id)
|
||||
return JSONResponse({"can_start_prod": ok})
|
||||
|
||||
@ -89,6 +89,9 @@ async def safe_patching_detail(request: Request, campaign_id: int, db=Depends(ge
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
campaign = get_campaign(db, campaign_id)
|
||||
if not campaign:
|
||||
@ -148,6 +151,9 @@ async def safe_patching_check_prereqs(request: Request, campaign_id: int, db=Dep
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url=f"/safe-patching/{campaign_id}")
|
||||
from ..services.prereq_service import check_prereqs_campaign
|
||||
checked, auto_excluded = check_prereqs_campaign(db, campaign_id)
|
||||
return RedirectResponse(url=f"/safe-patching/{campaign_id}?step=prereqs&msg=prereqs_done", status_code=303)
|
||||
@ -159,6 +165,9 @@ async def safe_patching_bulk_exclude(request: Request, campaign_id: int, db=Depe
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url=f"/safe-patching/{campaign_id}")
|
||||
from ..services.campaign_service import exclude_session
|
||||
ids = [int(x) for x in session_ids.split(",") if x.strip().isdigit()]
|
||||
for sid in ids:
|
||||
@ -173,6 +182,9 @@ async def safe_patching_execute(request: Request, campaign_id: int, db=Depends(g
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "campaigns"):
|
||||
return RedirectResponse(url=f"/safe-patching/{campaign_id}")
|
||||
|
||||
# Récupérer les sessions pending de la branche
|
||||
if branch == "hprod":
|
||||
@ -215,6 +227,9 @@ async def safe_patching_terminal(request: Request, campaign_id: int, db=Depends(
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "campaigns"):
|
||||
return RedirectResponse(url="/safe-patching")
|
||||
campaign = get_campaign(db, campaign_id)
|
||||
ctx = base_context(request, db, user)
|
||||
ctx.update({"app_name": APP_NAME, "c": campaign, "branch": branch})
|
||||
@ -222,8 +237,11 @@ async def safe_patching_terminal(request: Request, campaign_id: int, db=Depends(
|
||||
|
||||
|
||||
@router.get("/safe-patching/{campaign_id}/stream")
|
||||
async def safe_patching_stream(request: Request, campaign_id: int):
|
||||
async def safe_patching_stream(request: Request, campaign_id: int, db=Depends(get_db)):
|
||||
"""SSE endpoint — stream les logs en temps réel"""
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return StreamingResponse(iter([]), media_type="text/event-stream")
|
||||
async def event_generator():
|
||||
q = get_stream(campaign_id)
|
||||
while True:
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
from fastapi import APIRouter, Request, Depends, Query, Form
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse, StreamingResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from ..dependencies import get_db, get_current_user
|
||||
from ..dependencies import get_db, get_current_user, get_user_perms, can_view, can_edit
|
||||
from ..services.server_service import (
|
||||
get_server_full, get_server_tags, get_server_ips,
|
||||
list_servers, update_server, get_reference_data
|
||||
@ -24,6 +24,9 @@ async def servers_list(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "servers"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
|
||||
filters = {"domain": domain, "env": env, "tier": tier, "etat": etat, "os": os, "owner": owner, "search": search}
|
||||
servers, total = list_servers(db, filters, page, sort=sort, sort_dir=sort_dir)
|
||||
@ -47,6 +50,9 @@ async def servers_export_csv(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "servers"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
import io, csv
|
||||
filters = {"domain": domain, "env": env, "tier": tier, "etat": etat, "os": os, "owner": owner, "search": search}
|
||||
servers, total = list_servers(db, filters, page=1, per_page=99999, sort="hostname", sort_dir="asc")
|
||||
@ -72,7 +78,10 @@ async def servers_export_csv(request: Request, db=Depends(get_db),
|
||||
async def server_detail(request: Request, server_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorise</p>")
|
||||
return HTMLResponse("<p>Non autorise</p>", status_code=401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "servers"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
s = get_server_full(db, server_id)
|
||||
if not s:
|
||||
return HTMLResponse("<p>Serveur non trouve</p>")
|
||||
@ -87,7 +96,10 @@ async def server_detail(request: Request, server_id: int, db=Depends(get_db)):
|
||||
async def server_edit(request: Request, server_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorise</p>")
|
||||
return HTMLResponse("<p>Non autorise</p>", status_code=401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
s = get_server_full(db, server_id)
|
||||
if not s:
|
||||
return HTMLResponse("<p>Serveur non trouve</p>")
|
||||
@ -111,7 +123,10 @@ async def server_update(request: Request, server_id: int, db=Depends(get_db),
|
||||
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorise</p>")
|
||||
return HTMLResponse("<p>Non autorise</p>", status_code=401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
|
||||
data = {
|
||||
"domain_code": domain_code, "env_code": env_code, "zone": zone,
|
||||
@ -139,6 +154,9 @@ async def servers_bulk(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return RedirectResponse(url="/servers", status_code=303)
|
||||
if not server_ids or not bulk_field or not bulk_value:
|
||||
return RedirectResponse(url="/servers", status_code=303)
|
||||
|
||||
@ -189,7 +207,10 @@ async def servers_bulk(request: Request, db=Depends(get_db),
|
||||
async def server_sync_qualys(request: Request, server_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorise</p>")
|
||||
return HTMLResponse("<p>Non autorise</p>", status_code=401)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "servers"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
result = sync_server_qualys(db, server_id)
|
||||
s = get_server_full(db, server_id)
|
||||
tags = get_server_tags(db, s.qid) if s else []
|
||||
|
||||
@ -3,7 +3,7 @@ from fastapi import APIRouter, Request, Depends, Form
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy import text
|
||||
from ..dependencies import get_db, get_current_user
|
||||
from ..dependencies import get_db, get_current_user, get_user_perms, can_view, can_edit
|
||||
from ..services.secrets_service import get_secret, set_secret, list_secrets, init_secrets_from_config
|
||||
from ..config import APP_NAME
|
||||
|
||||
@ -134,6 +134,9 @@ async def settings_page(request: Request, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "settings"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
ctx = _build_context(db, user)
|
||||
ctx["request"] = request
|
||||
return templates.TemplateResponse("settings.html", ctx)
|
||||
@ -146,6 +149,12 @@ async def settings_save(request: Request, section: str, db=Depends(get_db)):
|
||||
return RedirectResponse(url="/login")
|
||||
if section not in SECTIONS:
|
||||
return HTMLResponse("<p>Section inconnue</p>", status_code=400)
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "settings"):
|
||||
return RedirectResponse(url="/settings")
|
||||
role = user.get("role", "viewer")
|
||||
if section in SECTION_ACCESS and role not in SECTION_ACCESS[section]["editable"]:
|
||||
return RedirectResponse(url="/settings")
|
||||
|
||||
form = await request.form()
|
||||
for key, label, is_secret in SECTIONS[section]:
|
||||
@ -174,6 +183,9 @@ async def vcenter_add(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "settings"):
|
||||
return RedirectResponse(url="/settings")
|
||||
db.execute(text(
|
||||
"INSERT INTO vcenters (name, endpoint, datacenter, description, responsable) VALUES (:n, :e, :dc, :desc, :resp)"
|
||||
), {"n": vc_name, "e": vc_endpoint, "dc": vc_datacenter or None, "desc": vc_description or None, "resp": vc_responsable or None})
|
||||
@ -188,6 +200,9 @@ async def vcenter_delete(request: Request, vc_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "settings"):
|
||||
return RedirectResponse(url="/settings")
|
||||
db.execute(text("UPDATE vcenters SET is_active = false WHERE id = :id"), {"id": vc_id})
|
||||
db.commit()
|
||||
ctx = _build_context(db, user, saved="vsphere")
|
||||
@ -203,6 +218,9 @@ async def secret_update(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "settings"):
|
||||
return RedirectResponse(url="/settings")
|
||||
if secret_value and secret_value != "********":
|
||||
# Recuperer la description existante
|
||||
existing = db.execute(text("SELECT description FROM app_secrets WHERE key = :k"),
|
||||
@ -240,6 +258,9 @@ async def network_add(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "settings"):
|
||||
return RedirectResponse(url="/settings")
|
||||
db.execute(text("INSERT INTO allowed_networks (cidr, description) VALUES (:c, :d)"),
|
||||
{"c": cidr.strip(), "d": description or None})
|
||||
db.commit()
|
||||
@ -254,6 +275,9 @@ async def network_delete(request: Request, net_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "settings"):
|
||||
return RedirectResponse(url="/settings")
|
||||
db.execute(text("DELETE FROM allowed_networks WHERE id = :id"), {"id": net_id})
|
||||
db.commit()
|
||||
_regen_nginx_acl(db)
|
||||
@ -267,6 +291,9 @@ async def network_toggle(request: Request, net_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "settings"):
|
||||
return RedirectResponse(url="/settings")
|
||||
db.execute(text("UPDATE allowed_networks SET is_active = NOT is_active WHERE id = :id"), {"id": net_id})
|
||||
db.commit()
|
||||
_regen_nginx_acl(db)
|
||||
|
||||
@ -47,6 +47,9 @@ async def specifics_list(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_view(perms, "specifics"):
|
||||
return RedirectResponse(url="/dashboard")
|
||||
entries = _list_specifics(db, app_type, search)
|
||||
# Types en base
|
||||
types_in_db = db.execute(text(
|
||||
@ -65,6 +68,9 @@ async def specific_edit(request: Request, spec_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return HTMLResponse("<p>Non autorise</p>")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "specifics"):
|
||||
return HTMLResponse("<p>Acces interdit</p>", status_code=403)
|
||||
row = db.execute(text("""
|
||||
SELECT ss.*, s.hostname FROM server_specifics ss
|
||||
JOIN servers s ON ss.server_id = s.id WHERE ss.id = :id
|
||||
@ -81,6 +87,9 @@ async def specific_save(request: Request, spec_id: int, db=Depends(get_db)):
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "specifics"):
|
||||
return RedirectResponse(url="/specifics")
|
||||
form = await request.form()
|
||||
|
||||
def val(k): v = form.get(k, ""); return v.strip() if v else None
|
||||
@ -147,6 +156,9 @@ async def specific_add(request: Request, db=Depends(get_db),
|
||||
user = get_current_user(request)
|
||||
if not user:
|
||||
return RedirectResponse(url="/login")
|
||||
perms = get_user_perms(db, user)
|
||||
if not can_edit(perms, "specifics"):
|
||||
return RedirectResponse(url="/specifics")
|
||||
row = db.execute(text("SELECT id FROM servers WHERE LOWER(hostname) = LOWER(:h)"),
|
||||
{"h": hostname.strip()}).fetchone()
|
||||
if not row:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user