Phase 3 harden CSRF invalid POST and work access handling
This commit is contained in:
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from fastapi import APIRouter, Form, Request
|
from fastapi import APIRouter, Form, Request
|
||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
|
from app.core.http_responses import not_found_response
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
|
||||||
from app.core.db.common import CommonSessionLocal
|
from app.core.db.common import CommonSessionLocal
|
||||||
@@ -17,6 +18,12 @@ from app.modules.core.rbac.services import build_permissions_payload, build_role
|
|||||||
router = APIRouter(prefix="/system-settings/rbac", tags=["rbac-ui"])
|
router = APIRouter(prefix="/system-settings/rbac", tags=["rbac-ui"])
|
||||||
|
|
||||||
|
|
||||||
|
def _csrf_rejected(request: Request):
|
||||||
|
from app.core.http_responses import forbidden_response
|
||||||
|
return forbidden_response(request, "CSRF validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _redirect_login():
|
def _redirect_login():
|
||||||
return RedirectResponse(url="/login", status_code=303)
|
return RedirectResponse(url="/login", status_code=303)
|
||||||
|
|
||||||
@@ -47,6 +54,15 @@ def rbac_dashboard(request: Request):
|
|||||||
return RedirectResponse(url="/system-settings/rbac/roles", status_code=303)
|
return RedirectResponse(url="/system-settings/rbac/roles", status_code=303)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Phase 3 security hardening: the roles list endpoint must not accept direct unsafe POSTs.
|
||||||
|
# Existing role creation continues to use /roles/new.
|
||||||
|
@router.post("/roles")
|
||||||
|
def roles_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/roles")
|
@router.get("/roles")
|
||||||
def roles_list(request: Request, q: str = "", page: int = 1, per_page: int = 10):
|
def roles_list(request: Request, q: str = "", page: int = 1, per_page: int = 10):
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
@@ -76,7 +92,10 @@ def role_create_submit(
|
|||||||
is_active: str | None = Form(None),
|
is_active: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -124,7 +143,7 @@ def role_permissions_edit(request: Request, role_id: int):
|
|||||||
|
|
||||||
role = db.execute(select(Role).where(Role.id == role_id)).scalar_one_or_none()
|
role = db.execute(select(Role).where(Role.id == role_id)).scalar_one_or_none()
|
||||||
if not role:
|
if not role:
|
||||||
return RedirectResponse(url="/system-settings/rbac/roles", status_code=303)
|
return not_found_response(request, "Role not found")
|
||||||
|
|
||||||
scope = build_scope(db, current_user)
|
scope = build_scope(db, current_user)
|
||||||
try:
|
try:
|
||||||
@@ -160,7 +179,10 @@ def role_permissions_submit(
|
|||||||
permission_ids: list[int] = Form([]),
|
permission_ids: list[int] = Form([]),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -172,7 +194,7 @@ def role_permissions_submit(
|
|||||||
|
|
||||||
role = db.execute(select(Role).where(Role.id == role_id)).scalar_one_or_none()
|
role = db.execute(select(Role).where(Role.id == role_id)).scalar_one_or_none()
|
||||||
if not role:
|
if not role:
|
||||||
return RedirectResponse(url="/system-settings/rbac/roles", status_code=303)
|
return not_found_response(request, "Role not found")
|
||||||
|
|
||||||
old_permission_ids = db.execute(
|
old_permission_ids = db.execute(
|
||||||
select(RolePermission.permission_id).where(RolePermission.role_id == role.id)
|
select(RolePermission.permission_id).where(RolePermission.role_id == role.id)
|
||||||
@@ -233,7 +255,10 @@ def permission_create_submit(
|
|||||||
is_active: str | None = Form(None),
|
is_active: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -265,4 +290,4 @@ def permission_create_submit(
|
|||||||
|
|
||||||
return RedirectResponse(url="/system-settings/rbac/permissions", status_code=303)
|
return RedirectResponse(url="/system-settings/rbac/permissions", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
db.close()
|
db.close()
|
||||||
|
|||||||
+213
-48
@@ -135,6 +135,12 @@ from app.modules.employees.service import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
router = APIRouter(prefix="/employees", tags=["employees-ui"])
|
router = APIRouter(prefix="/employees", tags=["employees-ui"])
|
||||||
|
|
||||||
|
|
||||||
|
def _csrf_rejected(request: Request):
|
||||||
|
from app.core.http_responses import forbidden_response
|
||||||
|
return forbidden_response(request, "CSRF validation failed")
|
||||||
|
|
||||||
portal_router = APIRouter(prefix="/employee", tags=["employee-portal-ui"])
|
portal_router = APIRouter(prefix="/employee", tags=["employee-portal-ui"])
|
||||||
|
|
||||||
|
|
||||||
@@ -416,7 +422,10 @@ def employee_new(request: Request):
|
|||||||
@router.post("/new")
|
@router.post("/new")
|
||||||
async def employee_create_submit(request: Request):
|
async def employee_create_submit(request: Request):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -447,6 +456,21 @@ async def employee_create_submit(request: Request):
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Phase 3 security hardening: list pages must not accept direct unsafe POSTs.
|
||||||
|
# Existing attendance and leave actions continue to use their dedicated action routes.
|
||||||
|
@router.post("/attendance")
|
||||||
|
def employee_attendance_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/leaves")
|
||||||
|
@router.post("/leave")
|
||||||
|
def employee_leave_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/attendance")
|
@router.get("/attendance")
|
||||||
def employees_attendance_list(
|
def employees_attendance_list(
|
||||||
request: Request,
|
request: Request,
|
||||||
@@ -506,7 +530,10 @@ def employees_attendance_manual_submit(
|
|||||||
remarks: str | None = Form(None),
|
remarks: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -541,7 +568,10 @@ def employees_attendance_review_submit(
|
|||||||
review_notes: str | None = Form(None),
|
review_notes: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -583,7 +613,10 @@ def employee_leave_types(request: Request, include_inactive: str | None = None):
|
|||||||
|
|
||||||
@router.post("/leave-types/defaults")
|
@router.post("/leave-types/defaults")
|
||||||
def employee_leave_type_defaults(request: Request, csrf_token: str = Form(...)):
|
def employee_leave_type_defaults(request: Request, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -604,7 +637,10 @@ def employee_leave_type_defaults(request: Request, csrf_token: str = Form(...)):
|
|||||||
|
|
||||||
@router.post("/leave-types/new")
|
@router.post("/leave-types/new")
|
||||||
def employee_leave_type_create(request: Request, code: str = Form(...), name: str = Form(...), description: str | None = Form(None), annual_quota_days: int = Form(0), carry_forward_allowed: str | None = Form(None), allow_negative_balance: str | None = Form(None), requires_approval: str | None = Form(None), is_paid: str | None = Form(None), is_active: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_leave_type_create(request: Request, code: str = Form(...), name: str = Form(...), description: str | None = Form(None), annual_quota_days: int = Form(0), carry_forward_allowed: str | None = Form(None), allow_negative_balance: str | None = Form(None), requires_approval: str | None = Form(None), is_paid: str | None = Form(None), is_active: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -625,7 +661,10 @@ def employee_leave_type_create(request: Request, code: str = Form(...), name: st
|
|||||||
|
|
||||||
@router.post("/leave-types/{leave_type_id}/edit")
|
@router.post("/leave-types/{leave_type_id}/edit")
|
||||||
def employee_leave_type_edit(request: Request, leave_type_id: int, name: str = Form(...), description: str | None = Form(None), annual_quota_days: int = Form(0), carry_forward_allowed: str | None = Form(None), allow_negative_balance: str | None = Form(None), requires_approval: str | None = Form(None), is_paid: str | None = Form(None), is_active: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_leave_type_edit(request: Request, leave_type_id: int, name: str = Form(...), description: str | None = Form(None), annual_quota_days: int = Form(0), carry_forward_allowed: str | None = Form(None), allow_negative_balance: str | None = Form(None), requires_approval: str | None = Form(None), is_paid: str | None = Form(None), is_active: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -669,7 +708,10 @@ def employee_leave_balances(request: Request, employee_id: int | None = None):
|
|||||||
|
|
||||||
@router.post("/leave-balances/adjust")
|
@router.post("/leave-balances/adjust")
|
||||||
def employee_leave_balance_adjust(request: Request, employee_id: int = Form(...), leave_type_id: int = Form(...), adjusted_days: int = Form(0), notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_leave_balance_adjust(request: Request, employee_id: int = Form(...), leave_type_id: int = Form(...), adjusted_days: int = Form(0), notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -712,7 +754,10 @@ def employee_leave_requests(request: Request, employee_id: int | None = None, st
|
|||||||
|
|
||||||
@router.post("/leave/{request_id}/review")
|
@router.post("/leave/{request_id}/review")
|
||||||
def employee_leave_review_submit(request: Request, request_id: int, status: str = Form(...), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_leave_review_submit(request: Request, request_id: int, status: str = Form(...), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -798,7 +843,10 @@ def employee_registration_request_approve(
|
|||||||
review_notes: str | None = Form(None),
|
review_notes: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -825,7 +873,10 @@ def employee_registration_request_reject(
|
|||||||
review_notes: str | None = Form(None),
|
review_notes: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -869,7 +920,10 @@ def employee_onboarding_checklist(request: Request):
|
|||||||
|
|
||||||
@router.post("/onboarding-checklist/defaults")
|
@router.post("/onboarding-checklist/defaults")
|
||||||
def employee_onboarding_checklist_defaults(request: Request, csrf_token: str = Form(...)):
|
def employee_onboarding_checklist_defaults(request: Request, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -891,7 +945,10 @@ def employee_onboarding_checklist_defaults(request: Request, csrf_token: str = F
|
|||||||
@router.post("/onboarding-checklist")
|
@router.post("/onboarding-checklist")
|
||||||
async def employee_onboarding_checklist_create(request: Request):
|
async def employee_onboarding_checklist_create(request: Request):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -913,7 +970,10 @@ async def employee_onboarding_checklist_create(request: Request):
|
|||||||
@router.post("/onboarding-checklist/{item_id}/edit")
|
@router.post("/onboarding-checklist/{item_id}/edit")
|
||||||
async def employee_onboarding_checklist_edit(request: Request, item_id: int):
|
async def employee_onboarding_checklist_edit(request: Request, item_id: int):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -954,7 +1014,10 @@ def employee_onboarding_tasks(request: Request, employee_id: int | None = None):
|
|||||||
|
|
||||||
@router.post("/{employee_id}/onboarding/generate")
|
@router.post("/{employee_id}/onboarding/generate")
|
||||||
def employee_generate_onboarding(request: Request, employee_id: int, csrf_token: str = Form(...)):
|
def employee_generate_onboarding(request: Request, employee_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -976,7 +1039,10 @@ def employee_generate_onboarding(request: Request, employee_id: int, csrf_token:
|
|||||||
|
|
||||||
@router.post("/onboarding/{task_id}/status")
|
@router.post("/onboarding/{task_id}/status")
|
||||||
def employee_onboarding_task_status(request: Request, task_id: int, status: str = Form(...), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_onboarding_task_status(request: Request, task_id: int, status: str = Form(...), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1019,7 +1085,10 @@ def employee_offboarding_requests(request: Request, status: str | None = None):
|
|||||||
@router.post("/{employee_id}/offboarding/initiate")
|
@router.post("/{employee_id}/offboarding/initiate")
|
||||||
async def employee_offboarding_initiate(request: Request, employee_id: int):
|
async def employee_offboarding_initiate(request: Request, employee_id: int):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1041,7 +1110,10 @@ async def employee_offboarding_initiate(request: Request, employee_id: int):
|
|||||||
|
|
||||||
@router.post("/offboarding/{request_id}/review")
|
@router.post("/offboarding/{request_id}/review")
|
||||||
def employee_offboarding_review(request: Request, request_id: int, status: str = Form(...), approved_relieving_date: str | None = Form(None), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_offboarding_review(request: Request, request_id: int, status: str = Form(...), approved_relieving_date: str | None = Form(None), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1063,7 +1135,10 @@ def employee_offboarding_review(request: Request, request_id: int, status: str =
|
|||||||
|
|
||||||
@router.post("/offboarding/tasks/{task_id}/status")
|
@router.post("/offboarding/tasks/{task_id}/status")
|
||||||
def employee_offboarding_task_status(request: Request, task_id: int, status: str = Form(...), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_offboarding_task_status(request: Request, task_id: int, status: str = Form(...), review_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1085,7 +1160,10 @@ def employee_offboarding_task_status(request: Request, task_id: int, status: str
|
|||||||
|
|
||||||
@router.post("/offboarding/{request_id}/complete")
|
@router.post("/offboarding/{request_id}/complete")
|
||||||
def employee_offboarding_complete(request: Request, request_id: int, csrf_token: str = Form(...)):
|
def employee_offboarding_complete(request: Request, request_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1127,7 +1205,10 @@ def employee_document_types(request: Request, include_inactive: str | None = Non
|
|||||||
|
|
||||||
@router.post("/document-types/defaults")
|
@router.post("/document-types/defaults")
|
||||||
def employee_document_types_defaults(request: Request, csrf_token: str = Form(...)):
|
def employee_document_types_defaults(request: Request, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1149,7 +1230,10 @@ def employee_document_types_defaults(request: Request, csrf_token: str = Form(..
|
|||||||
@router.post("/document-types")
|
@router.post("/document-types")
|
||||||
async def employee_document_type_create(request: Request):
|
async def employee_document_type_create(request: Request):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1174,7 +1258,10 @@ async def employee_document_type_create(request: Request):
|
|||||||
@router.post("/document-types/{type_id}/edit")
|
@router.post("/document-types/{type_id}/edit")
|
||||||
async def employee_document_type_update(request: Request, type_id: int):
|
async def employee_document_type_update(request: Request, type_id: int):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1216,7 +1303,10 @@ def employee_documents(request: Request, employee_id: int | None = None, status:
|
|||||||
@router.post("/{employee_id}/documents/upload")
|
@router.post("/{employee_id}/documents/upload")
|
||||||
async def employee_document_upload(request: Request, employee_id: int, document_file: UploadFile = File(...)):
|
async def employee_document_upload(request: Request, employee_id: int, document_file: UploadFile = File(...)):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1258,7 +1348,10 @@ async def employee_document_upload(request: Request, employee_id: int, document_
|
|||||||
|
|
||||||
@router.post("/documents/{document_id}/review")
|
@router.post("/documents/{document_id}/review")
|
||||||
def employee_document_review(request: Request, document_id: int, status: str = Form(...), verification_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_document_review(request: Request, document_id: int, status: str = Form(...), verification_notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1280,7 +1373,10 @@ def employee_document_review(request: Request, document_id: int, status: str = F
|
|||||||
|
|
||||||
@router.post("/documents/{document_id}/archive")
|
@router.post("/documents/{document_id}/archive")
|
||||||
def employee_document_archive(request: Request, document_id: int, notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_document_archive(request: Request, document_id: int, notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1324,7 +1420,10 @@ def employee_self_documents(request: Request):
|
|||||||
@portal_router.post("/documents/upload")
|
@portal_router.post("/documents/upload")
|
||||||
async def employee_self_document_upload(request: Request, document_file: UploadFile = File(...)):
|
async def employee_self_document_upload(request: Request, document_file: UploadFile = File(...)):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1398,7 +1497,10 @@ def employee_salary_structures(request: Request, employee_id: int | None = None)
|
|||||||
@router.post("/payroll/structures")
|
@router.post("/payroll/structures")
|
||||||
async def employee_salary_structure_submit(request: Request):
|
async def employee_salary_structure_submit(request: Request):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1425,7 +1527,10 @@ async def employee_salary_structure_submit(request: Request):
|
|||||||
@router.post("/payroll/structures/{structure_id}/update")
|
@router.post("/payroll/structures/{structure_id}/update")
|
||||||
async def employee_salary_structure_update(request: Request, structure_id: int):
|
async def employee_salary_structure_update(request: Request, structure_id: int):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1468,7 +1573,10 @@ def employee_payroll_runs(request: Request):
|
|||||||
|
|
||||||
@router.post("/payroll/runs")
|
@router.post("/payroll/runs")
|
||||||
def employee_payroll_run_create(request: Request, pay_year: int = Form(...), pay_month: int = Form(...), notes: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_payroll_run_create(request: Request, pay_year: int = Form(...), pay_month: int = Form(...), notes: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1489,7 +1597,10 @@ def employee_payroll_run_create(request: Request, pay_year: int = Form(...), pay
|
|||||||
|
|
||||||
@router.post("/payroll/runs/{run_id}/generate")
|
@router.post("/payroll/runs/{run_id}/generate")
|
||||||
def employee_payroll_run_generate(request: Request, run_id: int, csrf_token: str = Form(...)):
|
def employee_payroll_run_generate(request: Request, run_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1511,7 +1622,10 @@ def employee_payroll_run_generate(request: Request, run_id: int, csrf_token: str
|
|||||||
|
|
||||||
@router.post("/payroll/runs/{run_id}/approve")
|
@router.post("/payroll/runs/{run_id}/approve")
|
||||||
def employee_payroll_run_approve(request: Request, run_id: int, csrf_token: str = Form(...)):
|
def employee_payroll_run_approve(request: Request, run_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1533,7 +1647,10 @@ def employee_payroll_run_approve(request: Request, run_id: int, csrf_token: str
|
|||||||
|
|
||||||
@router.post("/payroll/runs/{run_id}/paid")
|
@router.post("/payroll/runs/{run_id}/paid")
|
||||||
def employee_payroll_run_paid(request: Request, run_id: int, csrf_token: str = Form(...)):
|
def employee_payroll_run_paid(request: Request, run_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -1680,7 +1797,10 @@ def employee_work_task_assign(
|
|||||||
require_permission(db, current_user, "employees.work.manage")
|
require_permission(db, current_user, "employees.work.manage")
|
||||||
except Exception:
|
except Exception:
|
||||||
return _redirect_denied()
|
return _redirect_denied()
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
||||||
branch_id = request.session.get("active_branch_id")
|
branch_id = request.session.get("active_branch_id")
|
||||||
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
||||||
@@ -1720,7 +1840,10 @@ def employee_my_work_task_status(
|
|||||||
require_permission(db, current_user, "employees.work.view_self")
|
require_permission(db, current_user, "employees.work.view_self")
|
||||||
except Exception:
|
except Exception:
|
||||||
return _redirect_denied()
|
return _redirect_denied()
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
||||||
branch_id = request.session.get("active_branch_id")
|
branch_id = request.session.get("active_branch_id")
|
||||||
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
||||||
@@ -1860,7 +1983,10 @@ def employee_work_task_add_communication(
|
|||||||
require_permission(db, current_user, "employees.work.manage")
|
require_permission(db, current_user, "employees.work.manage")
|
||||||
except Exception:
|
except Exception:
|
||||||
return _redirect_denied()
|
return _redirect_denied()
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
||||||
branch_id = request.session.get("active_branch_id")
|
branch_id = request.session.get("active_branch_id")
|
||||||
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
||||||
@@ -1935,7 +2061,10 @@ def employee_my_work_task_add_communication(
|
|||||||
require_permission(db, current_user, "employees.work.view_self")
|
require_permission(db, current_user, "employees.work.view_self")
|
||||||
except Exception:
|
except Exception:
|
||||||
return _redirect_denied()
|
return _redirect_denied()
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
tenant_id = request.session.get("active_tenant_id") or current_user.tenant_id
|
||||||
branch_id = request.session.get("active_branch_id")
|
branch_id = request.session.get("active_branch_id")
|
||||||
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
scope = build_employee_scope(db, current_user, tenant_id=tenant_id, branch_id=branch_id)
|
||||||
@@ -2026,7 +2155,10 @@ def employee_import_template(request: Request, import_type: str):
|
|||||||
@router.post("/imports/preview")
|
@router.post("/imports/preview")
|
||||||
async def employee_import_preview(request: Request, import_type: str = Form(...), import_file: UploadFile = File(...)):
|
async def employee_import_preview(request: Request, import_type: str = Form(...), import_file: UploadFile = File(...)):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2069,7 +2201,10 @@ async def employee_import_preview(request: Request, import_type: str = Form(...)
|
|||||||
|
|
||||||
@router.post("/imports/commit")
|
@router.post("/imports/commit")
|
||||||
def employee_import_commit(request: Request, csrf_token: str = Form(...)):
|
def employee_import_commit(request: Request, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2162,7 +2297,10 @@ def employee_edit(request: Request, employee_id: int):
|
|||||||
@router.post("/{employee_id}/edit")
|
@router.post("/{employee_id}/edit")
|
||||||
async def employee_edit_submit(request: Request, employee_id: int):
|
async def employee_edit_submit(request: Request, employee_id: int):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2199,7 +2337,10 @@ async def employee_edit_submit(request: Request, employee_id: int):
|
|||||||
|
|
||||||
@router.post("/{employee_id}/link-user")
|
@router.post("/{employee_id}/link-user")
|
||||||
def employee_link_user_submit(request: Request, employee_id: int, user_id: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_link_user_submit(request: Request, employee_id: int, user_id: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2231,7 +2372,10 @@ def employee_status_submit(
|
|||||||
date_of_leaving: str | None = Form(None),
|
date_of_leaving: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2324,7 +2468,10 @@ def employee_punch_in_submit(
|
|||||||
accuracy_meters: str | None = Form(None),
|
accuracy_meters: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2357,7 +2504,10 @@ def employee_punch_out_submit(
|
|||||||
accuracy_meters: str | None = Form(None),
|
accuracy_meters: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2405,7 +2555,10 @@ def employee_self_leave(request: Request):
|
|||||||
|
|
||||||
@portal_router.post("/leave/apply")
|
@portal_router.post("/leave/apply")
|
||||||
def employee_self_leave_apply(request: Request, leave_type_id: int = Form(...), from_date: str = Form(...), to_date: str = Form(...), reason: str | None = Form(None), csrf_token: str = Form(...)):
|
def employee_self_leave_apply(request: Request, leave_type_id: int = Form(...), from_date: str = Form(...), to_date: str = Form(...), reason: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2423,7 +2576,10 @@ def employee_self_leave_apply(request: Request, leave_type_id: int = Form(...),
|
|||||||
|
|
||||||
@portal_router.post("/leave/{request_id}/cancel")
|
@portal_router.post("/leave/{request_id}/cancel")
|
||||||
def employee_self_leave_cancel(request: Request, request_id: int, csrf_token: str = Form(...)):
|
def employee_self_leave_cancel(request: Request, request_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2461,7 +2617,10 @@ def employee_self_offboarding(request: Request):
|
|||||||
@portal_router.post("/offboarding/request")
|
@portal_router.post("/offboarding/request")
|
||||||
async def employee_self_offboarding_request(request: Request):
|
async def employee_self_offboarding_request(request: Request):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2513,7 +2672,10 @@ def employee_self_profile(request: Request):
|
|||||||
@portal_router.post("/profile")
|
@portal_router.post("/profile")
|
||||||
async def employee_self_profile_submit(request: Request):
|
async def employee_self_profile_submit(request: Request):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
@@ -2605,7 +2767,10 @@ def employee_registration_form(request: Request):
|
|||||||
@portal_router.post("/register")
|
@portal_router.post("/register")
|
||||||
async def employee_registration_submit(request: Request):
|
async def employee_registration_submit(request: Request):
|
||||||
form = await request.form()
|
form = await request.form()
|
||||||
validate_csrf(request, form.get("csrf_token"))
|
try:
|
||||||
|
validate_csrf(request, form.get("csrf_token"))
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
current_user = get_current_user(request, db=db)
|
current_user = get_current_user(request, db=db)
|
||||||
|
|||||||
@@ -34,6 +34,12 @@ router = APIRouter(prefix="/marketplace", tags=["marketplace-ui"])
|
|||||||
public_router = APIRouter(tags=["marketplace-public-ui"])
|
public_router = APIRouter(tags=["marketplace-public-ui"])
|
||||||
|
|
||||||
|
|
||||||
|
def _csrf_rejected(request: Request):
|
||||||
|
from app.core.http_responses import forbidden_response
|
||||||
|
return forbidden_response(request, "CSRF validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _public_marketplace_ctx(request: Request, db, **ctx):
|
def _public_marketplace_ctx(request: Request, db, **ctx):
|
||||||
@@ -135,7 +141,10 @@ def marketplace_public_request_service_submit(request: Request, csrf_token: str
|
|||||||
return RedirectResponse(url="/marketplace/public-lead", status_code=303)
|
return RedirectResponse(url="/marketplace/public-lead", status_code=303)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
lead = create_marketplace_lead(
|
lead = create_marketplace_lead(
|
||||||
db,
|
db,
|
||||||
lead_name=lead_name,
|
lead_name=lead_name,
|
||||||
@@ -254,7 +263,10 @@ def lead_create(request: Request, csrf_token: str = Form(...), lead_name: str =
|
|||||||
user, response = _require_user(request, db, "marketplace_leads.create")
|
user, response = _require_user(request, db, "marketplace_leads.create")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
lead = create_marketplace_lead(db, lead_name=lead_name, business_name=business_name, email=email, mobile=mobile, city=city, state=state, service_category=service_category, service_requested=service_requested, message=message, source=source, priority=priority, estimated_value=estimated_value, created_by_user_id=user.id)
|
lead = create_marketplace_lead(db, lead_name=lead_name, business_name=business_name, email=email, mobile=mobile, city=city, state=state, service_category=service_category, service_requested=service_requested, message=message, source=source, priority=priority, estimated_value=estimated_value, created_by_user_id=user.id)
|
||||||
return RedirectResponse(url=f"/marketplace/leads/{lead.id}", status_code=303)
|
return RedirectResponse(url=f"/marketplace/leads/{lead.id}", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
@@ -274,7 +286,10 @@ def public_lead_form(request: Request):
|
|||||||
def public_lead_submit(request: Request, csrf_token: str = Form(...), lead_name: str = Form(...), business_name: str = Form(""), email: str = Form(""), mobile: str = Form(""), city: str = Form(""), state: str = Form(""), service_category: str = Form(""), service_requested: str = Form(...), message: str = Form("")):
|
def public_lead_submit(request: Request, csrf_token: str = Form(...), lead_name: str = Form(...), business_name: str = Form(""), email: str = Form(""), mobile: str = Form(""), city: str = Form(""), state: str = Form(""), service_category: str = Form(""), service_requested: str = Form(...), message: str = Form("")):
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
lead = create_marketplace_lead(db, lead_name=lead_name, business_name=business_name, email=email, mobile=mobile, city=city, state=state, service_category=service_category, service_requested=service_requested, message=message, source="public_website", priority="NORMAL")
|
lead = create_marketplace_lead(db, lead_name=lead_name, business_name=business_name, email=email, mobile=mobile, city=city, state=state, service_category=service_category, service_requested=service_requested, message=message, source="public_website", priority="NORMAL")
|
||||||
return _render(request, "modules/marketplace/templates/marketplace/public_thank_you.html", db, None, title="Thank You", lead=lead)
|
return _render(request, "modules/marketplace/templates/marketplace/public_thank_you.html", db, None, title="Thank You", lead=lead)
|
||||||
finally:
|
finally:
|
||||||
@@ -303,7 +318,10 @@ def lead_assign(request: Request, lead_id: int, csrf_token: str = Form(...), ten
|
|||||||
user, response = _require_user(request, db, "marketplace_leads.assign")
|
user, response = _require_user(request, db, "marketplace_leads.assign")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
lead = get_marketplace_lead(db, lead_id)
|
lead = get_marketplace_lead(db, lead_id)
|
||||||
if lead:
|
if lead:
|
||||||
assign_marketplace_lead(db, lead=lead, tenant_id=tenant_id, branch_id=branch_id or None, partner_user_id=partner_user_id or None, notes=notes, assigned_by_user_id=user.id)
|
assign_marketplace_lead(db, lead=lead, tenant_id=tenant_id, branch_id=branch_id or None, partner_user_id=partner_user_id or None, notes=notes, assigned_by_user_id=user.id)
|
||||||
@@ -319,7 +337,10 @@ def lead_status_update(request: Request, lead_id: int, csrf_token: str = Form(..
|
|||||||
user, response = _require_user(request, db, "marketplace_leads.update")
|
user, response = _require_user(request, db, "marketplace_leads.update")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
lead = get_marketplace_lead(db, lead_id)
|
lead = get_marketplace_lead(db, lead_id)
|
||||||
if lead:
|
if lead:
|
||||||
update_lead_status(db, lead=lead, status=status, user_id=user.id)
|
update_lead_status(db, lead=lead, status=status, user_id=user.id)
|
||||||
@@ -335,7 +356,10 @@ def lead_convert_client(request: Request, lead_id: int, csrf_token: str = Form(.
|
|||||||
user, response = _require_user(request, db, "marketplace_leads.convert")
|
user, response = _require_user(request, db, "marketplace_leads.convert")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
lead = get_marketplace_lead(db, lead_id)
|
lead = get_marketplace_lead(db, lead_id)
|
||||||
if lead:
|
if lead:
|
||||||
client = convert_lead_to_client(db, lead=lead, tenant_id=tenant_id, branch_id=branch_id, partner_user_id=partner_user_id or None, client_code=client_code, user_id=user.id)
|
client = convert_lead_to_client(db, lead=lead, tenant_id=tenant_id, branch_id=branch_id, partner_user_id=partner_user_id or None, client_code=client_code, user_id=user.id)
|
||||||
|
|||||||
@@ -46,6 +46,12 @@ from app.modules.core.tenancy.year_control import redirect_if_financial_year_loc
|
|||||||
router = APIRouter(prefix="/notice-cases", tags=["notice-cases-ui"])
|
router = APIRouter(prefix="/notice-cases", tags=["notice-cases-ui"])
|
||||||
|
|
||||||
|
|
||||||
|
def _csrf_rejected(request: Request):
|
||||||
|
from app.core.http_responses import forbidden_response
|
||||||
|
return forbidden_response(request, "CSRF validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _base_ctx(request: Request, user, db, **ctx):
|
def _base_ctx(request: Request, user, db, **ctx):
|
||||||
base = {
|
base = {
|
||||||
"request": request,
|
"request": request,
|
||||||
@@ -249,7 +255,10 @@ def case_create_submit(
|
|||||||
remarks: str = Form(""),
|
remarks: str = Form(""),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user, response = _require_user(request, db, "notice_cases.create")
|
user, response = _require_user(request, db, "notice_cases.create")
|
||||||
@@ -316,7 +325,10 @@ def case_edit_page(request: Request, case_id: int):
|
|||||||
|
|
||||||
@router.post("/{case_id}/edit")
|
@router.post("/{case_id}/edit")
|
||||||
def case_edit_submit(request: Request, case_id: int, department: str = Form("GST"), case_type: str = Form("Notice"), title: str = Form(""), reference_no: str = Form(""), din_ack_no: str = Form(""), notice_date: str = Form(""), due_date: str = Form(""), financial_year: str = Form(""), assessment_year: str = Form(""), period_label: str = Form(""), status: str = Form("open"), priority: str = Form("normal"), assigned_partner_user_id: str = Form(""), assigned_manager_user_id: str = Form(""), assigned_staff_user_id: str = Form(""), issue_summary: str = Form(""), remarks: str = Form(""), csrf_token: str = Form(...)):
|
def case_edit_submit(request: Request, case_id: int, department: str = Form("GST"), case_type: str = Form("Notice"), title: str = Form(""), reference_no: str = Form(""), din_ack_no: str = Form(""), notice_date: str = Form(""), due_date: str = Form(""), financial_year: str = Form(""), assessment_year: str = Form(""), period_label: str = Form(""), status: str = Form("open"), priority: str = Form("normal"), assigned_partner_user_id: str = Form(""), assigned_manager_user_id: str = Form(""), assigned_staff_user_id: str = Form(""), issue_summary: str = Form(""), remarks: str = Form(""), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user, response = _require_user(request, db, "notice_cases.edit")
|
user, response = _require_user(request, db, "notice_cases.edit")
|
||||||
@@ -348,7 +360,10 @@ def case_edit_submit(request: Request, case_id: int, department: str = Form("GST
|
|||||||
|
|
||||||
@router.post("/{case_id}/events")
|
@router.post("/{case_id}/events")
|
||||||
def case_add_event(request: Request, case_id: int, event_type: str = Form("Internal Note"), event_date: str = Form(""), description: str = Form(""), next_due_date: str = Form(""), csrf_token: str = Form(...)):
|
def case_add_event(request: Request, case_id: int, event_type: str = Form("Internal Note"), event_date: str = Form(""), description: str = Form(""), next_due_date: str = Form(""), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user, response = _require_user(request, db, "notice_cases.events.manage")
|
user, response = _require_user(request, db, "notice_cases.events.manage")
|
||||||
@@ -368,7 +383,10 @@ def case_add_event(request: Request, case_id: int, event_type: str = Form("Inter
|
|||||||
|
|
||||||
@router.post("/{case_id}/hearings")
|
@router.post("/{case_id}/hearings")
|
||||||
def case_add_hearing(request: Request, case_id: int, hearing_date: str = Form(""), hearing_time: str = Form(""), venue_or_mode: str = Form(""), officer_name: str = Form(""), agenda: str = Form(""), outcome: str = Form(""), status: str = Form("scheduled"), csrf_token: str = Form(...)):
|
def case_add_hearing(request: Request, case_id: int, hearing_date: str = Form(""), hearing_time: str = Form(""), venue_or_mode: str = Form(""), officer_name: str = Form(""), agenda: str = Form(""), outcome: str = Form(""), status: str = Form("scheduled"), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user, response = _require_user(request, db, "notice_cases.hearings.manage")
|
user, response = _require_user(request, db, "notice_cases.hearings.manage")
|
||||||
@@ -388,7 +406,10 @@ def case_add_hearing(request: Request, case_id: int, hearing_date: str = Form(""
|
|||||||
|
|
||||||
@router.post("/{case_id}/orders")
|
@router.post("/{case_id}/orders")
|
||||||
def case_add_order(request: Request, case_id: int, order_type: str = Form("Other"), order_no: str = Form(""), order_date: str = Form(""), demand_amount: str = Form("0"), tax_amount: str = Form("0"), interest_amount: str = Form("0"), penalty_amount: str = Form("0"), summary: str = Form(""), appeal_due_date: str = Form(""), appeal_filed: str | None = Form(None), csrf_token: str = Form(...)):
|
def case_add_order(request: Request, case_id: int, order_type: str = Form("Other"), order_no: str = Form(""), order_date: str = Form(""), demand_amount: str = Form("0"), tax_amount: str = Form("0"), interest_amount: str = Form("0"), penalty_amount: str = Form("0"), summary: str = Form(""), appeal_due_date: str = Form(""), appeal_filed: str | None = Form(None), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user, response = _require_user(request, db, "notice_cases.orders.manage")
|
user, response = _require_user(request, db, "notice_cases.orders.manage")
|
||||||
@@ -408,7 +429,10 @@ def case_add_order(request: Request, case_id: int, order_type: str = Form("Other
|
|||||||
|
|
||||||
@router.post("/{case_id}/documents/upload")
|
@router.post("/{case_id}/documents/upload")
|
||||||
def case_document_upload(request: Request, case_id: int, title: str = Form(""), document_type: str = Form("OTHER"), description: str = Form(""), event_id: str = Form(""), file: UploadFile = File(...), csrf_token: str = Form(...)):
|
def case_document_upload(request: Request, case_id: int, title: str = Form(""), document_type: str = Form("OTHER"), description: str = Form(""), event_id: str = Form(""), file: UploadFile = File(...), csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user, response = _require_user(request, db, "notice_cases.documents.upload")
|
user, response = _require_user(request, db, "notice_cases.documents.upload")
|
||||||
@@ -451,7 +475,10 @@ def case_document_download(request: Request, document_id: int):
|
|||||||
|
|
||||||
@router.post("/documents/{document_id}/delete")
|
@router.post("/documents/{document_id}/delete")
|
||||||
def case_document_delete(request: Request, document_id: int, csrf_token: str = Form(...)):
|
def case_document_delete(request: Request, document_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user, response = _require_user(request, db, "notice_cases.documents.delete")
|
user, response = _require_user(request, db, "notice_cases.documents.delete")
|
||||||
|
|||||||
@@ -48,6 +48,12 @@ from app.modules.platform_billing.services import (
|
|||||||
router = APIRouter(prefix="/platform-billing", tags=["platform-billing-ui"])
|
router = APIRouter(prefix="/platform-billing", tags=["platform-billing-ui"])
|
||||||
|
|
||||||
|
|
||||||
|
def _csrf_rejected(request: Request):
|
||||||
|
from app.core.http_responses import forbidden_response
|
||||||
|
return forbidden_response(request, "CSRF validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _redirect_denied():
|
def _redirect_denied():
|
||||||
from app.core.http_responses import ui_access_denied
|
from app.core.http_responses import ui_access_denied
|
||||||
return ui_access_denied()
|
return ui_access_denied()
|
||||||
@@ -121,6 +127,45 @@ def dashboard(request: Request):
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Phase 3 security hardening: list pages must not accept direct unsafe POSTs.
|
||||||
|
# Existing create/update features continue to use their dedicated /new or action routes.
|
||||||
|
@router.post("/plans")
|
||||||
|
def plans_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/accounts")
|
||||||
|
def accounts_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/audit-firm-subscriptions")
|
||||||
|
def audit_firm_subscriptions_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/client-dashboard-subscriptions")
|
||||||
|
def client_dashboard_subscriptions_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/consultant-subscriptions")
|
||||||
|
def consultant_subscriptions_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/subscriptions")
|
||||||
|
def subscriptions_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/invoices")
|
||||||
|
def invoices_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/plans")
|
@router.get("/plans")
|
||||||
def plans_list(request: Request, q: str = ""):
|
def plans_list(request: Request, q: str = ""):
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
@@ -152,7 +197,10 @@ def plan_create(request: Request, csrf_token: str = Form(...), code: str = Form(
|
|||||||
user, response = _require_user(request, db, "platform_plans.manage")
|
user, response = _require_user(request, db, "platform_plans.manage")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
create_platform_plan(db, code=code, name=name, target_account_type=target_account_type, billing_cycle=billing_cycle, base_amount=base_amount, gst_rate=gst_rate, description=description, feature_text=feature_text)
|
create_platform_plan(db, code=code, name=name, target_account_type=target_account_type, billing_cycle=billing_cycle, base_amount=base_amount, gst_rate=gst_rate, description=description, feature_text=feature_text)
|
||||||
return RedirectResponse(url="/platform-billing/plans", status_code=303)
|
return RedirectResponse(url="/platform-billing/plans", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
@@ -190,7 +238,10 @@ def account_create(request: Request, csrf_token: str = Form(...), account_type:
|
|||||||
user, response = _require_user(request, db, "platform_billing.create")
|
user, response = _require_user(request, db, "platform_billing.create")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
create_platform_account(db, account_type=account_type, account_code=account_code, display_name=display_name, tenant_id=int(tenant_id) if tenant_id else None, client_id=int(client_id) if client_id else None, consultant_id=int(consultant_id) if consultant_id else None, email=email, mobile=mobile, gstin=gstin, pan=pan, billing_address=billing_address, state=state, notes=notes, user_id=user.id)
|
create_platform_account(db, account_type=account_type, account_code=account_code, display_name=display_name, tenant_id=int(tenant_id) if tenant_id else None, client_id=int(client_id) if client_id else None, consultant_id=int(consultant_id) if consultant_id else None, email=email, mobile=mobile, gstin=gstin, pan=pan, billing_address=billing_address, state=state, notes=notes, user_id=user.id)
|
||||||
return RedirectResponse(url="/platform-billing/accounts", status_code=303)
|
return RedirectResponse(url="/platform-billing/accounts", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
@@ -228,7 +279,10 @@ def audit_firm_accounts_sync(request: Request, csrf_token: str = Form(...)):
|
|||||||
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
result = sync_audit_firm_billing_accounts(db, user_id=user.id)
|
result = sync_audit_firm_billing_accounts(db, user_id=user.id)
|
||||||
return RedirectResponse(url=f"/platform-billing/audit-firm-subscriptions?synced=created-{result['created']}-updated-{result['updated']}", status_code=303)
|
return RedirectResponse(url=f"/platform-billing/audit-firm-subscriptions?synced=created-{result['created']}-updated-{result['updated']}", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
@@ -264,7 +318,10 @@ def audit_firm_generate_submit(request: Request, csrf_token: str = Form(...), su
|
|||||||
user, response = _require_user(request, db, "platform_billing.generate")
|
user, response = _require_user(request, db, "platform_billing.generate")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
result = generate_audit_firm_subscription_invoices(
|
result = generate_audit_firm_subscription_invoices(
|
||||||
db,
|
db,
|
||||||
subscription_ids=subscription_ids,
|
subscription_ids=subscription_ids,
|
||||||
@@ -329,7 +386,10 @@ def client_dashboard_accounts_sync(request: Request, csrf_token: str = Form(...)
|
|||||||
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
result = sync_client_dashboard_billing_accounts(db, user_id=user.id)
|
result = sync_client_dashboard_billing_accounts(db, user_id=user.id)
|
||||||
return RedirectResponse(url=f"/platform-billing/client-dashboard-subscriptions?synced=created-{result['created']}-updated-{result['updated']}", status_code=303)
|
return RedirectResponse(url=f"/platform-billing/client-dashboard-subscriptions?synced=created-{result['created']}-updated-{result['updated']}", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
@@ -343,7 +403,10 @@ def client_dashboard_subscription_create(request: Request, csrf_token: str = For
|
|||||||
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
create_platform_subscription(
|
create_platform_subscription(
|
||||||
db,
|
db,
|
||||||
account_id=account_id,
|
account_id=account_id,
|
||||||
@@ -392,7 +455,10 @@ def client_dashboard_generate_submit(request: Request, csrf_token: str = Form(..
|
|||||||
user, response = _require_user(request, db, "platform_billing.generate")
|
user, response = _require_user(request, db, "platform_billing.generate")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
result = generate_client_dashboard_subscription_invoices(
|
result = generate_client_dashboard_subscription_invoices(
|
||||||
db,
|
db,
|
||||||
subscription_ids=subscription_ids,
|
subscription_ids=subscription_ids,
|
||||||
@@ -456,7 +522,10 @@ def consultant_accounts_sync(request: Request, csrf_token: str = Form(...)):
|
|||||||
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
result = sync_consultant_billing_accounts(db, user_id=user.id)
|
result = sync_consultant_billing_accounts(db, user_id=user.id)
|
||||||
return RedirectResponse(url=f"/platform-billing/consultant-subscriptions?synced=created-{result['created']}-updated-{result['updated']}", status_code=303)
|
return RedirectResponse(url=f"/platform-billing/consultant-subscriptions?synced=created-{result['created']}-updated-{result['updated']}", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
@@ -470,7 +539,10 @@ def consultant_subscription_create(request: Request, csrf_token: str = Form(...)
|
|||||||
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
create_platform_subscription(
|
create_platform_subscription(
|
||||||
db,
|
db,
|
||||||
account_id=account_id,
|
account_id=account_id,
|
||||||
@@ -519,7 +591,10 @@ def consultant_generate_submit(request: Request, csrf_token: str = Form(...), su
|
|||||||
user, response = _require_user(request, db, "platform_billing.generate")
|
user, response = _require_user(request, db, "platform_billing.generate")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
result = generate_consultant_subscription_invoices(
|
result = generate_consultant_subscription_invoices(
|
||||||
db,
|
db,
|
||||||
subscription_ids=subscription_ids,
|
subscription_ids=subscription_ids,
|
||||||
@@ -580,7 +655,10 @@ def subscription_create(request: Request, csrf_token: str = Form(...), account_i
|
|||||||
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
user, response = _require_user(request, db, "platform_subscriptions.manage")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
create_platform_subscription(db, account_id=account_id, plan_id=plan_id, subscription_code=subscription_code, start_date=parse_date(start_date), end_date=parse_date(end_date), billing_cycle=billing_cycle, amount=amount, gst_rate=gst_rate, auto_generate_invoice=auto_generate_invoice == "on", notes=notes, user_id=user.id)
|
create_platform_subscription(db, account_id=account_id, plan_id=plan_id, subscription_code=subscription_code, start_date=parse_date(start_date), end_date=parse_date(end_date), billing_cycle=billing_cycle, amount=amount, gst_rate=gst_rate, auto_generate_invoice=auto_generate_invoice == "on", notes=notes, user_id=user.id)
|
||||||
return RedirectResponse(url="/platform-billing/subscriptions", status_code=303)
|
return RedirectResponse(url="/platform-billing/subscriptions", status_code=303)
|
||||||
finally:
|
finally:
|
||||||
@@ -618,7 +696,10 @@ def invoice_create(request: Request, csrf_token: str = Form(...), account_id: in
|
|||||||
user, response = _require_user(request, db, "platform_billing.create")
|
user, response = _require_user(request, db, "platform_billing.create")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
invoice = create_platform_invoice(
|
invoice = create_platform_invoice(
|
||||||
db,
|
db,
|
||||||
account_id=account_id,
|
account_id=account_id,
|
||||||
@@ -660,7 +741,10 @@ def invoice_post(request: Request, invoice_id: int, csrf_token: str = Form(...))
|
|||||||
user, response = _require_user(request, db, "platform_billing.post")
|
user, response = _require_user(request, db, "platform_billing.post")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
invoice = get_platform_invoice(db, invoice_id)
|
invoice = get_platform_invoice(db, invoice_id)
|
||||||
if invoice and invoice.status == "DRAFT":
|
if invoice and invoice.status == "DRAFT":
|
||||||
post_platform_invoice(db, invoice, user.id)
|
post_platform_invoice(db, invoice, user.id)
|
||||||
@@ -676,7 +760,10 @@ def payment_create(request: Request, invoice_id: int, csrf_token: str = Form(...
|
|||||||
user, response = _require_user(request, db, "platform_billing.payment.create")
|
user, response = _require_user(request, db, "platform_billing.payment.create")
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
invoice = get_platform_invoice(db, invoice_id)
|
invoice = get_platform_invoice(db, invoice_id)
|
||||||
if invoice:
|
if invoice:
|
||||||
record_platform_payment(db, invoice=invoice, amount=amount, mode=mode, reference_no=reference_no, notes=notes, user_id=user.id)
|
record_platform_payment(db, invoice=invoice, amount=amount, mode=mode, reference_no=reference_no, notes=notes, user_id=user.id)
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ from app.modules.system_settings.year_backup_service import build_year_backup_ex
|
|||||||
router = APIRouter(prefix="/system-settings", tags=["system-settings-ui"])
|
router = APIRouter(prefix="/system-settings", tags=["system-settings-ui"])
|
||||||
|
|
||||||
|
|
||||||
|
def _csrf_rejected(request: Request):
|
||||||
|
from app.core.http_responses import forbidden_response
|
||||||
|
return forbidden_response(request, "CSRF validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _base_ctx(request: Request, user, db, **ctx):
|
def _base_ctx(request: Request, user, db, **ctx):
|
||||||
base = {
|
base = {
|
||||||
"request": request,
|
"request": request,
|
||||||
@@ -172,6 +178,25 @@ def dashboard(request: Request):
|
|||||||
# -----------------------------
|
# -----------------------------
|
||||||
# Tenant - System Admin only
|
# Tenant - System Admin only
|
||||||
# -----------------------------
|
# -----------------------------
|
||||||
|
|
||||||
|
|
||||||
|
# Phase 3 security hardening: list/index pages must not accept direct unsafe POSTs.
|
||||||
|
# Existing create/update features continue to use their dedicated /new or action routes.
|
||||||
|
@router.post("/tenants")
|
||||||
|
def tenants_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/branches")
|
||||||
|
def branches_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/financial-years")
|
||||||
|
def financial_years_list_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/tenants")
|
@router.get("/tenants")
|
||||||
def tenants_list(request: Request, q: str = "", page: int = 1, per_page: int = 10):
|
def tenants_list(request: Request, q: str = "", page: int = 1, per_page: int = 10):
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
@@ -222,7 +247,10 @@ def tenant_create_submit(
|
|||||||
default_storage_mode: str = Form("local_only"),
|
default_storage_mode: str = Form("local_only"),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -296,7 +324,10 @@ def tenant_edit_submit(
|
|||||||
is_active: str | None = Form(None),
|
is_active: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -432,7 +463,10 @@ def branch_create_submit(
|
|||||||
attendance_allowed_ip_csv: str = Form(""),
|
attendance_allowed_ip_csv: str = Form(""),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -627,7 +661,10 @@ def branch_edit_submit(
|
|||||||
lockout_attempts: str = Form("5"),
|
lockout_attempts: str = Form("5"),
|
||||||
lockout_minutes: str = Form("15"),
|
lockout_minutes: str = Form("15"),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -881,7 +918,10 @@ async def branding_save(
|
|||||||
favicon_file: UploadFile | None = File(None),
|
favicon_file: UploadFile | None = File(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -1043,7 +1083,10 @@ def financial_year_create_submit(
|
|||||||
is_current: str | None = Form(None),
|
is_current: str | None = Form(None),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -1140,7 +1183,10 @@ def financial_year_edit_submit(
|
|||||||
end_date: str = Form(...),
|
end_date: str = Form(...),
|
||||||
csrf_token: str = Form(...),
|
csrf_token: str = Form(...),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -1182,7 +1228,10 @@ def financial_year_edit_submit(
|
|||||||
|
|
||||||
@router.post("/financial-years/{fy_id}/make-current")
|
@router.post("/financial-years/{fy_id}/make-current")
|
||||||
def financial_year_make_current(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
def financial_year_make_current(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -1209,7 +1258,10 @@ def financial_year_make_current(request: Request, fy_id: int, csrf_token: str =
|
|||||||
|
|
||||||
@router.post("/financial-years/{fy_id}/lock")
|
@router.post("/financial-years/{fy_id}/lock")
|
||||||
def financial_year_lock(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
def financial_year_lock(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -1232,7 +1284,10 @@ def financial_year_lock(request: Request, fy_id: int, csrf_token: str = Form(...
|
|||||||
|
|
||||||
@router.post("/financial-years/{fy_id}/unlock")
|
@router.post("/financial-years/{fy_id}/unlock")
|
||||||
def financial_year_unlock(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
def financial_year_unlock(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -1289,7 +1344,10 @@ def financial_year_backup_page(request: Request, fy_id: int):
|
|||||||
|
|
||||||
@router.post("/financial-years/{fy_id}/backup/export")
|
@router.post("/financial-years/{fy_id}/backup/export")
|
||||||
def financial_year_backup_export_submit(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
def financial_year_backup_export_submit(request: Request, fy_id: int, csrf_token: str = Form(...)):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ from app.modules.work_detail.service import get_task_for_action, load_unified_en
|
|||||||
router = APIRouter(prefix="/work", tags=["unified-work-detail-ui"])
|
router = APIRouter(prefix="/work", tags=["unified-work-detail-ui"])
|
||||||
|
|
||||||
|
|
||||||
|
def _csrf_rejected(request: Request):
|
||||||
|
from app.core.http_responses import forbidden_response
|
||||||
|
return forbidden_response(request, "CSRF validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _base_ctx(request: Request, db, user, **ctx):
|
def _base_ctx(request: Request, db, user, **ctx):
|
||||||
base = {
|
base = {
|
||||||
"request": request,
|
"request": request,
|
||||||
@@ -56,6 +62,15 @@ def unified_work_board(request: Request):
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Phase 3 security hardening: /work/engagements is a listing alias, not a create endpoint.
|
||||||
|
# Existing engagement creation remains in the services module.
|
||||||
|
@router.post("/engagements")
|
||||||
|
def unified_engagements_post_rejected(request: Request):
|
||||||
|
return _csrf_rejected(request)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/engagements")
|
@router.get("/engagements")
|
||||||
def unified_engagements_index(request: Request):
|
def unified_engagements_index(request: Request):
|
||||||
"""Compatibility alias for /work/engagements.
|
"""Compatibility alias for /work/engagements.
|
||||||
@@ -79,6 +94,8 @@ def unified_engagement_detail(request: Request, engagement_id: int):
|
|||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
if not user:
|
if not user:
|
||||||
return RedirectResponse(url="/login", status_code=303)
|
return RedirectResponse(url="/login", status_code=303)
|
||||||
|
if "Client" in set(get_user_roles(db, user.id)):
|
||||||
|
return forbidden_response(request, "Access denied")
|
||||||
detail = load_unified_engagement_detail(db, request=request, user=user, engagement_id=engagement_id)
|
detail = load_unified_engagement_detail(db, request=request, user=user, engagement_id=engagement_id)
|
||||||
if not detail:
|
if not detail:
|
||||||
return not_found_response(request, "Work engagement not found or access denied")
|
return not_found_response(request, "Work engagement not found or access denied")
|
||||||
@@ -92,7 +109,10 @@ def unified_engagement_detail(request: Request, engagement_id: int):
|
|||||||
|
|
||||||
@router.post("/tasks/{task_id}/status")
|
@router.post("/tasks/{task_id}/status")
|
||||||
async def unified_task_status_update(request: Request, task_id: int, csrf_token: str = Form(...), status: str = Form(...), priority: str = Form("")):
|
async def unified_task_status_update(request: Request, task_id: int, csrf_token: str = Form(...), status: str = Form(...), priority: str = Form("")):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
@@ -122,7 +142,10 @@ async def unified_task_comment_add(
|
|||||||
visibility: str = Form("internal"),
|
visibility: str = Form("internal"),
|
||||||
message: str = Form(""),
|
message: str = Form(""),
|
||||||
):
|
):
|
||||||
validate_csrf(request, csrf_token)
|
try:
|
||||||
|
validate_csrf(request, csrf_token)
|
||||||
|
except PermissionError:
|
||||||
|
return _csrf_rejected(request)
|
||||||
db = CommonSessionLocal()
|
db = CommonSessionLocal()
|
||||||
try:
|
try:
|
||||||
user = get_current_user(request, db=db)
|
user = get_current_user(request, db=db)
|
||||||
|
|||||||
Reference in New Issue
Block a user