599 lines
24 KiB
Python
599 lines
24 KiB
Python
# Copyright (c) 2025 Patrick Motsch
|
|
# All rights reserved.
|
|
"""
|
|
System Module - Main Module.
|
|
Registers system-level RBAC objects (UI, DATA, RESOURCE) that are not part of any feature.
|
|
These are global system pages and resources available to all users with appropriate roles.
|
|
|
|
Also defines the navigation structure for the frontend.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Dict, List, Any, Optional
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# System metadata
|
|
FEATURE_CODE = "system"
|
|
FEATURE_LABEL = {"en": "System", "de": "System", "fr": "Système"}
|
|
FEATURE_ICON = "mdi-cog"
|
|
|
|
# =============================================================================
|
|
# Navigation Structure (Single Source of Truth)
|
|
# =============================================================================
|
|
#
|
|
# Block Order (gemäss Navigation-API-Konzept):
|
|
# - System: 10
|
|
# - <dynamic/features>: 15 (wird in routeSystem.py eingefügt)
|
|
# - Basisdaten: 30
|
|
# - Administration: 200
|
|
#
|
|
# NOTE: Workflows and Migrate sections removed - now handled as features
|
|
#
|
|
# Item Order: Default-Abstand 10 pro Item
|
|
# uiComponent: Abgeleitet von objectKey (ui.system.home -> page.system.home)
|
|
# icon: Wird intern gehalten aber NICHT in der API Response zurückgegeben
|
|
|
|
NAVIGATION_SECTIONS = [
|
|
{
|
|
"id": "system",
|
|
"title": {"en": "SYSTEM", "de": "SYSTEM", "fr": "SYSTÈME"},
|
|
"order": 10,
|
|
"items": [
|
|
{
|
|
"id": "home",
|
|
"objectKey": "ui.system.home",
|
|
"label": {"en": "Home", "de": "Übersicht", "fr": "Accueil"},
|
|
"icon": "FaHome",
|
|
"path": "/",
|
|
"order": 10,
|
|
"public": True,
|
|
},
|
|
{
|
|
"id": "store",
|
|
"objectKey": "ui.system.store",
|
|
"label": {"en": "Store", "de": "Store", "fr": "Store"},
|
|
"icon": "FaStore",
|
|
"path": "/store",
|
|
"order": 15,
|
|
"public": True,
|
|
},
|
|
{
|
|
"id": "settings",
|
|
"objectKey": "ui.system.settings",
|
|
"label": {"en": "Settings", "de": "Einstellungen", "fr": "Paramètres"},
|
|
"icon": "FaCog",
|
|
"path": "/settings",
|
|
"order": 20,
|
|
"public": True,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"id": "basedata",
|
|
"title": {"en": "BASE DATA", "de": "BASISDATEN", "fr": "DONNÉES DE BASE"},
|
|
"order": 30,
|
|
"items": [
|
|
{
|
|
"id": "prompts",
|
|
"objectKey": "ui.system.prompts",
|
|
"label": {"en": "Prompts", "de": "Prompts", "fr": "Prompts"},
|
|
"icon": "FaLightbulb",
|
|
"path": "/basedata/prompts",
|
|
"order": 10,
|
|
},
|
|
{
|
|
"id": "files",
|
|
"objectKey": "ui.system.files",
|
|
"label": {"en": "Files", "de": "Dateien", "fr": "Fichiers"},
|
|
"icon": "FaRegFileAlt",
|
|
"path": "/basedata/files",
|
|
"order": 20,
|
|
},
|
|
{
|
|
"id": "connections",
|
|
"objectKey": "ui.system.connections",
|
|
"label": {"en": "Connections", "de": "Verbindungen", "fr": "Connexions"},
|
|
"icon": "FaLink",
|
|
"path": "/basedata/connections",
|
|
"order": 30,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"id": "billing",
|
|
"title": {"en": "BILLING", "de": "BILLING", "fr": "FACTURATION"},
|
|
"order": 35,
|
|
"items": [
|
|
{
|
|
"id": "billing-transactions",
|
|
"objectKey": "ui.billing.transactions",
|
|
"label": {"en": "Billing", "de": "Billing", "fr": "Facturation"},
|
|
"icon": "FaWallet",
|
|
"path": "/billing/transactions",
|
|
"order": 10,
|
|
},
|
|
],
|
|
},
|
|
# ─── Administration (with subgroups) ───
|
|
# Access control is at item level, NOT section level.
|
|
# Groups auto-hide if 0 visible pages for the user.
|
|
{
|
|
"id": "admin",
|
|
"title": {"en": "ADMINISTRATION", "de": "ADMINISTRATION", "fr": "ADMINISTRATION"},
|
|
"order": 200,
|
|
"subgroups": [
|
|
# ── Wizards ──
|
|
{
|
|
"id": "admin-wizards",
|
|
"title": {"en": "Wizards", "de": "Wizards", "fr": "Assistants"},
|
|
"order": 10,
|
|
"items": [
|
|
{
|
|
"id": "admin-mandate-wizard",
|
|
"objectKey": "ui.admin.mandateWizard",
|
|
"label": {"en": "Mandate Wizard", "de": "Mandanten-Wizard", "fr": "Assistant mandat"},
|
|
"icon": "FaMagic",
|
|
"path": "/admin/mandate-wizard",
|
|
"order": 10,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-invitation-wizard",
|
|
"objectKey": "ui.admin.invitationWizard",
|
|
"label": {"en": "Invitation Wizard", "de": "Einladungs-Wizard", "fr": "Assistant d'invitation"},
|
|
"icon": "FaEnvelopeOpenText",
|
|
"path": "/admin/invitation-wizard",
|
|
"order": 20,
|
|
"adminOnly": True,
|
|
},
|
|
],
|
|
},
|
|
# ── Users ──
|
|
{
|
|
"id": "admin-users-group",
|
|
"title": {"en": "Users", "de": "Benutzer", "fr": "Utilisateurs"},
|
|
"order": 20,
|
|
"items": [
|
|
{
|
|
"id": "admin-users",
|
|
"objectKey": "ui.admin.users",
|
|
"label": {"en": "Users", "de": "Benutzer", "fr": "Utilisateurs"},
|
|
"icon": "FaUsers",
|
|
"path": "/admin/users",
|
|
"order": 10,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-invitations",
|
|
"objectKey": "ui.admin.invitations",
|
|
"label": {"en": "User Invitations", "de": "Benutzer-Einladungen", "fr": "Invitations utilisateurs"},
|
|
"icon": "FaEnvelopeOpenText",
|
|
"path": "/admin/invitations",
|
|
"order": 20,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-user-access-overview",
|
|
"objectKey": "ui.admin.userAccessOverview",
|
|
"label": {"en": "User Access Overview", "de": "Benutzer-Zugriffsübersicht", "fr": "Aperçu des accès utilisateur"},
|
|
"icon": "FaClipboardList",
|
|
"path": "/admin/user-access-overview",
|
|
"order": 30,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-billing",
|
|
"objectKey": "ui.admin.billing",
|
|
"label": {"en": "Billing Administration", "de": "Billing-Verwaltung", "fr": "Administration de facturation"},
|
|
"icon": "FaMoneyBillAlt",
|
|
"path": "/admin/billing",
|
|
"order": 40,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-subscriptions",
|
|
"objectKey": "ui.admin.subscriptions",
|
|
"label": {"en": "Subscriptions", "de": "Abonnements", "fr": "Abonnements"},
|
|
"icon": "FaFileContract",
|
|
"path": "/admin/subscriptions",
|
|
"order": 50,
|
|
"adminOnly": True,
|
|
},
|
|
],
|
|
},
|
|
# ── System ──
|
|
{
|
|
"id": "admin-system-group",
|
|
"title": {"en": "System", "de": "System", "fr": "Système"},
|
|
"order": 30,
|
|
"items": [
|
|
{
|
|
"id": "admin-roles",
|
|
"objectKey": "ui.admin.roles",
|
|
"label": {"en": "Roles", "de": "Rollen", "fr": "Rôles"},
|
|
"icon": "FaUserTag",
|
|
"path": "/admin/mandate-roles",
|
|
"order": 10,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-mandate-role-permissions",
|
|
"objectKey": "ui.admin.mandateRolePermissions",
|
|
"label": {"en": "Role Permissions", "de": "Rollen-Berechtigungen", "fr": "Permissions des rôles"},
|
|
"icon": "FaKey",
|
|
"path": "/admin/mandate-role-permissions",
|
|
"order": 20,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-mandates",
|
|
"objectKey": "ui.admin.mandates",
|
|
"label": {"en": "Mandates", "de": "Mandanten", "fr": "Mandats"},
|
|
"icon": "FaBuilding",
|
|
"path": "/admin/mandates",
|
|
"order": 30,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-user-mandates",
|
|
"objectKey": "ui.admin.userMandates",
|
|
"label": {"en": "Mandate Members", "de": "Mandanten-Mitglieder", "fr": "Membres du mandat"},
|
|
"icon": "FaUserFriends",
|
|
"path": "/admin/user-mandates",
|
|
"order": 40,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-access",
|
|
"objectKey": "ui.admin.access",
|
|
"label": {"en": "Access Management", "de": "Zugriffsverwaltung", "fr": "Gestion des accès"},
|
|
"icon": "FaBuilding",
|
|
"path": "/admin/access",
|
|
"order": 50,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-feature-instances",
|
|
"objectKey": "ui.admin.featureInstances",
|
|
"label": {"en": "Feature Instances", "de": "Feature-Instanzen", "fr": "Instances de features"},
|
|
"icon": "FaCubes",
|
|
"path": "/admin/feature-instances",
|
|
"order": 60,
|
|
"adminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-feature-roles",
|
|
"objectKey": "ui.admin.featureRoles",
|
|
"label": {"en": "Feature Role Templates", "de": "Features Rollen-Vorlagen", "fr": "Modèles de rôles features"},
|
|
"icon": "FaShieldAlt",
|
|
"path": "/admin/feature-roles",
|
|
"order": 70,
|
|
"adminOnly": True,
|
|
"sysAdminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-automation-events",
|
|
"objectKey": "ui.admin.automationEvents",
|
|
"label": {"en": "Automation Events", "de": "Automation Events", "fr": "Événements d'automatisation"},
|
|
"icon": "FaClock",
|
|
"path": "/admin/automation-events",
|
|
"order": 80,
|
|
"adminOnly": True,
|
|
"sysAdminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-automation-logs",
|
|
"objectKey": "ui.admin.automationLogs",
|
|
"label": {"en": "Execution Logs", "de": "Ausführungsprotokolle", "fr": "Journaux d'exécution"},
|
|
"icon": "FaClipboardList",
|
|
"path": "/admin/automation-logs",
|
|
"order": 85,
|
|
"adminOnly": True,
|
|
"sysAdminOnly": True,
|
|
},
|
|
{
|
|
"id": "admin-logs",
|
|
"objectKey": "ui.admin.logs",
|
|
"label": {"en": "Logs", "de": "Logs", "fr": "Logs"},
|
|
"icon": "FaFileAlt",
|
|
"path": "/admin/logs",
|
|
"order": 90,
|
|
"adminOnly": True,
|
|
"sysAdminOnly": True,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
|
|
def _objectKeyToUiComponent(objectKey: str) -> str:
|
|
"""
|
|
Convert objectKey to uiComponent.
|
|
|
|
Example: ui.system.home -> page.system.home
|
|
ui.admin.users -> page.admin.users
|
|
ui.feature.trustee.dashboard -> page.feature.trustee.dashboard
|
|
"""
|
|
if objectKey.startswith("ui."):
|
|
return "page." + objectKey[3:]
|
|
return objectKey
|
|
|
|
|
|
def _buildUiObjectsFromNavigation() -> List[Dict[str, Any]]:
|
|
"""Build UI_OBJECTS list from NAVIGATION_SECTIONS for RBAC registration."""
|
|
uiObjects = []
|
|
for section in NAVIGATION_SECTIONS:
|
|
# Process direct items
|
|
for item in section.get("items", []):
|
|
uiObjects.append({
|
|
"objectKey": item["objectKey"],
|
|
"label": item["label"],
|
|
"meta": {
|
|
"area": section["id"],
|
|
"public": item.get("public", False),
|
|
"adminOnly": item.get("adminOnly", False),
|
|
"deprecated": item.get("deprecated", False),
|
|
"path": item["path"],
|
|
"icon": item["icon"],
|
|
}
|
|
})
|
|
# Process subgroups (nested items within section)
|
|
for subgroup in section.get("subgroups", []):
|
|
for item in subgroup.get("items", []):
|
|
uiObjects.append({
|
|
"objectKey": item["objectKey"],
|
|
"label": item["label"],
|
|
"meta": {
|
|
"area": section["id"],
|
|
"subgroup": subgroup["id"],
|
|
"public": item.get("public", False),
|
|
"adminOnly": item.get("adminOnly", False),
|
|
"deprecated": item.get("deprecated", False),
|
|
"path": item["path"],
|
|
"icon": item["icon"],
|
|
}
|
|
})
|
|
return uiObjects
|
|
|
|
|
|
# Generate UI_OBJECTS from navigation structure
|
|
UI_OBJECTS = _buildUiObjectsFromNavigation()
|
|
|
|
# =============================================================================
|
|
# System DATA Objects
|
|
# =============================================================================
|
|
# Namespace structure:
|
|
# - data.uam.* → User Access Management (mandantenübergreifend)
|
|
# - data.chat.* → Chat/AI-Daten (benutzer-eigen, kein Mandantenkontext)
|
|
# - data.files.* → Dateien (benutzer-eigen)
|
|
# - data.automation.* → Automation (benutzer-eigen)
|
|
# - data.feature.* → Mandanten-/Feature-spezifische Daten (dynamisch)
|
|
# =============================================================================
|
|
|
|
DATA_OBJECTS = [
|
|
# UAM (User Access Management) - mandantenübergreifend
|
|
{
|
|
"objectKey": "data.uam.UserInDB",
|
|
"label": {"en": "User", "de": "Benutzer", "fr": "Utilisateur"},
|
|
"meta": {"table": "UserInDB", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.AuthEvent",
|
|
"label": {"en": "Auth Event", "de": "Auth-Ereignis", "fr": "Événement d'auth"},
|
|
"meta": {"table": "AuthEvent", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.UserConnection",
|
|
"label": {"en": "Connection", "de": "Verbindung", "fr": "Connexion"},
|
|
"meta": {"table": "UserConnection", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.Mandate",
|
|
"label": {"en": "Mandate", "de": "Mandant", "fr": "Mandat"},
|
|
"meta": {"table": "Mandate", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.UserMandate",
|
|
"label": {"en": "User Mandate", "de": "Benutzer-Mandant", "fr": "Mandat utilisateur"},
|
|
"meta": {"table": "UserMandate", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.Invitation",
|
|
"label": {"en": "Invitation", "de": "Einladung", "fr": "Invitation"},
|
|
"meta": {"table": "Invitation", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.Role",
|
|
"label": {"en": "Role", "de": "Rolle", "fr": "Rôle"},
|
|
"meta": {"table": "Role", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.AccessRule",
|
|
"label": {"en": "Access Rule", "de": "Zugriffsregel", "fr": "Règle d'accès"},
|
|
"meta": {"table": "AccessRule", "namespace": "uam"}
|
|
},
|
|
{
|
|
"objectKey": "data.uam.FeatureInstance",
|
|
"label": {"en": "Feature Instance", "de": "Feature-Instanz", "fr": "Instance de feature"},
|
|
"meta": {"table": "FeatureInstance", "namespace": "uam"}
|
|
},
|
|
# Chat - benutzer-eigen, kein Mandantenkontext
|
|
{
|
|
"objectKey": "data.chat.Prompt",
|
|
"label": {"en": "Prompt", "de": "Prompt", "fr": "Prompt"},
|
|
"meta": {"table": "Prompt", "namespace": "chat", "groupDisabled": True}
|
|
},
|
|
{
|
|
"objectKey": "data.chat.ChatWorkflow",
|
|
"label": {"en": "Chat Workflow", "de": "Chat-Workflow", "fr": "Workflow de chat"},
|
|
"meta": {"table": "ChatWorkflow", "namespace": "chat", "groupDisabled": True}
|
|
},
|
|
# Files - benutzer-eigen
|
|
{
|
|
"objectKey": "data.files.FileItem",
|
|
"label": {"en": "File", "de": "Datei", "fr": "Fichier"},
|
|
"meta": {"table": "FileItem", "namespace": "files", "groupDisabled": True}
|
|
},
|
|
# Automation - benutzer-eigen
|
|
{
|
|
"objectKey": "data.automation.AutomationDefinition",
|
|
"label": {"en": "Automation", "de": "Automatisierung", "fr": "Automatisation"},
|
|
"meta": {"table": "AutomationDefinition", "namespace": "automation", "groupDisabled": True}
|
|
},
|
|
]
|
|
|
|
# =============================================================================
|
|
# System RESOURCE Objects
|
|
# =============================================================================
|
|
|
|
RESOURCE_OBJECTS = [
|
|
{
|
|
"objectKey": "resource.store.automation",
|
|
"label": {"en": "Store: Automation", "de": "Store: Automation", "fr": "Store: Automatisation"},
|
|
"meta": {"category": "store", "featureCode": "automation"}
|
|
},
|
|
{
|
|
"objectKey": "resource.store.automation2",
|
|
"label": {"en": "Store: Automation 2", "de": "Store: Automation 2", "fr": "Store: Automatisation 2"},
|
|
"meta": {"category": "store", "featureCode": "automation2"}
|
|
},
|
|
{
|
|
"objectKey": "resource.store.teamsbot",
|
|
"label": {"en": "Store: Teams Bot", "de": "Store: Teams Bot", "fr": "Store: Teams Bot"},
|
|
"meta": {"category": "store", "featureCode": "teamsbot"}
|
|
},
|
|
{
|
|
"objectKey": "resource.store.workspace",
|
|
"label": {"en": "Store: AI Workspace", "de": "Store: AI Workspace", "fr": "Store: AI Workspace"},
|
|
"meta": {"category": "store", "featureCode": "workspace"}
|
|
},
|
|
{
|
|
"objectKey": "resource.store.commcoach",
|
|
"label": {"en": "Store: CommCoach", "de": "Store: CommCoach", "fr": "Store: CommCoach"},
|
|
"meta": {"category": "store", "featureCode": "commcoach"}
|
|
},
|
|
{
|
|
"objectKey": "resource.system.api.auth",
|
|
"label": {"en": "Authentication API", "de": "Authentifizierungs-API", "fr": "API d'authentification"},
|
|
"meta": {"endpoint": "/api/auth/*"}
|
|
},
|
|
{
|
|
"objectKey": "resource.system.api.users",
|
|
"label": {"en": "Users API", "de": "Benutzer-API", "fr": "API des utilisateurs"},
|
|
"meta": {"endpoint": "/api/users/*"}
|
|
},
|
|
{
|
|
"objectKey": "resource.system.api.mandates",
|
|
"label": {"en": "Mandates API", "de": "Mandanten-API", "fr": "API des mandats"},
|
|
"meta": {"endpoint": "/api/mandates/*"}
|
|
},
|
|
{
|
|
"objectKey": "resource.system.api.rbac",
|
|
"label": {"en": "RBAC API", "de": "RBAC-API", "fr": "API RBAC"},
|
|
"meta": {"endpoint": "/api/rbac/*"}
|
|
},
|
|
]
|
|
|
|
|
|
def _discoverAicoreProviderObjects() -> List[Dict[str, Any]]:
|
|
"""
|
|
Dynamically discover AICore provider resources for the RBAC catalog.
|
|
Providers are discovered from the model registry at startup.
|
|
"""
|
|
providerLabels = {
|
|
"anthropic": {"en": "Anthropic (Claude)", "de": "Anthropic (Claude)", "fr": "Anthropic (Claude)"},
|
|
"openai": {"en": "OpenAI (GPT)", "de": "OpenAI (GPT)", "fr": "OpenAI (GPT)"},
|
|
"mistral": {"en": "Mistral (Le Chat)", "de": "Mistral (Le Chat)", "fr": "Mistral (Le Chat)"},
|
|
"perplexity": {"en": "Perplexity", "de": "Perplexity", "fr": "Perplexity"},
|
|
"tavily": {"en": "Tavily (Web Search)", "de": "Tavily (Websuche)", "fr": "Tavily (Recherche Web)"},
|
|
"privatellm": {"en": "Private LLM", "de": "Private LLM", "fr": "LLM Privé"},
|
|
"internal": {"en": "Internal", "de": "Intern", "fr": "Interne"},
|
|
}
|
|
|
|
try:
|
|
from modules.aicore.aicoreModelRegistry import modelRegistry
|
|
connectors = modelRegistry.discoverConnectors()
|
|
providers = [c.getConnectorType() for c in connectors]
|
|
|
|
objects = []
|
|
for provider in providers:
|
|
label = providerLabels.get(provider, {"en": provider, "de": provider, "fr": provider})
|
|
objects.append({
|
|
"objectKey": f"resource.aicore.{provider}",
|
|
"label": label,
|
|
"meta": {"provider": provider, "category": "aicore"}
|
|
})
|
|
|
|
if objects:
|
|
logger.info(f"Discovered {len(objects)} AICore provider catalog objects: {providers}")
|
|
return objects
|
|
|
|
except Exception as e:
|
|
logger.warning(f"Failed to discover AICore providers for catalog: {e}")
|
|
return []
|
|
|
|
|
|
def registerFeature(catalogService) -> bool:
|
|
"""
|
|
Register system RBAC objects in the catalog.
|
|
|
|
Args:
|
|
catalogService: The RBAC catalog service instance
|
|
|
|
Returns:
|
|
True if registration was successful
|
|
"""
|
|
try:
|
|
# Register UI objects
|
|
for uiObj in UI_OBJECTS:
|
|
catalogService.registerUiObject(
|
|
featureCode=FEATURE_CODE,
|
|
objectKey=uiObj["objectKey"],
|
|
label=uiObj["label"],
|
|
meta=uiObj.get("meta")
|
|
)
|
|
|
|
# Register DATA objects
|
|
for dataObj in DATA_OBJECTS:
|
|
catalogService.registerDataObject(
|
|
featureCode=FEATURE_CODE,
|
|
objectKey=dataObj["objectKey"],
|
|
label=dataObj["label"],
|
|
meta=dataObj.get("meta")
|
|
)
|
|
|
|
# Register RESOURCE objects
|
|
for resObj in RESOURCE_OBJECTS:
|
|
catalogService.registerResourceObject(
|
|
featureCode=FEATURE_CODE,
|
|
objectKey=resObj["objectKey"],
|
|
label=resObj["label"],
|
|
meta=resObj.get("meta")
|
|
)
|
|
|
|
# Register dynamically discovered AICore provider resources
|
|
aicoreObjects = _discoverAicoreProviderObjects()
|
|
for aicoreObj in aicoreObjects:
|
|
catalogService.registerResourceObject(
|
|
featureCode=FEATURE_CODE,
|
|
objectKey=aicoreObj["objectKey"],
|
|
label=aicoreObj["label"],
|
|
meta=aicoreObj.get("meta")
|
|
)
|
|
|
|
# Register feature definition
|
|
catalogService.registerFeatureDefinition(
|
|
featureCode=FEATURE_CODE,
|
|
label=FEATURE_LABEL,
|
|
icon=FEATURE_ICON
|
|
)
|
|
|
|
logger.info(f"Registered system RBAC objects: {len(UI_OBJECTS)} UI, {len(DATA_OBJECTS)} DATA, {len(RESOURCE_OBJECTS)} RESOURCE")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to register system RBAC objects: {e}")
|
|
return False
|