web-mojo 2.4.6 → 2.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin-models.cjs.js +1 -1
- package/dist/admin-models.cjs.js.map +1 -1
- package/dist/admin-models.es.js +1 -1
- package/dist/admin-models.es.js.map +1 -1
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.cjs.js.map +1 -1
- package/dist/admin.es.js +1 -1
- package/dist/admin.es.js.map +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.es.js +1 -1
- package/dist/chunks/{ChatView-D2WOSxPu.js → ChatView-C_2dRLAY.js} +2 -2
- package/dist/chunks/{ChatView-D2WOSxPu.js.map → ChatView-C_2dRLAY.js.map} +1 -1
- package/dist/chunks/{ChatView-kWguc444.js → ChatView-DVb2Ufq_.js} +2 -2
- package/dist/chunks/{ChatView-kWguc444.js.map → ChatView-DVb2Ufq_.js.map} +1 -1
- package/dist/chunks/{Collection-DNmr743A.js → Collection-Bq_EMAqK.js} +2 -2
- package/dist/chunks/{Collection-DNmr743A.js.map → Collection-Bq_EMAqK.js.map} +1 -1
- package/dist/chunks/{Collection-C0pHSKDH.js → Collection-tgvDhyz_.js} +2 -2
- package/dist/chunks/{Collection-C0pHSKDH.js.map → Collection-tgvDhyz_.js.map} +1 -1
- package/dist/chunks/{ContextMenu-T3yDdsIe.js → ContextMenu-BL_sdgIw.js} +2 -2
- package/dist/chunks/{ContextMenu-T3yDdsIe.js.map → ContextMenu-BL_sdgIw.js.map} +1 -1
- package/dist/chunks/{ContextMenu-BeveGkJr.js → ContextMenu-fIy3upEy.js} +2 -2
- package/dist/chunks/{ContextMenu-BeveGkJr.js.map → ContextMenu-fIy3upEy.js.map} +1 -1
- package/dist/chunks/{DataView-VZIXSsZa.js → DataView-DRQ2yFRz.js} +2 -2
- package/dist/chunks/{DataView-VZIXSsZa.js.map → DataView-DRQ2yFRz.js.map} +1 -1
- package/dist/chunks/{DataView-z2rxXk4L.js → DataView-DW_ufpQo.js} +2 -2
- package/dist/chunks/{DataView-z2rxXk4L.js.map → DataView-DW_ufpQo.js.map} +1 -1
- package/dist/chunks/{FormView-COIPtbrd.js → FormView-eWUWw8oL.js} +2 -2
- package/dist/chunks/{FormView-COIPtbrd.js.map → FormView-eWUWw8oL.js.map} +1 -1
- package/dist/chunks/{FormView-DUXQruUZ.js → FormView-xl_w506t.js} +2 -2
- package/dist/chunks/{FormView-DUXQruUZ.js.map → FormView-xl_w506t.js.map} +1 -1
- package/dist/chunks/{ListView-BjsNHuZ1.js → ListView-Bj4ONQFG.js} +2 -2
- package/dist/chunks/{ListView-BjsNHuZ1.js.map → ListView-Bj4ONQFG.js.map} +1 -1
- package/dist/chunks/{ListView-BxcxIwC3.js → ListView-jyIVhCN3.js} +2 -2
- package/dist/chunks/{ListView-BxcxIwC3.js.map → ListView-jyIVhCN3.js.map} +1 -1
- package/dist/chunks/MetricsCountryMapView-D_666qlW.js +2 -0
- package/dist/chunks/MetricsCountryMapView-D_666qlW.js.map +1 -0
- package/dist/chunks/MetricsCountryMapView-U3xr0QXD.js +2 -0
- package/dist/chunks/MetricsCountryMapView-U3xr0QXD.js.map +1 -0
- package/dist/chunks/Modal-CCVJefEX.js +3 -0
- package/dist/chunks/{Modal-Bm1OQ8Ou.js.map → Modal-CCVJefEX.js.map} +1 -1
- package/dist/chunks/Modal-Uwt-GBgJ.js +3 -0
- package/dist/chunks/{Modal-KnJhNZ1E.js.map → Modal-Uwt-GBgJ.js.map} +1 -1
- package/dist/chunks/Passkeys-DScGUF6p.js +2 -0
- package/dist/chunks/{Passkeys-BlHx11-5.js.map → Passkeys-DScGUF6p.js.map} +1 -1
- package/dist/chunks/{Passkeys-B1-Z4-16.js → Passkeys-c4amXO03.js} +2 -2
- package/dist/chunks/{Passkeys-B1-Z4-16.js.map → Passkeys-c4amXO03.js.map} +1 -1
- package/dist/chunks/{TokenManager-CiNtJclo.js → TokenManager-BRx2U5w4.js} +2 -2
- package/dist/chunks/{TokenManager-CiNtJclo.js.map → TokenManager-BRx2U5w4.js.map} +1 -1
- package/dist/chunks/{TokenManager-6atX9uKB.js → TokenManager-DZP2Lcnz.js} +2 -2
- package/dist/chunks/{TokenManager-6atX9uKB.js.map → TokenManager-DZP2Lcnz.js.map} +1 -1
- package/dist/chunks/{User-9qvKV7G6.js → User-DR-2VJcv.js} +2 -2
- package/dist/chunks/{User-9qvKV7G6.js.map → User-DR-2VJcv.js.map} +1 -1
- package/dist/chunks/{User-BM76Ughk.js → User-e9aOjdHv.js} +2 -2
- package/dist/chunks/{User-BM76Ughk.js.map → User-e9aOjdHv.js.map} +1 -1
- package/dist/chunks/{UserProfileView-DDflzpTa.js → UserProfileView-CCNcNT-M.js} +2 -2
- package/dist/chunks/{UserProfileView-DDflzpTa.js.map → UserProfileView-CCNcNT-M.js.map} +1 -1
- package/dist/chunks/{UserProfileView-cUF8ED9n.js → UserProfileView-PmerV2tC.js} +2 -2
- package/dist/chunks/{UserProfileView-cUF8ED9n.js.map → UserProfileView-PmerV2tC.js.map} +1 -1
- package/dist/chunks/{View-CPWwS19u.js → View-CLWMWXbO.js} +2 -2
- package/dist/chunks/{View-CPWwS19u.js.map → View-CLWMWXbO.js.map} +1 -1
- package/dist/chunks/{View-BxlKR1IW.js → View-DADtcBcb.js} +2 -2
- package/dist/chunks/{View-BxlKR1IW.js.map → View-DADtcBcb.js.map} +1 -1
- package/dist/chunks/{WebApp-BdxhRnnT.js → WebApp-BBrvjnnH.js} +2 -2
- package/dist/chunks/{WebApp-BdxhRnnT.js.map → WebApp-BBrvjnnH.js.map} +1 -1
- package/dist/chunks/{WebApp-Bo_egO0c.js → WebApp-wMWf0qkm.js} +2 -2
- package/dist/chunks/{WebApp-Bo_egO0c.js.map → WebApp-wMWf0qkm.js.map} +1 -1
- package/dist/chunks/exportChart-BszC9qir.js +2 -0
- package/dist/chunks/{exportChart-BTrEOM9j.js.map → exportChart-BszC9qir.js.map} +1 -1
- package/dist/chunks/exportChart-CnAGJjyS.js +2 -0
- package/dist/chunks/{exportChart-BfzZUb1j.js.map → exportChart-CnAGJjyS.js.map} +1 -1
- package/dist/chunks/{index-DsID1QpB.js → index-B312g4f-.js} +2 -2
- package/dist/chunks/{index-DsID1QpB.js.map → index-B312g4f-.js.map} +1 -1
- package/dist/chunks/{index-Cxffar1o.js → index-D7ITRVln.js} +2 -2
- package/dist/chunks/{index-Cxffar1o.js.map → index-D7ITRVln.js.map} +1 -1
- package/dist/chunks/{version-BxLEknar.js → version-Cz_nlYsB.js} +2 -2
- package/dist/chunks/{version-BxLEknar.js.map → version-Cz_nlYsB.js.map} +1 -1
- package/dist/chunks/{version-BYy2UAT0.js → version-D2vRYNuT.js} +2 -2
- package/dist/chunks/{version-BYy2UAT0.js.map → version-D2vRYNuT.js.map} +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +1 -1
- package/dist/map.cjs.js +1 -1
- package/dist/map.es.js +1 -1
- package/dist/timeline.cjs.js +1 -1
- package/dist/timeline.es.js +1 -1
- package/dist/user-profile.cjs.js +1 -1
- package/dist/user-profile.es.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/AssistantPanelView-CkQEcaFk.js +0 -2
- package/dist/chunks/AssistantPanelView-CkQEcaFk.js.map +0 -1
- package/dist/chunks/AssistantPanelView-D1wEbgtM.js +0 -2
- package/dist/chunks/AssistantPanelView-D1wEbgtM.js.map +0 -1
- package/dist/chunks/MetricsCountryMapView-Bp3qoVHp.js +0 -2
- package/dist/chunks/MetricsCountryMapView-Bp3qoVHp.js.map +0 -1
- package/dist/chunks/MetricsCountryMapView-CWjIEBJB.js +0 -2
- package/dist/chunks/MetricsCountryMapView-CWjIEBJB.js.map +0 -1
- package/dist/chunks/Modal-Bm1OQ8Ou.js +0 -3
- package/dist/chunks/Modal-KnJhNZ1E.js +0 -3
- package/dist/chunks/Passkeys-BlHx11-5.js +0 -2
- package/dist/chunks/TicketPanelView-DVePzWyJ.js +0 -2
- package/dist/chunks/TicketPanelView-DVePzWyJ.js.map +0 -1
- package/dist/chunks/TicketPanelView-TYh5iZiR.js +0 -2
- package/dist/chunks/TicketPanelView-TYh5iZiR.js.map +0 -1
- package/dist/chunks/admin-CHPo4iDn.js +0 -2
- package/dist/chunks/admin-CHPo4iDn.js.map +0 -1
- package/dist/chunks/admin-CucHFXfD.js +0 -2
- package/dist/chunks/admin-CucHFXfD.js.map +0 -1
- package/dist/chunks/admin-models-CkHjtMHf.js +0 -2
- package/dist/chunks/admin-models-CkHjtMHf.js.map +0 -1
- package/dist/chunks/admin-models-DLtFboxy.js +0 -2
- package/dist/chunks/admin-models-DLtFboxy.js.map +0 -1
- package/dist/chunks/exportChart-BTrEOM9j.js +0 -2
- package/dist/chunks/exportChart-BfzZUb1j.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"User-BM76Ughk.js","sources":["../../src/core/models/Group.js","../../src/core/models/User.js"],"sourcesContent":["\nimport Collection from '@core/Collection.js';\nimport Model from '@core/Model.js';\n\n/**\n * Group Model - Represents an organization, team, or group entity\n *\n * Features:\n * - Hierarchical group support (parent/child relationships)\n * - Member management\n * - Search and filtering capabilities\n * - Role-based permissions within groups\n * - Metadata and settings management\n */\nclass Group extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/group'\n });\n }\n}\n\n/**\n * GroupCollection - Enhanced collection for managing groups with advanced search and filtering\n */\nclass GroupList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: Group,\n endpoint: '/api/group',\n size: 10,\n ...options\n });\n }\n}\n\nconst GroupKinds = {\n 'org': 'Organization',\n 'division': 'Division',\n 'department': 'Department',\n 'team': 'Team',\n 'merchant': 'Merchant',\n 'partner': 'Partner',\n 'client': 'Client',\n 'iso': 'ISO',\n 'sales': 'Sales',\n 'reseller': 'Reseller',\n 'location': 'Location',\n 'region': 'Region',\n 'route': 'Route',\n 'project': 'Project',\n \"inventory\": \"Inventory\",\n 'test': 'Testing',\n 'misc': 'Miscellaneous',\n 'qa': 'Quality Assurance'\n};\n\n// Convert GroupKinds to select options\nconst GroupKindOptions = Object.entries(GroupKinds).map(([key, label]) => ({\n value: key,\n label: label\n}));\n\n/**\n * Form configurations for group management\n */\nconst GroupForms = {\n create: {\n title: 'Create Group',\n fields: [\n {\n name: 'name',\n type: 'text',\n label: 'Group Name',\n required: true,\n placeholder: 'Enter group name'\n },\n {\n name: 'kind',\n type: 'select',\n label: 'Group Kind',\n required: true,\n options: GroupKindOptions\n },\n {\n type: 'collection',\n name: 'parent',\n label: 'Parent Group',\n Collection: GroupList, // Collection class\n labelField: 'name', // Field to display in dropdown\n valueField: 'id', // Field to use as value\n maxItems: 10, // Max items to show in dropdown\n placeholder: 'Search groups...',\n emptyFetch: false,\n debounceMs: 300, // Search debounce delay\n }\n ]\n },\n\n edit: {\n title: 'Edit Group',\n fields: [\n {\n name: 'name',\n type: 'text',\n label: 'Group Name',\n required: true,\n placeholder: 'Enter group name',\n },\n {\n name: 'kind',\n type: 'select',\n label: 'Group Kind',\n required: true,\n options: GroupKindOptions\n },\n {\n type: 'collection',\n name: 'parent',\n label: 'Parent Group',\n Collection: GroupList, // Collection class\n labelField: 'name', // Field to display in dropdown\n valueField: 'id', // Field to use as value\n maxItems: 10, // Max items to show in dropdown\n placeholder: 'Search groups...',\n emptyFetch: false,\n debounceMs: 300, // Search debounce delay\n },\n {\n name: 'metadata.domain',\n type: 'text',\n label: 'Default Domain',\n placeholder: 'Enter Domain',\n },\n {\n name: 'metadata.portal',\n type: 'text',\n label: 'Default Portal',\n placeholder: 'Enter Portal URL',\n },\n {\n name: 'is_active',\n type: 'switch',\n label: 'Is Active',\n cols: 4\n },\n ]\n },\n\n detailed: {\n title: 'Group Details',\n fields: [\n // Profile Header\n {\n type: 'header',\n text: 'Profile Information',\n level: 4,\n class: 'text-primary mb-3'\n },\n\n // Avatar and Basic Info\n {\n type: 'group',\n columns: { xs: 12, md: 4 },\n fields: [\n {\n type: 'image',\n name: 'avatar',\n size: 'lg',\n imageSize: { width: 200, height: 200 },\n placeholder: 'Upload your avatar',\n help: 'Square images work best',\n columns: 12\n },\n {\n name: 'is_active',\n type: 'switch',\n label: 'Is Active',\n columns: 12\n },\n ]\n },\n\n // Profile Details\n {\n type: 'group',\n columns: { xs: 12, md: 8 },\n title: 'Details',\n fields: [\n {\n name: 'name',\n type: 'text',\n label: 'Group Name',\n required: true,\n placeholder: 'Enter group name',\n columns: 12\n },\n {\n name: 'kind',\n type: 'select',\n label: 'Group Kind',\n required: true,\n columns: 12,\n options: [\n { value: 'org', label: 'Organization' },\n { value: 'team', label: 'Team' },\n { value: 'department', label: 'Department' },\n { value: 'merchant', label: 'Merchant' },\n { value: 'iso', label: 'ISO' },\n { value: 'group', label: 'Group' }\n ]\n },\n {\n type: 'collection',\n name: 'parent',\n label: 'Parent Group',\n Collection: GroupList, // Collection class\n labelField: 'name', // Field to display in dropdown\n valueField: 'id', // Field to use as value\n maxItems: 10, // Max items to show in dropdown\n placeholder: 'Search groups...',\n emptyFetch: false,\n debounceMs: 300, // Search debounce delay\n columns: 12\n }\n ]\n },\n\n // Account Settings\n {\n type: 'group',\n columns: 12,\n title: 'Account Settings',\n class: \"pt-3\",\n fields: [\n {\n type: 'select',\n name: 'metadata.timezone',\n label: 'Timezone',\n columns: 6,\n value: 'America/Los_Angeles',\n options: [\n { value: 'America/New_York', text: 'Eastern Time' },\n { value: 'America/Chicago', text: 'Central Time' },\n { value: 'America/Denver', text: 'Mountain Time' },\n { value: 'America/Los_Angeles', text: 'Pacific Time' },\n { value: 'UTC', text: 'UTC' }\n ]\n },\n {\n type: 'select',\n name: 'metadata.eod_hour',\n label: 'End of Day Hour',\n columns: 6,\n options: [\n { value: 0, text: 'Midnight' },\n { value: 1, text: '1 AM' },\n { value: 2, text: '2 AM' },\n { value: 3, text: '3 AM' },\n { value: 4, text: '4 AM' },\n { value: 5, text: '5 AM' },\n { value: 6, text: '6 AM' },\n { value: 7, text: '7 AM' },\n { value: 8, text: '8 AM' },\n { value: 9, text: '9 AM' },\n { value: 10, text: '10 AM' },\n { value: 11, text: '11 AM' },\n { value: 12, text: '12 PM' },\n { value: 13, text: '1 PM' },\n { value: 14, text: '2 PM' },\n { value: 15, text: '3 PM' },\n { value: 16, text: '4 PM' },\n { value: 17, text: '5 PM' },\n { value: 18, text: '6 PM' },\n { value: 19, text: '7 PM' },\n { value: 20, text: '8 PM' },\n { value: 21, text: '9 PM' },\n { value: 22, text: '10 PM' },\n { value: 23, text: '11 PM' }\n ]\n }\n ]\n },\n {\n type: \"text\",\n label: \"Email Template (Prefix)\",\n name: \"metadata.email_template\",\n columns: 12\n }\n ]\n },\n};\n\nGroup.EDIT_FORM = GroupForms.edit;\nGroup.ADD_FORM = GroupForms.create;\nGroup.CREATE_FORM = GroupForms.create; // Alias for compatibility\nGroup.GroupKindOptions = GroupKindOptions;\nGroup.GroupKinds = GroupKinds;\nexport { Group, GroupList, GroupForms };\n","import Collection from '@core/Collection.js';\nimport Model from '@core/Model.js';\n\nimport { GroupList } from './Group.js';\n\nclass User extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/user'\n });\n }\n\n hasPermission(permission) {\n if (this.get(\"is_superuser\")) return true;\n if (Array.isArray(permission)) {\n return permission.some(p => this.hasPermission(p));\n }\n\n // Check if permission has \"sys.\" prefix\n const isSysPermission = permission.startsWith('sys.');\n const permissionToCheck = isSysPermission ? permission.substring(4) : permission;\n\n if (this._hasPermission(permissionToCheck)) {\n return true;\n }\n\n // Only check member permissions if it's not a system permission\n if (!isSysPermission && this.member && this.member.hasPermission(permission)) {\n return true;\n }\n\n return false;\n }\n\n _hasPermission(permission) {\n const permissions = this.get(\"permissions\");\n if (!permissions) {\n return false;\n }\n if (permissions[permission] == true) {\n return true;\n }\n // Check if user has the category permission that covers this granular perm\n const category = User.GRANULAR_TO_CATEGORY[permission];\n if (category && permissions[category] == true) {\n return true;\n }\n return false;\n }\n\n hasPerm(p) {\n return this.hasPermission(p);\n }\n}\n\nclass UserList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: User,\n endpoint: '/api/user',\n ...options\n });\n }\n}\n\n// ── Category Permissions (broad domain-level access) ──────────────\nUser.CATEGORY_PERMISSIONS = [\n { name: \"view_admin\", label: \"Admin Panel\", tooltip: \"Access the admin panel, Mojo, and system tools\" },\n { name: \"security\", label: \"Security\", tooltip: \"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs\" },\n { name: \"users\", label: \"Users\", tooltip: \"User records, passkeys, TOTP, API keys, OAuth, devices, locations\" },\n { name: \"groups\", label: \"Groups\", tooltip: \"Groups, members, group API keys, settings\" },\n { name: \"comms\", label: \"Communications\", tooltip: \"Email, phone, SMS, push notifications, chat, notifications\" },\n { name: \"jobs\", label: \"Jobs\", tooltip: \"Jobs, job events, job logs, runners, queue control, system stats\" },\n { name: \"metrics\", label: \"Metrics\", tooltip: \"Metrics recording, fetching, categories, values, permissions\" },\n { name: \"files\", label: \"Files\", tooltip: \"File managers, files, renditions, vault files, vault data, S3 buckets\" },\n { name: \"assistant\", label: \"Mojo\", tooltip: \"Access to Mojo\" },\n { name: \"comms\", label: \"Communication\", tooltip: \"Ability to notify users\" },\n];\n\n// ── Granular Permissions (fine-grained view/manage pairs) ─────────\nUser.GRANULAR_PERMISSION_TABS = [\n {\n label: 'Account',\n permissions: [\n { name: \"view_users\", label: \"View Users\" },\n { name: \"manage_users\", label: \"Manage Users\" },\n { name: \"view_groups\", label: \"View Groups\" },\n { name: \"manage_groups\", label: \"Manage Groups\" },\n { name: \"manage_group\", label: \"Manage Own Group\" },\n { name: \"view_members\", label: \"View Members\" },\n { name: \"manage_settings\", label: \"Manage Settings\" },\n ]\n },\n {\n label: 'Communication',\n permissions: [\n { name: \"manage_chat\", label: \"Manage Chat\" },\n { name: \"manage_aws\", label: \"Manage Email (AWS)\" },\n { name: \"view_notifications\", label: \"View Notifications\" },\n { name: \"manage_notifications\", label: \"Manage Notifications\" },\n { name: \"send_notifications\", label: \"Send Notifications\" },\n { name: \"view_devices\", label: \"View Push Devices\" },\n { name: \"manage_devices\", label: \"Manage Push Devices\" },\n { name: \"manage_push_config\", label: \"Push Config\" },\n { name: \"view_phone_numbers\", label: \"View Phone Numbers\" },\n { name: \"manage_phone_numbers\", label: \"Manage Phone Numbers\" },\n { name: \"manage_phone_config\", label: \"Phone Config\" },\n { name: \"view_sms\", label: \"View SMS\" },\n { name: \"manage_sms\", label: \"Manage SMS\" },\n { name: \"send_sms\", label: \"Send SMS\" },\n ]\n },\n {\n label: 'Platform',\n permissions: [\n { name: \"view_security\", label: \"View Security\" },\n { name: \"manage_security\", label: \"Manage Security\" },\n { name: \"admin\", label: \"Log Admin\" },\n { name: \"view_logs\", label: \"View Logs\" },\n { name: \"manage_logs\", label: \"Manage Logs\" },\n { name: \"view_jobs\", label: \"View Jobs\" },\n { name: \"manage_jobs\", label: \"Manage Jobs\" },\n { name: \"view_metrics\", label: \"View Metrics\" },\n { name: \"manage_metrics\", label: \"Manage Metrics\" },\n { name: \"write_metrics\", label: \"Write Metrics\" },\n { name: \"view_fileman\", label: \"View File Managers\" },\n { name: \"manage_files\", label: \"Manage Files\" },\n { name: \"view_vault\", label: \"View Vault\" },\n { name: \"manage_vault\", label: \"Manage Vault\" },\n { name: \"manage_docit\", label: \"Manage Docs\" },\n { name: \"manage_shortlinks\", label: \"Manage Shortlinks\" },\n ]\n },\n];\n\n// ── Category → Granular mapping ───────────────────────────────────\n// Maps each category permission to the granular permissions it covers.\n// If a user has a category perm, all its granular perms are implicitly granted.\nUser.CATEGORY_GRANULAR_MAP = {\n security: [\"view_security\", \"manage_security\"],\n users: [\"view_users\", \"manage_users\", \"view_members\"],\n groups: [\"view_groups\", \"manage_groups\", \"manage_group\"],\n comms: [\"manage_chat\", \"manage_aws\", \"view_notifications\", \"manage_notifications\", \"send_notifications\",\n \"view_devices\", \"manage_devices\", \"manage_push_config\",\n \"view_phone_numbers\", \"manage_phone_numbers\", \"manage_phone_config\",\n \"view_sms\", \"manage_sms\", \"send_sms\"],\n jobs: [\"view_jobs\", \"manage_jobs\"],\n metrics: [\"view_metrics\", \"manage_metrics\", \"write_metrics\"],\n files: [\"view_fileman\", \"manage_files\", \"view_vault\", \"manage_vault\"]\n};\n\n// ── App-level extension points (empty by default) ─────────────────\n// Mutate (push, splice, key-set) these source structures, then call\n// User.rebuildPermissions() to refresh the cached field arrays the UI\n// reads from. Apps may also extend User.GRANULAR_PERMISSION_TABS and\n// User.CATEGORY_GRANULAR_MAP and have rebuildPermissions() pick them up.\nUser.APP_CATEGORY_PERMISSIONS = [];\nUser.APP_GRANULAR_PERMISSIONS = [];\n\n// ── Field builder ─────────────────────────────────────────────────\n// Public so apps building custom permission forms can reuse the exact\n// shape (avoids drift if the framework's switch field shape evolves).\nUser._permSwitch = function(p) {\n return {\n name: `permissions.${p.name}`,\n type: 'switch',\n label: p.label,\n columns: 6,\n ...(p.tooltip ? { tooltip: p.tooltip } : {})\n };\n};\n\n// ── Live caches — populated by rebuildPermissions() ───────────────\n// Initialized here so consumers (e.g. UserForms.permissions.fields)\n// can hold a reference; rebuildPermissions() mutates these arrays in\n// place to keep cached references current across re-registrations.\nUser.PERMISSIONS = [];\nUser.PERMISSION_FIELDS = [];\nUser.CATEGORY_PERMISSION_FIELDS = [];\nUser.GRANULAR_PERMISSION_FIELDS = [];\nUser.GRANULAR_TO_CATEGORY = {};\n\n// Recompute every cached permission structure from the live source\n// arrays (CATEGORY_PERMISSIONS, GRANULAR_PERMISSION_TABS, the APP_*\n// extension points, CATEGORY_GRANULAR_MAP). Idempotent — safe to call\n// multiple times. Mutates caches in place so existing references stay\n// live; UI code that read User.PERMISSION_FIELDS once still sees the\n// updated list after a rebuild.\nUser.rebuildPermissions = function() {\n const _ps = User._permSwitch;\n\n // Flat list of every registered permission.\n User.PERMISSIONS.length = 0;\n User.PERMISSIONS.push(\n ...User.CATEGORY_PERMISSIONS,\n ...User.GRANULAR_PERMISSION_TABS.flatMap(tab => tab.permissions),\n ...User.APP_CATEGORY_PERMISSIONS,\n ...User.APP_GRANULAR_PERMISSIONS\n );\n\n // Flat field list (flat form, no tabs).\n User.PERMISSION_FIELDS.length = 0;\n User.PERMISSION_FIELDS.push(...User.PERMISSIONS.map(_ps));\n\n // \"Permissions\" sidenav section — tabset with System (+ App when non-empty).\n const categoryTabs = [\n { label: 'System', fields: User.CATEGORY_PERMISSIONS.map(_ps) }\n ];\n if (User.APP_CATEGORY_PERMISSIONS.length > 0) {\n categoryTabs.push({ label: 'App', fields: User.APP_CATEGORY_PERMISSIONS.map(_ps) });\n }\n User.CATEGORY_PERMISSION_FIELDS.length = 0;\n User.CATEGORY_PERMISSION_FIELDS.push({ type: 'tabset', tabs: categoryTabs });\n\n // \"Adv Permissions\" sidenav section — one tab per registered tab (+ App when non-empty).\n const granularTabs = User.GRANULAR_PERMISSION_TABS.map(tab => ({\n label: tab.label,\n fields: tab.permissions.map(_ps)\n }));\n if (User.APP_GRANULAR_PERMISSIONS.length > 0) {\n granularTabs.push({ label: 'App', fields: User.APP_GRANULAR_PERMISSIONS.map(_ps) });\n }\n User.GRANULAR_PERMISSION_FIELDS.length = 0;\n User.GRANULAR_PERMISSION_FIELDS.push({ type: 'tabset', tabs: granularTabs });\n\n // Reverse lookup: granular perm name → category name.\n for (const k of Object.keys(User.GRANULAR_TO_CATEGORY)) {\n delete User.GRANULAR_TO_CATEGORY[k];\n }\n for (const [category, perms] of Object.entries(User.CATEGORY_GRANULAR_MAP)) {\n for (const perm of perms) {\n User.GRANULAR_TO_CATEGORY[perm] = category;\n }\n }\n};\n\n// Register app-level category → granular mappings so a held category\n// permission implicitly satisfies a gate listing one of its granulars.\n// Pass an object of the same shape as CATEGORY_GRANULAR_MAP, e.g.:\n// User.registerCategoryMap({ app_cat: ['view_app_thing', 'manage_app_thing'] });\n// Merges with any existing entries for the same category and triggers\n// rebuildPermissions() so caches stay coherent.\nUser.registerCategoryMap = function(map) {\n if (!map) return;\n let touched = false;\n for (const [category, perms] of Object.entries(map)) {\n if (!Array.isArray(perms)) continue;\n const existing = User.CATEGORY_GRANULAR_MAP[category] || [];\n User.CATEGORY_GRANULAR_MAP[category] = Array.from(new Set([...existing, ...perms]));\n touched = true;\n }\n if (touched) User.rebuildPermissions();\n};\n\n// One-shot atomic registration of app permissions. Bundles every\n// extension-point mutation into a single call followed by one\n// rebuildPermissions() at the end, so apps don't have to know which\n// arrays to push and which map to merge.\n//\n// User.registerPermissions({\n// categories: [{ name: 'app_cat', label: 'App Category' }],\n// granularPermissions: [{ name: 'app_perm', label: 'App Perm' }],\n// granularTabs: [{\n// label: 'Custom',\n// permissions: [{ name: 'view_app_thing', label: 'View App Thing' }]\n// }],\n// categoryGranularMap: { app_cat: ['view_app_thing'] }\n// });\n//\n// All four keys are optional. Arrays are appended; the map is merged\n// (existing category entries are preserved + deduped).\nUser.registerPermissions = function(spec) {\n if (!spec) return;\n if (Array.isArray(spec.categories)) {\n User.APP_CATEGORY_PERMISSIONS.push(...spec.categories);\n }\n if (Array.isArray(spec.granularPermissions)) {\n User.APP_GRANULAR_PERMISSIONS.push(...spec.granularPermissions);\n }\n if (Array.isArray(spec.granularTabs)) {\n User.GRANULAR_PERMISSION_TABS.push(...spec.granularTabs);\n }\n if (spec.categoryGranularMap) {\n for (const [category, perms] of Object.entries(spec.categoryGranularMap)) {\n if (!Array.isArray(perms)) continue;\n const existing = User.CATEGORY_GRANULAR_MAP[category] || [];\n User.CATEGORY_GRANULAR_MAP[category] = Array.from(new Set([...existing, ...perms]));\n }\n }\n User.rebuildPermissions();\n};\n\n// Initial population — mirrors the old IIFE-built state exactly.\nUser.rebuildPermissions();\n\nconst UserForms = {\n create: {\n title: 'Create User',\n fields: [\n { name: 'email', type: 'text', label: 'Email', required: true },\n { name: 'phone_number', type: 'text', label: 'Phone number', columns: 12 },\n { name: 'display_name', type: 'text', label: 'Display Name' }\n ]\n },\n edit: {\n title: 'Edit User',\n fields: [\n { name: 'email', type: 'email', label: 'Email', columns: 12 },\n { name: 'display_name', type: 'text', label: 'Display Name', columns: 12},\n { name: 'phone_number', type: 'text', label: 'Phone number', columns: 12 },\n { type: 'collection', name: 'org', label: 'Organization', Collection: GroupList, labelField: 'name', valueField: 'id', columns: 12 },\n ]\n },\n permissions: {\n title: 'Edit Permissions',\n fields: User.PERMISSION_FIELDS\n }\n};\n\n\n// DataView configuration for User model\nconst UserDataView = {\n // Basic user profile view\n profile: {\n title: 'User Profile',\n columns: 2,\n fields: [\n {\n name: 'id',\n label: 'User ID',\n type: 'number',\n columns: 4\n },\n {\n name: 'last_login',\n label: 'Last Login',\n type: 'datetime',\n format: 'relative',\n columns: 4\n },\n {\n name: 'last_activity',\n label: 'Last Activity',\n type: 'datetime',\n format: 'relative',\n columns: 4\n },\n {\n name: 'username',\n label: 'Username',\n type: 'text',\n format: 'lowercase',\n columns: 4\n },\n {\n name: 'display_name',\n label: 'Display Name',\n type: 'text',\n columns: 4\n },\n\n {\n name: 'email',\n label: 'Email',\n type: 'email',\n columns: 12\n },\n\n {\n name: 'org.name',\n label: 'Organization',\n type: 'text',\n columns: 6\n },\n {\n name: 'phone_number',\n label: 'Phone Number',\n type: 'text',\n columns: 6\n }\n ]\n },\n\n // Activity tracking view\n activity: {\n title: 'User Activity',\n columns: 2,\n fields: [\n {\n name: 'last_login',\n label: 'Last Login',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n },\n {\n name: 'last_activity',\n label: 'Last Activity',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n }\n ]\n },\n\n // Comprehensive view with all data\n detailed: {\n title: 'Detailed User Information',\n columns: 2,\n showEmptyValues: true,\n emptyValueText: 'Not set',\n fields: [\n // Basic Info Section\n {\n name: 'id',\n label: 'User ID',\n type: 'number',\n colSize: 3\n },\n {\n name: 'display_name',\n label: 'Display Name',\n type: 'text',\n format: 'capitalize|default(\"Unnamed User\")',\n colSize: 9\n },\n {\n name: 'username',\n label: 'Username',\n type: 'text',\n format: 'lowercase',\n colSize: 6\n },\n {\n name: 'email',\n label: 'Email Address',\n type: 'email',\n colSize: 6\n },\n {\n name: 'phone_number',\n label: 'Phone Number',\n type: 'phone',\n format: 'phone|default(\"Not provided\")',\n colSize: 6\n },\n {\n name: 'is_active',\n label: 'Account Status',\n type: 'boolean',\n colSize: 6\n },\n\n // Activity Info\n {\n name: 'last_login',\n label: 'Last Login',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n },\n {\n name: 'last_activity',\n label: 'Last Activity',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n },\n\n // Avatar Info\n {\n name: 'avatar.url',\n label: 'Avatar',\n type: 'url',\n colSize: 12\n },\n\n // Complex Data (will use full width automatically)\n {\n name: 'permissions',\n label: 'User Permissions',\n type: 'dataview',\n dataViewColumns: 2,\n showEmptyValues: false\n },\n {\n name: 'metadata',\n label: 'User Metadata',\n type: 'dataview',\n dataViewColumns: 1\n },\n {\n name: 'avatar',\n label: 'Avatar Details',\n type: 'dataview',\n dataViewColumns: 1\n }\n ]\n },\n\n // Permissions-focused view\n permissions: {\n title: 'User Permissions',\n columns: 1,\n fields: [\n {\n name: 'display_name',\n label: 'User',\n type: 'text',\n format: 'capitalize',\n columns: 12\n },\n {\n name: 'permissions',\n label: 'Assigned Permissions',\n type: 'dataview',\n dataViewColumns: 3,\n showEmptyValues: false,\n colSize: 12\n }\n ]\n },\n\n // Compact summary view\n summary: {\n title: 'User Summary',\n columns: 3,\n fields: [\n {\n name: 'display_name',\n label: 'Name',\n type: 'text',\n format: 'capitalize|truncate(30)'\n },\n {\n name: 'email',\n label: 'Email',\n type: 'email'\n },\n {\n name: 'is_active',\n label: 'Status',\n type: 'boolean'\n },\n {\n name: 'last_activity',\n label: 'Last Seen',\n type: 'datetime',\n format: 'relative',\n colSize: 12\n }\n ]\n }\n};\n\nUser.DATA_VIEW = UserDataView.detailed;\nUser.EDIT_FORM = UserForms.edit;\nUser.ADD_FORM = UserForms.create;\n\n/* =========================\n * UserDevice\n * ========================= */\nclass UserDevice extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/user/device',\n });\n }\n\n static async getByDuid(duid) {\n const model = new UserDevice();\n const resp = await model.rest.GET('/api/user/device/lookup', { duid: duid });\n if (resp.success && resp.data && resp.data.data) {\n // A direct lookup should return a single object\n return new UserDevice(resp.data.data);\n }\n return null;\n }\n}\n\nclass UserDeviceList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: UserDevice,\n endpoint: '/api/user/device',\n ...options,\n });\n }\n}\n\n/* =========================\n * UserDeviceLocation\n * ========================= */\nclass UserDeviceLocation extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/user/device/location',\n });\n }\n}\n\nclass UserDeviceLocationList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: UserDeviceLocation,\n endpoint: '/api/user/device/location',\n ...options,\n });\n }\n}\n\nexport { User, UserList, UserForms, UserDataView, UserDevice, UserDeviceList, UserDeviceLocation, UserDeviceLocationList };\n"],"names":["Group","Model","constructor","data","super","endpoint","GroupList","Collection","options","ModelClass","size","GroupKinds","org","division","department","team","merchant","partner","client","iso","sales","reseller","location","region","route","project","inventory","test","misc","qa","GroupKindOptions","Object","entries","map","key","label","value","GroupForms","create","title","fields","name","type","required","placeholder","labelField","valueField","maxItems","emptyFetch","debounceMs","edit","cols","detailed","text","level","class","columns","xs","md","imageSize","width","height","help","EDIT_FORM","ADD_FORM","CREATE_FORM","User","hasPermission","permission","this","get","Array","isArray","some","p","isSysPermission","startsWith","permissionToCheck","substring","_hasPermission","member","permissions","category","GRANULAR_TO_CATEGORY","hasPerm","UserList","CATEGORY_PERMISSIONS","tooltip","GRANULAR_PERMISSION_TABS","CATEGORY_GRANULAR_MAP","security","users","groups","comms","jobs","metrics","files","APP_CATEGORY_PERMISSIONS","APP_GRANULAR_PERMISSIONS","_permSwitch","PERMISSIONS","PERMISSION_FIELDS","CATEGORY_PERMISSION_FIELDS","GRANULAR_PERMISSION_FIELDS","rebuildPermissions","_ps","length","push","flatMap","tab","categoryTabs","tabs","granularTabs","k","keys","perms","perm","registerCategoryMap","touched","existing","from","Set","registerPermissions","spec","categories","granularPermissions","categoryGranularMap","UserForms","UserDataView","profile","format","activity","colSize","showEmptyValues","emptyValueText","dataViewColumns","summary","DATA_VIEW","UserDevice","getByDuid","duid","model","resp","rest","GET","success","UserDeviceList","UserDeviceLocation","UserDeviceLocationList"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"User-e9aOjdHv.js","sources":["../../src/core/models/Group.js","../../src/core/models/User.js"],"sourcesContent":["\nimport Collection from '@core/Collection.js';\nimport Model from '@core/Model.js';\n\n/**\n * Group Model - Represents an organization, team, or group entity\n *\n * Features:\n * - Hierarchical group support (parent/child relationships)\n * - Member management\n * - Search and filtering capabilities\n * - Role-based permissions within groups\n * - Metadata and settings management\n */\nclass Group extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/group'\n });\n }\n}\n\n/**\n * GroupCollection - Enhanced collection for managing groups with advanced search and filtering\n */\nclass GroupList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: Group,\n endpoint: '/api/group',\n size: 10,\n ...options\n });\n }\n}\n\nconst GroupKinds = {\n 'org': 'Organization',\n 'division': 'Division',\n 'department': 'Department',\n 'team': 'Team',\n 'merchant': 'Merchant',\n 'partner': 'Partner',\n 'client': 'Client',\n 'iso': 'ISO',\n 'sales': 'Sales',\n 'reseller': 'Reseller',\n 'location': 'Location',\n 'region': 'Region',\n 'route': 'Route',\n 'project': 'Project',\n \"inventory\": \"Inventory\",\n 'test': 'Testing',\n 'misc': 'Miscellaneous',\n 'qa': 'Quality Assurance'\n};\n\n// Convert GroupKinds to select options\nconst GroupKindOptions = Object.entries(GroupKinds).map(([key, label]) => ({\n value: key,\n label: label\n}));\n\n/**\n * Form configurations for group management\n */\nconst GroupForms = {\n create: {\n title: 'Create Group',\n fields: [\n {\n name: 'name',\n type: 'text',\n label: 'Group Name',\n required: true,\n placeholder: 'Enter group name'\n },\n {\n name: 'kind',\n type: 'select',\n label: 'Group Kind',\n required: true,\n options: GroupKindOptions\n },\n {\n type: 'collection',\n name: 'parent',\n label: 'Parent Group',\n Collection: GroupList, // Collection class\n labelField: 'name', // Field to display in dropdown\n valueField: 'id', // Field to use as value\n maxItems: 10, // Max items to show in dropdown\n placeholder: 'Search groups...',\n emptyFetch: false,\n debounceMs: 300, // Search debounce delay\n }\n ]\n },\n\n edit: {\n title: 'Edit Group',\n fields: [\n {\n name: 'name',\n type: 'text',\n label: 'Group Name',\n required: true,\n placeholder: 'Enter group name',\n },\n {\n name: 'kind',\n type: 'select',\n label: 'Group Kind',\n required: true,\n options: GroupKindOptions\n },\n {\n type: 'collection',\n name: 'parent',\n label: 'Parent Group',\n Collection: GroupList, // Collection class\n labelField: 'name', // Field to display in dropdown\n valueField: 'id', // Field to use as value\n maxItems: 10, // Max items to show in dropdown\n placeholder: 'Search groups...',\n emptyFetch: false,\n debounceMs: 300, // Search debounce delay\n },\n {\n name: 'metadata.domain',\n type: 'text',\n label: 'Default Domain',\n placeholder: 'Enter Domain',\n },\n {\n name: 'metadata.portal',\n type: 'text',\n label: 'Default Portal',\n placeholder: 'Enter Portal URL',\n },\n {\n name: 'is_active',\n type: 'switch',\n label: 'Is Active',\n cols: 4\n },\n ]\n },\n\n detailed: {\n title: 'Group Details',\n fields: [\n // Profile Header\n {\n type: 'header',\n text: 'Profile Information',\n level: 4,\n class: 'text-primary mb-3'\n },\n\n // Avatar and Basic Info\n {\n type: 'group',\n columns: { xs: 12, md: 4 },\n fields: [\n {\n type: 'image',\n name: 'avatar',\n size: 'lg',\n imageSize: { width: 200, height: 200 },\n placeholder: 'Upload your avatar',\n help: 'Square images work best',\n columns: 12\n },\n {\n name: 'is_active',\n type: 'switch',\n label: 'Is Active',\n columns: 12\n },\n ]\n },\n\n // Profile Details\n {\n type: 'group',\n columns: { xs: 12, md: 8 },\n title: 'Details',\n fields: [\n {\n name: 'name',\n type: 'text',\n label: 'Group Name',\n required: true,\n placeholder: 'Enter group name',\n columns: 12\n },\n {\n name: 'kind',\n type: 'select',\n label: 'Group Kind',\n required: true,\n columns: 12,\n options: [\n { value: 'org', label: 'Organization' },\n { value: 'team', label: 'Team' },\n { value: 'department', label: 'Department' },\n { value: 'merchant', label: 'Merchant' },\n { value: 'iso', label: 'ISO' },\n { value: 'group', label: 'Group' }\n ]\n },\n {\n type: 'collection',\n name: 'parent',\n label: 'Parent Group',\n Collection: GroupList, // Collection class\n labelField: 'name', // Field to display in dropdown\n valueField: 'id', // Field to use as value\n maxItems: 10, // Max items to show in dropdown\n placeholder: 'Search groups...',\n emptyFetch: false,\n debounceMs: 300, // Search debounce delay\n columns: 12\n }\n ]\n },\n\n // Account Settings\n {\n type: 'group',\n columns: 12,\n title: 'Account Settings',\n class: \"pt-3\",\n fields: [\n {\n type: 'select',\n name: 'metadata.timezone',\n label: 'Timezone',\n columns: 6,\n value: 'America/Los_Angeles',\n options: [\n { value: 'America/New_York', text: 'Eastern Time' },\n { value: 'America/Chicago', text: 'Central Time' },\n { value: 'America/Denver', text: 'Mountain Time' },\n { value: 'America/Los_Angeles', text: 'Pacific Time' },\n { value: 'UTC', text: 'UTC' }\n ]\n },\n {\n type: 'select',\n name: 'metadata.eod_hour',\n label: 'End of Day Hour',\n columns: 6,\n options: [\n { value: 0, text: 'Midnight' },\n { value: 1, text: '1 AM' },\n { value: 2, text: '2 AM' },\n { value: 3, text: '3 AM' },\n { value: 4, text: '4 AM' },\n { value: 5, text: '5 AM' },\n { value: 6, text: '6 AM' },\n { value: 7, text: '7 AM' },\n { value: 8, text: '8 AM' },\n { value: 9, text: '9 AM' },\n { value: 10, text: '10 AM' },\n { value: 11, text: '11 AM' },\n { value: 12, text: '12 PM' },\n { value: 13, text: '1 PM' },\n { value: 14, text: '2 PM' },\n { value: 15, text: '3 PM' },\n { value: 16, text: '4 PM' },\n { value: 17, text: '5 PM' },\n { value: 18, text: '6 PM' },\n { value: 19, text: '7 PM' },\n { value: 20, text: '8 PM' },\n { value: 21, text: '9 PM' },\n { value: 22, text: '10 PM' },\n { value: 23, text: '11 PM' }\n ]\n }\n ]\n },\n {\n type: \"text\",\n label: \"Email Template (Prefix)\",\n name: \"metadata.email_template\",\n columns: 12\n }\n ]\n },\n};\n\nGroup.EDIT_FORM = GroupForms.edit;\nGroup.ADD_FORM = GroupForms.create;\nGroup.CREATE_FORM = GroupForms.create; // Alias for compatibility\nGroup.GroupKindOptions = GroupKindOptions;\nGroup.GroupKinds = GroupKinds;\nexport { Group, GroupList, GroupForms };\n","import Collection from '@core/Collection.js';\nimport Model from '@core/Model.js';\n\nimport { GroupList } from './Group.js';\n\nclass User extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/user'\n });\n }\n\n hasPermission(permission) {\n if (this.get(\"is_superuser\")) return true;\n if (Array.isArray(permission)) {\n return permission.some(p => this.hasPermission(p));\n }\n\n // Check if permission has \"sys.\" prefix\n const isSysPermission = permission.startsWith('sys.');\n const permissionToCheck = isSysPermission ? permission.substring(4) : permission;\n\n if (this._hasPermission(permissionToCheck)) {\n return true;\n }\n\n // Only check member permissions if it's not a system permission\n if (!isSysPermission && this.member && this.member.hasPermission(permission)) {\n return true;\n }\n\n return false;\n }\n\n _hasPermission(permission) {\n const permissions = this.get(\"permissions\");\n if (!permissions) {\n return false;\n }\n if (permissions[permission] == true) {\n return true;\n }\n // Check if user has the category permission that covers this granular perm\n const category = User.GRANULAR_TO_CATEGORY[permission];\n if (category && permissions[category] == true) {\n return true;\n }\n return false;\n }\n\n hasPerm(p) {\n return this.hasPermission(p);\n }\n}\n\nclass UserList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: User,\n endpoint: '/api/user',\n ...options\n });\n }\n}\n\n// ── Category Permissions (broad domain-level access) ──────────────\nUser.CATEGORY_PERMISSIONS = [\n { name: \"view_admin\", label: \"Admin Panel\", tooltip: \"Access the admin panel, Mojo, and system tools\" },\n { name: \"security\", label: \"Security\", tooltip: \"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs\" },\n { name: \"users\", label: \"Users\", tooltip: \"User records, passkeys, TOTP, API keys, OAuth, devices, locations\" },\n { name: \"groups\", label: \"Groups\", tooltip: \"Groups, members, group API keys, settings\" },\n { name: \"comms\", label: \"Communications\", tooltip: \"Email, phone, SMS, push notifications, chat, notifications\" },\n { name: \"jobs\", label: \"Jobs\", tooltip: \"Jobs, job events, job logs, runners, queue control, system stats\" },\n { name: \"metrics\", label: \"Metrics\", tooltip: \"Metrics recording, fetching, categories, values, permissions\" },\n { name: \"files\", label: \"Files\", tooltip: \"File managers, files, renditions, vault files, vault data, S3 buckets\" },\n { name: \"assistant\", label: \"Mojo\", tooltip: \"Access to Mojo\" },\n { name: \"comms\", label: \"Communication\", tooltip: \"Ability to notify users\" },\n];\n\n// ── Granular Permissions (fine-grained view/manage pairs) ─────────\nUser.GRANULAR_PERMISSION_TABS = [\n {\n label: 'Account',\n permissions: [\n { name: \"view_users\", label: \"View Users\" },\n { name: \"manage_users\", label: \"Manage Users\" },\n { name: \"view_groups\", label: \"View Groups\" },\n { name: \"manage_groups\", label: \"Manage Groups\" },\n { name: \"manage_group\", label: \"Manage Own Group\" },\n { name: \"view_members\", label: \"View Members\" },\n { name: \"manage_settings\", label: \"Manage Settings\" },\n ]\n },\n {\n label: 'Communication',\n permissions: [\n { name: \"manage_chat\", label: \"Manage Chat\" },\n { name: \"manage_aws\", label: \"Manage Email (AWS)\" },\n { name: \"view_notifications\", label: \"View Notifications\" },\n { name: \"manage_notifications\", label: \"Manage Notifications\" },\n { name: \"send_notifications\", label: \"Send Notifications\" },\n { name: \"view_devices\", label: \"View Push Devices\" },\n { name: \"manage_devices\", label: \"Manage Push Devices\" },\n { name: \"manage_push_config\", label: \"Push Config\" },\n { name: \"view_phone_numbers\", label: \"View Phone Numbers\" },\n { name: \"manage_phone_numbers\", label: \"Manage Phone Numbers\" },\n { name: \"manage_phone_config\", label: \"Phone Config\" },\n { name: \"view_sms\", label: \"View SMS\" },\n { name: \"manage_sms\", label: \"Manage SMS\" },\n { name: \"send_sms\", label: \"Send SMS\" },\n ]\n },\n {\n label: 'Platform',\n permissions: [\n { name: \"view_security\", label: \"View Security\" },\n { name: \"manage_security\", label: \"Manage Security\" },\n { name: \"admin\", label: \"Log Admin\" },\n { name: \"view_logs\", label: \"View Logs\" },\n { name: \"manage_logs\", label: \"Manage Logs\" },\n { name: \"view_jobs\", label: \"View Jobs\" },\n { name: \"manage_jobs\", label: \"Manage Jobs\" },\n { name: \"view_metrics\", label: \"View Metrics\" },\n { name: \"manage_metrics\", label: \"Manage Metrics\" },\n { name: \"write_metrics\", label: \"Write Metrics\" },\n { name: \"view_fileman\", label: \"View File Managers\" },\n { name: \"manage_files\", label: \"Manage Files\" },\n { name: \"view_vault\", label: \"View Vault\" },\n { name: \"manage_vault\", label: \"Manage Vault\" },\n { name: \"manage_docit\", label: \"Manage Docs\" },\n { name: \"manage_shortlinks\", label: \"Manage Shortlinks\" },\n ]\n },\n];\n\n// ── Category → Granular mapping ───────────────────────────────────\n// Maps each category permission to the granular permissions it covers.\n// If a user has a category perm, all its granular perms are implicitly granted.\nUser.CATEGORY_GRANULAR_MAP = {\n security: [\"view_security\", \"manage_security\"],\n users: [\"view_users\", \"manage_users\", \"view_members\"],\n groups: [\"view_groups\", \"manage_groups\", \"manage_group\"],\n comms: [\"manage_chat\", \"manage_aws\", \"view_notifications\", \"manage_notifications\", \"send_notifications\",\n \"view_devices\", \"manage_devices\", \"manage_push_config\",\n \"view_phone_numbers\", \"manage_phone_numbers\", \"manage_phone_config\",\n \"view_sms\", \"manage_sms\", \"send_sms\"],\n jobs: [\"view_jobs\", \"manage_jobs\"],\n metrics: [\"view_metrics\", \"manage_metrics\", \"write_metrics\"],\n files: [\"view_fileman\", \"manage_files\", \"view_vault\", \"manage_vault\"]\n};\n\n// ── App-level extension points (empty by default) ─────────────────\n// Mutate (push, splice, key-set) these source structures, then call\n// User.rebuildPermissions() to refresh the cached field arrays the UI\n// reads from. Apps may also extend User.GRANULAR_PERMISSION_TABS and\n// User.CATEGORY_GRANULAR_MAP and have rebuildPermissions() pick them up.\nUser.APP_CATEGORY_PERMISSIONS = [];\nUser.APP_GRANULAR_PERMISSIONS = [];\n\n// ── Field builder ─────────────────────────────────────────────────\n// Public so apps building custom permission forms can reuse the exact\n// shape (avoids drift if the framework's switch field shape evolves).\nUser._permSwitch = function(p) {\n return {\n name: `permissions.${p.name}`,\n type: 'switch',\n label: p.label,\n columns: 6,\n ...(p.tooltip ? { tooltip: p.tooltip } : {})\n };\n};\n\n// ── Live caches — populated by rebuildPermissions() ───────────────\n// Initialized here so consumers (e.g. UserForms.permissions.fields)\n// can hold a reference; rebuildPermissions() mutates these arrays in\n// place to keep cached references current across re-registrations.\nUser.PERMISSIONS = [];\nUser.PERMISSION_FIELDS = [];\nUser.CATEGORY_PERMISSION_FIELDS = [];\nUser.GRANULAR_PERMISSION_FIELDS = [];\nUser.GRANULAR_TO_CATEGORY = {};\n\n// Recompute every cached permission structure from the live source\n// arrays (CATEGORY_PERMISSIONS, GRANULAR_PERMISSION_TABS, the APP_*\n// extension points, CATEGORY_GRANULAR_MAP). Idempotent — safe to call\n// multiple times. Mutates caches in place so existing references stay\n// live; UI code that read User.PERMISSION_FIELDS once still sees the\n// updated list after a rebuild.\nUser.rebuildPermissions = function() {\n const _ps = User._permSwitch;\n\n // Flat list of every registered permission.\n User.PERMISSIONS.length = 0;\n User.PERMISSIONS.push(\n ...User.CATEGORY_PERMISSIONS,\n ...User.GRANULAR_PERMISSION_TABS.flatMap(tab => tab.permissions),\n ...User.APP_CATEGORY_PERMISSIONS,\n ...User.APP_GRANULAR_PERMISSIONS\n );\n\n // Flat field list (flat form, no tabs).\n User.PERMISSION_FIELDS.length = 0;\n User.PERMISSION_FIELDS.push(...User.PERMISSIONS.map(_ps));\n\n // \"Permissions\" sidenav section — tabset with System (+ App when non-empty).\n const categoryTabs = [\n { label: 'System', fields: User.CATEGORY_PERMISSIONS.map(_ps) }\n ];\n if (User.APP_CATEGORY_PERMISSIONS.length > 0) {\n categoryTabs.push({ label: 'App', fields: User.APP_CATEGORY_PERMISSIONS.map(_ps) });\n }\n User.CATEGORY_PERMISSION_FIELDS.length = 0;\n User.CATEGORY_PERMISSION_FIELDS.push({ type: 'tabset', tabs: categoryTabs });\n\n // \"Adv Permissions\" sidenav section — one tab per registered tab (+ App when non-empty).\n const granularTabs = User.GRANULAR_PERMISSION_TABS.map(tab => ({\n label: tab.label,\n fields: tab.permissions.map(_ps)\n }));\n if (User.APP_GRANULAR_PERMISSIONS.length > 0) {\n granularTabs.push({ label: 'App', fields: User.APP_GRANULAR_PERMISSIONS.map(_ps) });\n }\n User.GRANULAR_PERMISSION_FIELDS.length = 0;\n User.GRANULAR_PERMISSION_FIELDS.push({ type: 'tabset', tabs: granularTabs });\n\n // Reverse lookup: granular perm name → category name.\n for (const k of Object.keys(User.GRANULAR_TO_CATEGORY)) {\n delete User.GRANULAR_TO_CATEGORY[k];\n }\n for (const [category, perms] of Object.entries(User.CATEGORY_GRANULAR_MAP)) {\n for (const perm of perms) {\n User.GRANULAR_TO_CATEGORY[perm] = category;\n }\n }\n};\n\n// Register app-level category → granular mappings so a held category\n// permission implicitly satisfies a gate listing one of its granulars.\n// Pass an object of the same shape as CATEGORY_GRANULAR_MAP, e.g.:\n// User.registerCategoryMap({ app_cat: ['view_app_thing', 'manage_app_thing'] });\n// Merges with any existing entries for the same category and triggers\n// rebuildPermissions() so caches stay coherent.\nUser.registerCategoryMap = function(map) {\n if (!map) return;\n let touched = false;\n for (const [category, perms] of Object.entries(map)) {\n if (!Array.isArray(perms)) continue;\n const existing = User.CATEGORY_GRANULAR_MAP[category] || [];\n User.CATEGORY_GRANULAR_MAP[category] = Array.from(new Set([...existing, ...perms]));\n touched = true;\n }\n if (touched) User.rebuildPermissions();\n};\n\n// One-shot atomic registration of app permissions. Bundles every\n// extension-point mutation into a single call followed by one\n// rebuildPermissions() at the end, so apps don't have to know which\n// arrays to push and which map to merge.\n//\n// User.registerPermissions({\n// categories: [{ name: 'app_cat', label: 'App Category' }],\n// granularPermissions: [{ name: 'app_perm', label: 'App Perm' }],\n// granularTabs: [{\n// label: 'Custom',\n// permissions: [{ name: 'view_app_thing', label: 'View App Thing' }]\n// }],\n// categoryGranularMap: { app_cat: ['view_app_thing'] }\n// });\n//\n// All four keys are optional. Arrays are appended; the map is merged\n// (existing category entries are preserved + deduped).\nUser.registerPermissions = function(spec) {\n if (!spec) return;\n if (Array.isArray(spec.categories)) {\n User.APP_CATEGORY_PERMISSIONS.push(...spec.categories);\n }\n if (Array.isArray(spec.granularPermissions)) {\n User.APP_GRANULAR_PERMISSIONS.push(...spec.granularPermissions);\n }\n if (Array.isArray(spec.granularTabs)) {\n User.GRANULAR_PERMISSION_TABS.push(...spec.granularTabs);\n }\n if (spec.categoryGranularMap) {\n for (const [category, perms] of Object.entries(spec.categoryGranularMap)) {\n if (!Array.isArray(perms)) continue;\n const existing = User.CATEGORY_GRANULAR_MAP[category] || [];\n User.CATEGORY_GRANULAR_MAP[category] = Array.from(new Set([...existing, ...perms]));\n }\n }\n User.rebuildPermissions();\n};\n\n// Initial population — mirrors the old IIFE-built state exactly.\nUser.rebuildPermissions();\n\nconst UserForms = {\n create: {\n title: 'Create User',\n fields: [\n { name: 'email', type: 'text', label: 'Email', required: true },\n { name: 'phone_number', type: 'text', label: 'Phone number', columns: 12 },\n { name: 'display_name', type: 'text', label: 'Display Name' }\n ]\n },\n edit: {\n title: 'Edit User',\n fields: [\n { name: 'email', type: 'email', label: 'Email', columns: 12 },\n { name: 'display_name', type: 'text', label: 'Display Name', columns: 12},\n { name: 'phone_number', type: 'text', label: 'Phone number', columns: 12 },\n { type: 'collection', name: 'org', label: 'Organization', Collection: GroupList, labelField: 'name', valueField: 'id', columns: 12 },\n ]\n },\n permissions: {\n title: 'Edit Permissions',\n fields: User.PERMISSION_FIELDS\n }\n};\n\n\n// DataView configuration for User model\nconst UserDataView = {\n // Basic user profile view\n profile: {\n title: 'User Profile',\n columns: 2,\n fields: [\n {\n name: 'id',\n label: 'User ID',\n type: 'number',\n columns: 4\n },\n {\n name: 'last_login',\n label: 'Last Login',\n type: 'datetime',\n format: 'relative',\n columns: 4\n },\n {\n name: 'last_activity',\n label: 'Last Activity',\n type: 'datetime',\n format: 'relative',\n columns: 4\n },\n {\n name: 'username',\n label: 'Username',\n type: 'text',\n format: 'lowercase',\n columns: 4\n },\n {\n name: 'display_name',\n label: 'Display Name',\n type: 'text',\n columns: 4\n },\n\n {\n name: 'email',\n label: 'Email',\n type: 'email',\n columns: 12\n },\n\n {\n name: 'org.name',\n label: 'Organization',\n type: 'text',\n columns: 6\n },\n {\n name: 'phone_number',\n label: 'Phone Number',\n type: 'text',\n columns: 6\n }\n ]\n },\n\n // Activity tracking view\n activity: {\n title: 'User Activity',\n columns: 2,\n fields: [\n {\n name: 'last_login',\n label: 'Last Login',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n },\n {\n name: 'last_activity',\n label: 'Last Activity',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n }\n ]\n },\n\n // Comprehensive view with all data\n detailed: {\n title: 'Detailed User Information',\n columns: 2,\n showEmptyValues: true,\n emptyValueText: 'Not set',\n fields: [\n // Basic Info Section\n {\n name: 'id',\n label: 'User ID',\n type: 'number',\n colSize: 3\n },\n {\n name: 'display_name',\n label: 'Display Name',\n type: 'text',\n format: 'capitalize|default(\"Unnamed User\")',\n colSize: 9\n },\n {\n name: 'username',\n label: 'Username',\n type: 'text',\n format: 'lowercase',\n colSize: 6\n },\n {\n name: 'email',\n label: 'Email Address',\n type: 'email',\n colSize: 6\n },\n {\n name: 'phone_number',\n label: 'Phone Number',\n type: 'phone',\n format: 'phone|default(\"Not provided\")',\n colSize: 6\n },\n {\n name: 'is_active',\n label: 'Account Status',\n type: 'boolean',\n colSize: 6\n },\n\n // Activity Info\n {\n name: 'last_login',\n label: 'Last Login',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n },\n {\n name: 'last_activity',\n label: 'Last Activity',\n type: 'datetime',\n format: 'relative',\n colSize: 6\n },\n\n // Avatar Info\n {\n name: 'avatar.url',\n label: 'Avatar',\n type: 'url',\n colSize: 12\n },\n\n // Complex Data (will use full width automatically)\n {\n name: 'permissions',\n label: 'User Permissions',\n type: 'dataview',\n dataViewColumns: 2,\n showEmptyValues: false\n },\n {\n name: 'metadata',\n label: 'User Metadata',\n type: 'dataview',\n dataViewColumns: 1\n },\n {\n name: 'avatar',\n label: 'Avatar Details',\n type: 'dataview',\n dataViewColumns: 1\n }\n ]\n },\n\n // Permissions-focused view\n permissions: {\n title: 'User Permissions',\n columns: 1,\n fields: [\n {\n name: 'display_name',\n label: 'User',\n type: 'text',\n format: 'capitalize',\n columns: 12\n },\n {\n name: 'permissions',\n label: 'Assigned Permissions',\n type: 'dataview',\n dataViewColumns: 3,\n showEmptyValues: false,\n colSize: 12\n }\n ]\n },\n\n // Compact summary view\n summary: {\n title: 'User Summary',\n columns: 3,\n fields: [\n {\n name: 'display_name',\n label: 'Name',\n type: 'text',\n format: 'capitalize|truncate(30)'\n },\n {\n name: 'email',\n label: 'Email',\n type: 'email'\n },\n {\n name: 'is_active',\n label: 'Status',\n type: 'boolean'\n },\n {\n name: 'last_activity',\n label: 'Last Seen',\n type: 'datetime',\n format: 'relative',\n colSize: 12\n }\n ]\n }\n};\n\nUser.DATA_VIEW = UserDataView.detailed;\nUser.EDIT_FORM = UserForms.edit;\nUser.ADD_FORM = UserForms.create;\n\n/* =========================\n * UserDevice\n * ========================= */\nclass UserDevice extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/user/device',\n });\n }\n\n static async getByDuid(duid) {\n const model = new UserDevice();\n const resp = await model.rest.GET('/api/user/device/lookup', { duid: duid });\n if (resp.success && resp.data && resp.data.data) {\n // A direct lookup should return a single object\n return new UserDevice(resp.data.data);\n }\n return null;\n }\n}\n\nclass UserDeviceList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: UserDevice,\n endpoint: '/api/user/device',\n ...options,\n });\n }\n}\n\n/* =========================\n * UserDeviceLocation\n * ========================= */\nclass UserDeviceLocation extends Model {\n constructor(data = {}) {\n super(data, {\n endpoint: '/api/user/device/location',\n });\n }\n}\n\nclass UserDeviceLocationList extends Collection {\n constructor(options = {}) {\n super({\n ModelClass: UserDeviceLocation,\n endpoint: '/api/user/device/location',\n ...options,\n });\n }\n}\n\nexport { User, UserList, UserForms, UserDataView, UserDevice, UserDeviceList, UserDeviceLocation, UserDeviceLocationList };\n"],"names":["Group","Model","constructor","data","super","endpoint","GroupList","Collection","options","ModelClass","size","GroupKinds","org","division","department","team","merchant","partner","client","iso","sales","reseller","location","region","route","project","inventory","test","misc","qa","GroupKindOptions","Object","entries","map","key","label","value","GroupForms","create","title","fields","name","type","required","placeholder","labelField","valueField","maxItems","emptyFetch","debounceMs","edit","cols","detailed","text","level","class","columns","xs","md","imageSize","width","height","help","EDIT_FORM","ADD_FORM","CREATE_FORM","User","hasPermission","permission","this","get","Array","isArray","some","p","isSysPermission","startsWith","permissionToCheck","substring","_hasPermission","member","permissions","category","GRANULAR_TO_CATEGORY","hasPerm","UserList","CATEGORY_PERMISSIONS","tooltip","GRANULAR_PERMISSION_TABS","CATEGORY_GRANULAR_MAP","security","users","groups","comms","jobs","metrics","files","APP_CATEGORY_PERMISSIONS","APP_GRANULAR_PERMISSIONS","_permSwitch","PERMISSIONS","PERMISSION_FIELDS","CATEGORY_PERMISSION_FIELDS","GRANULAR_PERMISSION_FIELDS","rebuildPermissions","_ps","length","push","flatMap","tab","categoryTabs","tabs","granularTabs","k","keys","perms","perm","registerCategoryMap","touched","existing","from","Set","registerPermissions","spec","categories","granularPermissions","categoryGranularMap","UserForms","UserDataView","profile","format","activity","colSize","showEmptyValues","emptyValueText","dataViewColumns","summary","DATA_VIEW","UserDevice","getByDuid","duid","model","resp","rest","GET","success","UserDeviceList","UserDeviceLocation","UserDeviceLocationList"],"mappings":"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"}
|