Enforce partner client ownership and partner-scoped imports
This commit is contained in:
+58
-37
@@ -11,7 +11,7 @@ from app.core.security.session_auth import get_current_user
|
||||
from app.core.security.otp import start_otp, verify_otp
|
||||
from app.core.templating import templates
|
||||
from app.modules.clients import repository
|
||||
from app.modules.clients.access import build_scope, can_view_client_row
|
||||
from app.modules.clients.access import build_scope, can_view_client_row, enforce_partner_scope, is_partner_role
|
||||
from app.modules.clients.constants import CLIENT_ACCEPTANCE_STATUS, CLIENT_CATEGORY_OPTIONS, CLIENT_STATUS, CLIENT_TYPES, RISK_CATEGORIES
|
||||
from app.modules.clients.filters import ClientListFilters
|
||||
from app.modules.clients.import_service import (
|
||||
@@ -150,6 +150,15 @@ def _elevate_scope_for_system_admin(scope, role_names: set[str]):
|
||||
return scope
|
||||
|
||||
|
||||
def _apply_role_scope(scope, user, role_names):
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
return enforce_partner_scope(scope, user=user, role_names=role_names)
|
||||
|
||||
|
||||
def _viewer_partner_id(user, role_names):
|
||||
return int(user.id) if is_partner_role(role_names) else None
|
||||
|
||||
|
||||
def _form_bool(value):
|
||||
return value in ("1", "true", "True", "on", "yes")
|
||||
|
||||
@@ -313,7 +322,7 @@ def clients_list(
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
filters = ClientListFilters.from_params(
|
||||
q=q,
|
||||
@@ -336,7 +345,8 @@ def clients_list(
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
partner_id=filters.partner_id,
|
||||
partner_id=None if is_partner_role(role_names) else filters.partner_id,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
q=filters.q,
|
||||
status=filters.status,
|
||||
client_type=filters.client_type,
|
||||
@@ -400,7 +410,7 @@ def clients_export(
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
filters = ClientListFilters.from_params(
|
||||
q=q,
|
||||
@@ -422,7 +432,8 @@ def clients_export(
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
partner_id=filters.partner_id,
|
||||
partner_id=None if is_partner_role(role_names) else filters.partner_id,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
q=filters.q,
|
||||
status=filters.status,
|
||||
client_type=filters.client_type,
|
||||
@@ -458,7 +469,7 @@ def client_import_page(request: Request):
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
return _render(
|
||||
request,
|
||||
@@ -469,7 +480,7 @@ def client_import_page(request: Request):
|
||||
scope=scope,
|
||||
role_names=sorted(role_names),
|
||||
current_tenant=repository.get_tenant(db, scope.tenant_id),
|
||||
partners=repository.list_partners_for_scope(db, tenant_id=scope.tenant_id, branch_id=None if scope.allow_cross_branch else scope.branch_id),
|
||||
partners=([repository.get_partner(db, user.id)] if is_partner_role(role_names) else repository.list_partners_for_scope(db, tenant_id=scope.tenant_id, branch_id=None if scope.allow_cross_branch else scope.branch_id)),
|
||||
import_errors=[],
|
||||
)
|
||||
finally:
|
||||
@@ -488,7 +499,7 @@ def client_import_template(request: Request):
|
||||
return _redirect_denied()
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
payload = build_client_import_template_bytes(current_user=user, tenant_id=scope.tenant_id, partner_id=user.id if 'partner' in role_names else None)
|
||||
return Response(
|
||||
content=payload,
|
||||
@@ -511,7 +522,7 @@ async def client_import_preview(request: Request, excel_file: UploadFile = File(
|
||||
return _redirect_denied()
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
@@ -543,7 +554,7 @@ async def client_import_commit(request: Request):
|
||||
return _redirect_denied()
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
preview_rows = deserialize_preview_rows(form.get("preview_payload") or "[]")
|
||||
@@ -578,7 +589,7 @@ def client_new_page(request: Request):
|
||||
role_names = _role_names(db, user)
|
||||
form_mode = _resolve_form_mode(role_names)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
defaults = {
|
||||
"status": "active",
|
||||
@@ -626,7 +637,7 @@ async def client_create(request: Request):
|
||||
role_names = _role_names(db, user)
|
||||
form_mode = _resolve_form_mode(role_names)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
form = await request.form()
|
||||
request._form = form
|
||||
@@ -678,13 +689,14 @@ def client_detail(request: Request, client_id: int):
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
row = repository.get_client_detail_payload(db, client_id)
|
||||
row = repository.get_client_detail_payload(db, client_id, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
if not row or not can_view_client_row(scope, row, user_id=user.id):
|
||||
return _redirect_denied()
|
||||
|
||||
audit_logs = list_client_audit_logs(db, row=type("Tmp", (), {"id": row["id"]})(), limit=10) if has("clients.audit_log.view") else []
|
||||
review_only = bool(is_partner_role(role_names) and int(row.get("effective_partner_id") or 0) != int(user.id))
|
||||
audit_logs = list_client_audit_logs(db, row=type("Tmp", (), {"id": row["id"]})(), limit=10) if has("clients.audit_log.view") and not review_only else []
|
||||
permanent_document_count = db.execute(
|
||||
select(func.count(PermanentClientDocument.id)).where(
|
||||
PermanentClientDocument.client_id == client_id,
|
||||
@@ -701,11 +713,11 @@ def client_detail(request: Request, client_id: int):
|
||||
audit_logs=audit_logs,
|
||||
permanent_document_count=permanent_document_count,
|
||||
scope=scope,
|
||||
can_edit=has("clients.edit"),
|
||||
can_deactivate=has("clients.deactivate"),
|
||||
can_activate=has("clients.activate"),
|
||||
can_archive=has("clients.archive"),
|
||||
can_restore=has("clients.restore"),
|
||||
can_edit=has("clients.edit") and not review_only,
|
||||
can_deactivate=has("clients.deactivate") and not review_only,
|
||||
can_activate=has("clients.activate") and not review_only,
|
||||
can_archive=has("clients.archive") and not review_only,
|
||||
can_restore=has("clients.restore") and not review_only,
|
||||
consultant_summary=get_client_consultant_summary(db, tenant_id=int(row["tenant_id"]), client_id=client_id),
|
||||
client_group=get_group(db, tenant_id=int(row["tenant_id"]), group_id=int(row["client_group_id"])) if row.get("client_group_id") else None,
|
||||
can_manage_acceptance=has("clients.acceptance.manage"),
|
||||
@@ -730,7 +742,7 @@ def client_edit_page(request: Request, client_id: int):
|
||||
role_names = _role_names(db, user)
|
||||
form_mode = _resolve_form_mode(role_names)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
row = get_client_or_404(
|
||||
db,
|
||||
@@ -739,6 +751,7 @@ def client_edit_page(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
|
||||
return _render(
|
||||
@@ -773,7 +786,7 @@ async def client_update(request: Request, client_id: int):
|
||||
role_names = _role_names(db, user)
|
||||
form_mode = _resolve_form_mode(role_names)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
row = get_client_or_404(
|
||||
db,
|
||||
@@ -782,6 +795,7 @@ async def client_update(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
|
||||
form = await request.form()
|
||||
@@ -834,7 +848,7 @@ async def client_acceptance_approve(request: Request, client_id: int):
|
||||
return _redirect_denied()
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
row = get_client_or_404(
|
||||
@@ -844,6 +858,7 @@ async def client_acceptance_approve(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
try:
|
||||
row = approve_client_acceptance_service(db, row=row, actor_user_id=user.id, review_notes=form.get("acceptance_review_notes"))
|
||||
@@ -883,7 +898,7 @@ async def client_acceptance_reject(request: Request, client_id: int):
|
||||
return _redirect_denied()
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
row = get_client_or_404(
|
||||
@@ -893,6 +908,7 @@ async def client_acceptance_reject(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
row = reject_client_acceptance_service(db, row=row, actor_user_id=user.id, rejection_reason=form.get("acceptance_rejection_reason"))
|
||||
return RedirectResponse(url=f"/clients/{row.id}", status_code=303)
|
||||
@@ -912,7 +928,7 @@ async def client_acceptance_pending(request: Request, client_id: int):
|
||||
return _redirect_denied()
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
row = get_client_or_404(
|
||||
@@ -922,6 +938,7 @@ async def client_acceptance_pending(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
row = mark_client_acceptance_pending_service(db, row=row, actor_user_id=user.id, review_notes=form.get("acceptance_review_notes"))
|
||||
return RedirectResponse(url=f"/clients/{row.id}", status_code=303)
|
||||
@@ -943,7 +960,7 @@ async def client_deactivate(request: Request, client_id: int):
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
@@ -955,6 +972,7 @@ async def client_deactivate(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
deactivate_client_service(db, row=row, actor_user_id=user.id)
|
||||
return RedirectResponse(url="/clients", status_code=303)
|
||||
@@ -976,7 +994,7 @@ async def client_activate(request: Request, client_id: int):
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
@@ -988,6 +1006,7 @@ async def client_activate(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
activate_client_service(db, row=row, actor_user_id=user.id)
|
||||
return RedirectResponse(url=f"/clients/{row.id}", status_code=303)
|
||||
@@ -1009,7 +1028,7 @@ async def client_archive(request: Request, client_id: int):
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
@@ -1021,6 +1040,7 @@ async def client_archive(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
archive_client_service(db, row=row, actor_user_id=user.id)
|
||||
return RedirectResponse(url="/clients?include_archived=true", status_code=303)
|
||||
@@ -1042,7 +1062,7 @@ async def client_restore(request: Request, client_id: int):
|
||||
|
||||
role_names = _role_names(db, user)
|
||||
scope = build_scope(request, user, has)
|
||||
scope = _elevate_scope_for_system_admin(scope, role_names)
|
||||
scope = _apply_role_scope(scope, user, role_names)
|
||||
|
||||
form = await request.form()
|
||||
validate_csrf(request, form.get("csrf_token"))
|
||||
@@ -1054,6 +1074,7 @@ async def client_restore(request: Request, client_id: int):
|
||||
branch_id=scope.branch_id,
|
||||
allow_cross_branch=scope.allow_cross_branch,
|
||||
allow_all_clients=scope.allow_all_clients,
|
||||
viewer_partner_id=_viewer_partner_id(user, role_names),
|
||||
)
|
||||
restore_client_service(db, row=row, actor_user_id=user.id)
|
||||
return RedirectResponse(url=f"/clients/{row.id}", status_code=303)
|
||||
@@ -1073,7 +1094,7 @@ async def client_acceptance_request_declarations(request: Request, client_id: in
|
||||
if not has("clients.acceptance.manage"):
|
||||
return _redirect_denied()
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
request_client_acceptance_declarations_service(db, row=row, actor_user_id=user.id)
|
||||
return RedirectResponse(url=f"/clients/{client_id}", status_code=303)
|
||||
finally:
|
||||
@@ -1122,7 +1143,7 @@ async def client_acceptance_kyc_sync(request: Request, client_id: int, csrf_toke
|
||||
if not has("clients.acceptance.manage"):
|
||||
return _redirect_denied()
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
sync_client_kyc_from_permanent_documents_service(db, row=row, actor_user_id=user.id)
|
||||
return RedirectResponse(url=f"/clients/{client_id}", status_code=303)
|
||||
finally:
|
||||
@@ -1141,7 +1162,7 @@ async def client_acceptance_kyc_verify(request: Request, client_id: int, csrf_to
|
||||
if not has("clients.acceptance.approve") and not has("clients.acceptance.manage"):
|
||||
return _redirect_denied()
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
verify_client_kyc_service(db, row=row, actor_user_id=user.id, notes=verification_notes)
|
||||
return RedirectResponse(url=f"/clients/{client_id}", status_code=303)
|
||||
finally:
|
||||
@@ -1160,7 +1181,7 @@ async def client_acceptance_kyc_reject(request: Request, client_id: int, csrf_to
|
||||
if not has("clients.acceptance.manage"):
|
||||
return _redirect_denied()
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
reject_client_kyc_service(db, row=row, actor_user_id=user.id, notes=verification_notes)
|
||||
return RedirectResponse(url=f"/clients/{client_id}", status_code=303)
|
||||
finally:
|
||||
@@ -1179,7 +1200,7 @@ async def client_engagement_letter_draft(request: Request, client_id: int, csrf_
|
||||
if not has("clients.acceptance.manage"):
|
||||
return _redirect_denied()
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
draft_client_engagement_letter_service(db, row=row, actor_user_id=user.id, title=title, body_text=body_text)
|
||||
return RedirectResponse(url=f"/clients/{client_id}", status_code=303)
|
||||
finally:
|
||||
@@ -1198,7 +1219,7 @@ async def client_engagement_letter_approve_send(request: Request, client_id: int
|
||||
if not has("clients.acceptance.approve"):
|
||||
return _redirect_denied()
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
approve_and_send_engagement_letter_service(db, row=row, letter_id=letter_id, actor_user_id=user.id)
|
||||
return RedirectResponse(url=f"/clients/{client_id}", status_code=303)
|
||||
finally:
|
||||
@@ -1214,7 +1235,7 @@ def client_engagement_letter_download(request: Request, client_id: int, letter_i
|
||||
return RedirectResponse(url="/login", status_code=303)
|
||||
has = _has_perm_factory(db, user)
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=True, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=True, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
letter = get_current_engagement_letter(db, client_id=client_id)
|
||||
if not letter or letter.id != letter_id:
|
||||
return _redirect_denied()
|
||||
@@ -1235,7 +1256,7 @@ async def client_engagement_letter_verify_manual(request: Request, client_id: in
|
||||
if not has("clients.acceptance.approve") and not has("clients.acceptance.manage"):
|
||||
return _redirect_denied()
|
||||
scope = _elevate_scope_for_system_admin(build_scope(request, user, has), _role_names(db, user))
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients)
|
||||
row = get_client_or_404(db, client_id=client_id, tenant_id=scope.tenant_id, branch_id=scope.branch_id, allow_cross_branch=scope.allow_cross_branch, allow_all_clients=scope.allow_all_clients, viewer_partner_id=_viewer_partner_id(user, role_names))
|
||||
verify_manual_engagement_letter_service(db, row=row, letter_id=letter_id, actor_user_id=user.id)
|
||||
return RedirectResponse(url=f"/clients/{client_id}", status_code=303)
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user