0.2.42: external Administrator role with entity-scoped management
The external fund_administrator role (relabeled Administrator) now signs
into the full admin interface, fenced to the funds and SPVs granted to
it via EntityAccess:
- Partners, capital accounts, documents (upload and delete), entity
edits, and eNAV imports for its own funds only; no fund creation,
valuation sign-off, audit log, or investor view.
- Scoped user management: sees and manages only investors tied to its
funds; creates investor accounts only; updates preserve grants on
funds outside its scope.
- New DELETE /api/users/{id} (in-app Delete user button) with the
cascade cleanup factored out of the CLI; Service Admin and self are
protected, and an Administrator can only delete an investor who
belongs solely to its funds.
- Internal fund_admin relabeled 'Staff (all funds)' and dropped from
the create picker to end the two-similar-names confusion.
- Version badge removed from the UI (sidebar and portal header); the
build version now logs to the browser console instead.
- deploy/.startos (signing key) added to .gitignore.
This commit is contained in:
@@ -8,8 +8,7 @@ from sqlmodel import Session, select
|
||||
|
||||
from ten31portal.audit import record_audit
|
||||
from ten31portal.auth import (
|
||||
accessible_entity_ids, can_access_entity, get_current_user,
|
||||
household_user_ids, require_internal_admin,
|
||||
accessible_entity_ids, can_access_entity, get_current_user, household_user_ids,
|
||||
)
|
||||
from ten31portal.database import get_session
|
||||
from ten31portal.models import (
|
||||
@@ -161,12 +160,15 @@ def download_document(
|
||||
@router.delete("/{document_id}")
|
||||
def delete_document(
|
||||
document_id: int,
|
||||
admin: User = Depends(require_internal_admin),
|
||||
admin: User = Depends(get_current_user),
|
||||
session: Session = Depends(get_session),
|
||||
) -> dict[str, str]:
|
||||
doc = session.get(Document, document_id)
|
||||
if doc is None:
|
||||
raise HTTPException(status_code=404, detail="Document not found")
|
||||
# Same reach as upload: internal admins anywhere, an Administrator on their entities.
|
||||
if not _can_upload(admin, doc.entity_id, session):
|
||||
raise HTTPException(status_code=403, detail="Insufficient permissions")
|
||||
storage.delete_file(doc.storage_path)
|
||||
record_audit(session, admin.id, "delete", "document", document_id, {
|
||||
"filename": doc.original_filename,
|
||||
|
||||
Reference in New Issue
Block a user