infrasynth-backend-kit/infrasynth/security/management/commands/sync_permissions.py
jcv-dev a2930426b4 feat: tenant configs, live signals, and automatic permission management
- infrasynth.configs: typed multi-tenant config store (registry, service,
  secrets, cache) + public config_changed/config_reset signals and API
- emit the declared-but-dead signals (features flags/overrides, scheduler
  task_completed/task_failed, tenancy tenant_updated, audit model_changed)
  and per-model audit field exclusions
- security: permission catalog (security_permission), Django-style
  model-derived AutoPermission, PermissionRegistry, RoleAssignment,
  global-or-tenant Grant/Revoke, catalog API
- consolidate the permission surface: PermissionRegistry only (drop the
  settings dict), IsAuthenticatedAndPermitted aliases HybridPermission,
  require_permission replaced by required_permissions + require_all
- packaging: add [build-system]; add Forgejo publish workflow (.forgejo)
2026-09-29 17:06:54 -05:00

35 lines
1.3 KiB
Python

"""Synchronise the permission catalog.
Model-derived permissions (``{app}.{verb}_{model}``) plus permissions registered
by apps through ``PermissionRegistry`` are upserted into the
``security_permission`` table. Imported permissions are
marked inactive, never deleted, so existing role assignments survive.
"""
from __future__ import annotations
from django.core.management.base import BaseCommand
from infrasynth.security.catalog import sync_permissions
class Command(BaseCommand):
help = "Synchronise the permission catalog from models and registered custom permissions."
def add_arguments(self, parser):
parser.add_argument(
"--no-deactivate",
action="store_true",
help="Do not deactivate catalog entries that are no longer derived/registered.",
)
def handle(self, *args, **options):
summary = sync_permissions(deactivate_missing=not options["no_deactivate"])
self.stdout.write(
self.style.SUCCESS(
"Permission catalog synced: "
f"{summary['created']} created, {summary['updated']} updated, "
f"{summary['reactivated']} reactivated, {summary['deactivated']} deactivated "
f"({summary['total']} total)."
)
)