feat: add stage 0 foundation
This commit is contained in:
1
backend/apps/accounts/__init__.py
Normal file
1
backend/apps/accounts/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
3
backend/apps/accounts/api.py
Normal file
3
backend/apps/accounts/api.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from ninja import Router
|
||||
|
||||
router = Router(tags=["accounts"])
|
||||
6
backend/apps/accounts/apps.py
Normal file
6
backend/apps/accounts/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AccountsConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "apps.accounts"
|
||||
1
backend/apps/accounts/management/__init__.py
Normal file
1
backend/apps/accounts/management/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
backend/apps/accounts/management/commands/__init__.py
Normal file
1
backend/apps/accounts/management/commands/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from apps.accounts.permissions import DEFAULT_GROUPS, PERMISSIONS
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Seed MVP permissions and default user groups."
|
||||
|
||||
def handle(self, *args, **options):
|
||||
content_type, _ = ContentType.objects.get_or_create(
|
||||
app_label="system",
|
||||
model="platformpermission",
|
||||
)
|
||||
|
||||
permissions_by_codename: dict[str, Permission] = {}
|
||||
for spec in PERMISSIONS:
|
||||
permission, _ = Permission.objects.get_or_create(
|
||||
content_type=content_type,
|
||||
codename=spec.codename,
|
||||
defaults={"name": spec.name},
|
||||
)
|
||||
if permission.name != spec.name:
|
||||
permission.name = spec.name
|
||||
permission.save(update_fields=["name"])
|
||||
permissions_by_codename[spec.codename] = permission
|
||||
|
||||
for group_name, codenames in DEFAULT_GROUPS.items():
|
||||
group, _ = Group.objects.get_or_create(name=group_name)
|
||||
group.permissions.set(permissions_by_codename[codename] for codename in codenames)
|
||||
|
||||
self.stdout.write(self.style.SUCCESS("Seeded permissions and groups."))
|
||||
1
backend/apps/accounts/models.py
Normal file
1
backend/apps/accounts/models.py
Normal file
@@ -0,0 +1 @@
|
||||
# Use Django's built-in User, Group, and Permission models for MVP RBAC.
|
||||
61
backend/apps/accounts/permissions.py
Normal file
61
backend/apps/accounts/permissions.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PermissionSpec:
|
||||
codename: str
|
||||
name: str
|
||||
|
||||
|
||||
PERMISSIONS: tuple[PermissionSpec, ...] = (
|
||||
PermissionSpec("ticket.view", "View tickets"),
|
||||
PermissionSpec("ticket.create", "Create tickets"),
|
||||
PermissionSpec("ticket.edit", "Edit tickets"),
|
||||
PermissionSpec("ticket.export", "Export tickets"),
|
||||
PermissionSpec("ticket.assign", "Assign tickets"),
|
||||
PermissionSpec("ticket.close", "Close tickets"),
|
||||
PermissionSpec("knowledge.view", "View knowledge"),
|
||||
PermissionSpec("knowledge.manage", "Manage knowledge"),
|
||||
PermissionSpec("solution.view", "View solutions"),
|
||||
PermissionSpec("solution.manage", "Manage solutions"),
|
||||
PermissionSpec("agent.use", "Use Agents"),
|
||||
PermissionSpec("agent.manage", "Manage Agents"),
|
||||
PermissionSpec("model.manage", "Manage model configs"),
|
||||
PermissionSpec("tool.manage", "Manage MCP tools"),
|
||||
PermissionSpec("audit.view", "View audit logs"),
|
||||
PermissionSpec("system.manage", "Manage system settings"),
|
||||
)
|
||||
|
||||
DEFAULT_GROUPS: dict[str, tuple[str, ...]] = {
|
||||
"System Admin": tuple(permission.codename for permission in PERMISSIONS),
|
||||
"Knowledge Admin": (
|
||||
"ticket.view",
|
||||
"knowledge.view",
|
||||
"knowledge.manage",
|
||||
"solution.view",
|
||||
"solution.manage",
|
||||
"agent.use",
|
||||
),
|
||||
"Support Engineer": (
|
||||
"ticket.view",
|
||||
"ticket.create",
|
||||
"ticket.edit",
|
||||
"ticket.assign",
|
||||
"ticket.close",
|
||||
"knowledge.view",
|
||||
"solution.view",
|
||||
"agent.use",
|
||||
),
|
||||
"Requester": (
|
||||
"ticket.view",
|
||||
"ticket.create",
|
||||
"knowledge.view",
|
||||
"solution.view",
|
||||
),
|
||||
"Auditor": (
|
||||
"ticket.view",
|
||||
"knowledge.view",
|
||||
"solution.view",
|
||||
"audit.view",
|
||||
),
|
||||
}
|
||||
1
backend/apps/accounts/schemas.py
Normal file
1
backend/apps/accounts/schemas.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
backend/apps/accounts/tests/__init__.py
Normal file
1
backend/apps/accounts/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
17
backend/apps/accounts/tests/test_permissions_seed.py
Normal file
17
backend/apps/accounts/tests/test_permissions_seed.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.core.management import call_command
|
||||
|
||||
from apps.accounts.permissions import DEFAULT_GROUPS, PERMISSIONS
|
||||
|
||||
|
||||
def test_seed_permissions_creates_permissions_and_groups(db):
|
||||
call_command("seed_permissions")
|
||||
|
||||
assert Permission.objects.filter(
|
||||
codename__in=[permission.codename for permission in PERMISSIONS]
|
||||
).count() == len(PERMISSIONS)
|
||||
|
||||
for group_name, codenames in DEFAULT_GROUPS.items():
|
||||
group = Group.objects.get(name=group_name)
|
||||
actual = set(group.permissions.values_list("codename", flat=True))
|
||||
assert actual == set(codenames)
|
||||
Reference in New Issue
Block a user