@elevasis/ui 2.35.0 → 2.37.0
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/api/index.js +4 -3
- package/dist/app/index.css +0 -384
- package/dist/app/index.d.ts +45 -18
- package/dist/app/index.js +21 -21
- package/dist/auth/index.d.ts +91 -28
- package/dist/auth/index.js +5 -1
- package/dist/charts/index.js +9 -3
- package/dist/chunk-5CTJ7TW2.js +111 -0
- package/dist/chunk-5EYJ2GIN.js +122 -0
- package/dist/{chunk-VDOOGGBA.js → chunk-6NREL3KL.js} +2 -2
- package/dist/chunk-6ROXVZ3L.js +9 -0
- package/dist/{chunk-YYX7OPZQ.js → chunk-73EWE2EW.js} +1 -1
- package/dist/{chunk-SIQ3P4OR.js → chunk-7GQFIWP4.js} +8 -756
- package/dist/chunk-A7IG36LB.js +215 -0
- package/dist/chunk-CLDCYJQT.js +1 -0
- package/dist/{chunk-AKW7KISS.js → chunk-CWYQRM5T.js} +2 -38
- package/dist/{chunk-LUYVRATI.js → chunk-DA6I5VEY.js} +5 -213
- package/dist/chunk-I53EX4VU.js +734 -0
- package/dist/chunk-IIMU5YAJ.js +53 -0
- package/dist/{chunk-VKIZUUPM.js → chunk-JPVZRZ3X.js} +31 -14
- package/dist/chunk-JXVNHVK7.js +79 -0
- package/dist/chunk-JZ2WID2G.js +337 -0
- package/dist/chunk-LCJQ6OWC.js +348 -0
- package/dist/chunk-LNC6PZAE.js +85 -0
- package/dist/{chunk-4U3XAWCN.js → chunk-NWMPBG4U.js} +134 -495
- package/dist/chunk-NYNOMAAS.js +422 -0
- package/dist/chunk-S3KBYQTI.js +39 -0
- package/dist/chunk-S3XR4II4.js +30 -0
- package/dist/chunk-SHZT7ULK.js +425 -0
- package/dist/{chunk-26HFM4MH.js → chunk-T3NI7DOA.js} +2005 -4106
- package/dist/{chunk-GX6XBRRF.js → chunk-TYRUKGGD.js} +2 -1
- package/dist/{chunk-R3VCBZDC.js → chunk-X4WBGKJQ.js} +3 -50
- package/dist/{chunk-GEFWMU26.js → chunk-X66MVMZT.js} +1 -9
- package/dist/{chunk-57OZ3AEG.js → chunk-Y3JQBSKQ.js} +1 -1
- package/dist/components/index.d.ts +36 -46
- package/dist/components/index.js +33 -19
- package/dist/components/navigation/index.js +3 -31
- package/dist/execution/index.d.ts +2 -2
- package/dist/features/auth/index.d.ts +55 -99
- package/dist/features/auth/index.js +36 -99
- package/dist/features/clients/index.js +33 -19
- package/dist/features/crm/index.d.ts +23 -0
- package/dist/features/crm/index.js +33 -19
- package/dist/features/dashboard/index.d.ts +3 -3
- package/dist/features/dashboard/index.js +33 -19
- package/dist/features/delivery/index.d.ts +23 -0
- package/dist/features/delivery/index.js +33 -19
- package/dist/features/knowledge/index.js +6 -30
- package/dist/features/lead-gen/index.d.ts +1373 -48
- package/dist/features/lead-gen/index.js +33 -19
- package/dist/features/monitoring/index.js +33 -19
- package/dist/features/monitoring/requests/index.js +33 -19
- package/dist/features/notes/index.d.ts +72 -0
- package/dist/features/notes/index.js +621 -0
- package/dist/features/operations/index.d.ts +30 -30
- package/dist/features/operations/index.js +33 -19
- package/dist/features/right-panel-host/index.d.ts +214 -0
- package/dist/features/right-panel-host/index.js +640 -0
- package/dist/features/seo/index.js +3 -2
- package/dist/features/settings/index.d.ts +26 -35
- package/dist/features/settings/index.js +33 -19
- package/dist/hooks/access/index.d.ts +90 -0
- package/dist/hooks/access/index.js +10 -0
- package/dist/hooks/delivery/index.d.ts +23 -0
- package/dist/hooks/delivery/index.js +33 -19
- package/dist/hooks/index.d.ts +1816 -1855
- package/dist/hooks/index.js +33 -19
- package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +13 -13
- package/dist/hooks/published.d.ts +1816 -1855
- package/dist/hooks/published.js +33 -19
- package/dist/hooks/user-notes/index.d.ts +57 -0
- package/dist/hooks/user-notes/index.js +3 -0
- package/dist/index.d.ts +290 -309
- package/dist/index.js +34 -20
- package/dist/initialization/index.d.ts +23 -19
- package/dist/knowledge/index.d.ts +21 -21
- package/dist/knowledge/index.js +12 -9
- package/dist/{knowledge-search-index-ORIJCEZX.js → knowledge-search-index-NBCTFIOH.js} +2 -2
- package/dist/layout/index.js +5 -3
- package/dist/organization/index.d.ts +0 -19
- package/dist/organization/index.js +33 -19
- package/dist/profile/index.d.ts +23 -0
- package/dist/provider/index.css +0 -384
- package/dist/provider/index.d.ts +45 -18
- package/dist/provider/index.js +15 -21
- package/dist/provider/published.css +0 -523
- package/dist/provider/published.d.ts +45 -18
- package/dist/provider/published.js +11 -21
- package/dist/sse/index.js +26 -5
- package/dist/supabase/index.d.ts +46 -0
- package/dist/test-utils/index.d.ts +2 -21
- package/dist/test-utils/index.js +5 -18
- package/dist/theme/index.js +2 -1
- package/dist/types/index.d.ts +86 -72
- package/dist/utils/index.d.ts +3 -3
- package/dist/utils/index.js +2 -1
- package/package.json +21 -5
- package/src/auth/README.md +6 -6
- package/dist/components/navigation/index.css +0 -649
- package/dist/features/knowledge/index.css +0 -649
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { useOptionalElevasisSystems } from './chunk-NYNOMAAS.js';
|
|
2
|
+
import { InitializationContext } from './chunk-533DUEQY.js';
|
|
3
|
+
import { DEFAULT_ORGANIZATION_MODEL, listAllSystems, getSystem } from './chunk-NWMPBG4U.js';
|
|
4
|
+
import { OrganizationContext } from './chunk-DD3CCMCZ.js';
|
|
5
|
+
import { STALE_TIME_DEFAULT } from './chunk-6ROXVZ3L.js';
|
|
6
|
+
import { ElevasisServiceContext } from './chunk-KJ3QUBNU.js';
|
|
7
|
+
import { useContext, useMemo } from 'react';
|
|
8
|
+
import { useQuery } from '@tanstack/react-query';
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
|
|
11
|
+
// ../core/src/auth/multi-tenancy/permissions.ts
|
|
12
|
+
var PERMISSIONS = {
|
|
13
|
+
ORG_READ: "org.read",
|
|
14
|
+
ORG_MANAGE: "org.manage",
|
|
15
|
+
ORG_DELETE: "org.delete",
|
|
16
|
+
MEMBERS_MANAGE: "members.manage",
|
|
17
|
+
ROLES_MANAGE: "roles.manage",
|
|
18
|
+
SECRETS_MANAGE: "secrets.manage",
|
|
19
|
+
OPERATIONS_READ: "operations.read",
|
|
20
|
+
OPERATIONS_MANAGE: "operations.manage",
|
|
21
|
+
ACQUISITION_MANAGE: "acquisition.manage",
|
|
22
|
+
PROJECTS_MANAGE: "projects.manage",
|
|
23
|
+
CLIENTS_MANAGE: "clients.manage"
|
|
24
|
+
};
|
|
25
|
+
var PERMISSION_CATALOG = [
|
|
26
|
+
{
|
|
27
|
+
key: "org.read",
|
|
28
|
+
description: "Read organization profile and listings",
|
|
29
|
+
isOrgGrantable: true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
key: "org.manage",
|
|
33
|
+
description: "Update organization settings",
|
|
34
|
+
isOrgGrantable: false
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
key: "org.delete",
|
|
38
|
+
description: "Delete the organization (owner-only)",
|
|
39
|
+
isOrgGrantable: false
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
key: "members.manage",
|
|
43
|
+
description: "Invite, remove, and reassign roles for members",
|
|
44
|
+
isOrgGrantable: false
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: "roles.manage",
|
|
48
|
+
description: "Grant or revoke privileged system roles (owner, admin) within the organization",
|
|
49
|
+
isOrgGrantable: false
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
key: "secrets.manage",
|
|
53
|
+
description: "Create, update, and delete API keys and credentials",
|
|
54
|
+
isOrgGrantable: false
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: "operations.read",
|
|
58
|
+
description: "View executions, sessions, schedules, and command queue",
|
|
59
|
+
isOrgGrantable: true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
key: "operations.manage",
|
|
63
|
+
description: "Run and modify executions, sessions, schedules, queue",
|
|
64
|
+
isOrgGrantable: true
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
key: "acquisition.manage",
|
|
68
|
+
description: "Create, update, and delete acquisition records (acq_companies, acq_contacts, acq_deals, acq_lists*, acq_content*, acquisition storage files)",
|
|
69
|
+
isOrgGrantable: false
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: "projects.manage",
|
|
73
|
+
description: "Create, update, and delete project records (prj_projects, prj_milestones, prj_tasks, prj_notes)",
|
|
74
|
+
isOrgGrantable: false
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
key: "clients.manage",
|
|
78
|
+
description: "Create, update, and delete client hub records (clients, clt_* satellites)",
|
|
79
|
+
isOrgGrantable: false
|
|
80
|
+
}
|
|
81
|
+
];
|
|
82
|
+
new Set(PERMISSION_CATALOG.map((p) => p.key));
|
|
83
|
+
var DEFAULT_ACCESS_ACTION = "view";
|
|
84
|
+
var PLATFORM_ADMIN_ACCESS_KEY = "platform.admin";
|
|
85
|
+
var PLATFORM_ADMIN_ACCESS_KEY_SHORTHAND = "platformAdmin";
|
|
86
|
+
var AccessActionSchema = z.enum(["view", "manage"]);
|
|
87
|
+
var AccessKeyObjectSchema = z.object({
|
|
88
|
+
systemPath: z.string().trim().min(1),
|
|
89
|
+
action: AccessActionSchema.default(DEFAULT_ACCESS_ACTION)
|
|
90
|
+
}).strict();
|
|
91
|
+
var AccessKeyInputSchema = z.union([z.string().trim().min(1), AccessKeyObjectSchema]);
|
|
92
|
+
var NormalizedAccessKeySchema = AccessKeyObjectSchema;
|
|
93
|
+
var DIAGNOSTIC_VIEW_ACCESS_KEYS = [
|
|
94
|
+
"diagnostic.operations.overview",
|
|
95
|
+
"diagnostic.operations.recent-executions",
|
|
96
|
+
"diagnostic.monitoring.execution-logs",
|
|
97
|
+
"diagnostic.monitoring.notifications"
|
|
98
|
+
];
|
|
99
|
+
var AccessKeys = {
|
|
100
|
+
platformAdmin: { systemPath: PLATFORM_ADMIN_ACCESS_KEY, action: DEFAULT_ACCESS_ACTION },
|
|
101
|
+
organizationManage: { systemPath: "permission.org", action: "manage" },
|
|
102
|
+
membersManage: { systemPath: "permission.members", action: "manage" },
|
|
103
|
+
rolesManage: { systemPath: "permission.roles", action: "manage" },
|
|
104
|
+
secretsManage: { systemPath: "permission.secrets", action: "manage" },
|
|
105
|
+
operationsRead: { systemPath: "permission.operations", action: DEFAULT_ACCESS_ACTION },
|
|
106
|
+
operationsManage: { systemPath: "permission.operations", action: "manage" },
|
|
107
|
+
acquisitionManage: { systemPath: "permission.acquisition", action: "manage" },
|
|
108
|
+
projectsManage: { systemPath: "permission.projects", action: "manage" },
|
|
109
|
+
clientsManage: { systemPath: "permission.clients", action: "manage" },
|
|
110
|
+
operationsOverview: { systemPath: "diagnostic.operations.overview", action: DEFAULT_ACCESS_ACTION },
|
|
111
|
+
operationsRecentExecutions: { systemPath: "diagnostic.operations.recent-executions", action: DEFAULT_ACCESS_ACTION },
|
|
112
|
+
monitoringExecutionLogs: { systemPath: "diagnostic.monitoring.execution-logs", action: DEFAULT_ACCESS_ACTION },
|
|
113
|
+
monitoringNotifications: { systemPath: "diagnostic.monitoring.notifications", action: DEFAULT_ACCESS_ACTION }
|
|
114
|
+
};
|
|
115
|
+
var PERMISSION_ACCESS_KEY_DEFINITIONS = [
|
|
116
|
+
{ key: AccessKeys.organizationManage, rolePermission: PERMISSIONS.ORG_MANAGE },
|
|
117
|
+
{ key: AccessKeys.membersManage, rolePermission: PERMISSIONS.MEMBERS_MANAGE },
|
|
118
|
+
{ key: AccessKeys.rolesManage, rolePermission: PERMISSIONS.ROLES_MANAGE },
|
|
119
|
+
{ key: AccessKeys.secretsManage, rolePermission: PERMISSIONS.SECRETS_MANAGE },
|
|
120
|
+
{ key: AccessKeys.operationsRead, rolePermission: PERMISSIONS.OPERATIONS_READ },
|
|
121
|
+
{ key: AccessKeys.operationsManage, rolePermission: PERMISSIONS.OPERATIONS_MANAGE },
|
|
122
|
+
{ key: AccessKeys.acquisitionManage, rolePermission: PERMISSIONS.ACQUISITION_MANAGE },
|
|
123
|
+
{ key: AccessKeys.projectsManage, rolePermission: PERMISSIONS.PROJECTS_MANAGE },
|
|
124
|
+
{ key: AccessKeys.clientsManage, rolePermission: PERMISSIONS.CLIENTS_MANAGE }
|
|
125
|
+
];
|
|
126
|
+
function normalizeAccessKey(input) {
|
|
127
|
+
const parsed = AccessKeyInputSchema.parse(input);
|
|
128
|
+
const normalized = typeof parsed === "string" ? {
|
|
129
|
+
systemPath: parsed === PLATFORM_ADMIN_ACCESS_KEY_SHORTHAND ? PLATFORM_ADMIN_ACCESS_KEY : parsed,
|
|
130
|
+
action: DEFAULT_ACCESS_ACTION
|
|
131
|
+
} : parsed;
|
|
132
|
+
return NormalizedAccessKeySchema.parse(normalized);
|
|
133
|
+
}
|
|
134
|
+
function rolePermissionForAccessKey(key) {
|
|
135
|
+
if (key.action === DEFAULT_ACCESS_ACTION) return void 0;
|
|
136
|
+
return `${key.systemPath}.${key.action}`;
|
|
137
|
+
}
|
|
138
|
+
function groupCatalogEntries(entries) {
|
|
139
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
140
|
+
for (const entry of entries) {
|
|
141
|
+
const existing = grouped.get(entry.key.systemPath) ?? [];
|
|
142
|
+
existing.push(entry);
|
|
143
|
+
grouped.set(entry.key.systemPath, existing);
|
|
144
|
+
}
|
|
145
|
+
return grouped;
|
|
146
|
+
}
|
|
147
|
+
function buildCatalogEntry(systemPath, action, source) {
|
|
148
|
+
const key = normalizeAccessKey({ systemPath, action });
|
|
149
|
+
return {
|
|
150
|
+
key,
|
|
151
|
+
source,
|
|
152
|
+
rolePermission: rolePermissionForAccessKey(key)
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function deriveAccessKeyCatalog(organizationModel, options = {}) {
|
|
156
|
+
const { diagnosticKeys = DIAGNOSTIC_VIEW_ACCESS_KEYS, includeManageActions = true } = options;
|
|
157
|
+
const entries = [
|
|
158
|
+
buildCatalogEntry(PLATFORM_ADMIN_ACCESS_KEY, DEFAULT_ACCESS_ACTION, "platform")
|
|
159
|
+
];
|
|
160
|
+
for (const { path } of listAllSystems(organizationModel)) {
|
|
161
|
+
entries.push(buildCatalogEntry(path, DEFAULT_ACCESS_ACTION, "om-system"));
|
|
162
|
+
if (includeManageActions) {
|
|
163
|
+
entries.push(buildCatalogEntry(path, "manage", "om-system"));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
for (const { key, rolePermission } of PERMISSION_ACCESS_KEY_DEFINITIONS) {
|
|
167
|
+
entries.push({
|
|
168
|
+
key,
|
|
169
|
+
source: "permission",
|
|
170
|
+
rolePermission
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
for (const systemPath of diagnosticKeys) {
|
|
174
|
+
entries.push(buildCatalogEntry(systemPath, DEFAULT_ACCESS_ACTION, "diagnostic"));
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
bySystemPath: groupCatalogEntries(entries),
|
|
178
|
+
entries
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function findAccessCatalogEntry(catalog, key) {
|
|
182
|
+
return catalog.bySystemPath.get(key.systemPath)?.find((entry) => entry.key.action === key.action);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ../core/src/auth/access-model.ts
|
|
186
|
+
var ALLOWED = { allowed: true, restrictedBy: null, reason: "allowed" };
|
|
187
|
+
var PLATFORM_ADMIN_BYPASS = {
|
|
188
|
+
allowed: true,
|
|
189
|
+
restrictedBy: null,
|
|
190
|
+
reason: "platform-admin-bypass"
|
|
191
|
+
};
|
|
192
|
+
function deny(restrictedBy, reason) {
|
|
193
|
+
return { allowed: false, restrictedBy, reason };
|
|
194
|
+
}
|
|
195
|
+
function isPlatformAdmin(profile) {
|
|
196
|
+
return profile?.isPlatformAdmin === true || profile?.is_platform_admin === true;
|
|
197
|
+
}
|
|
198
|
+
function diagnosticAllowlistHas(allowlist, systemPath) {
|
|
199
|
+
if (allowlist === void 0) return false;
|
|
200
|
+
return "has" in allowlist ? allowlist.has(systemPath) : allowlist.includes(systemPath);
|
|
201
|
+
}
|
|
202
|
+
function lifecycleAllowsAccess(lifecycle, ctx) {
|
|
203
|
+
if (lifecycle === "active") return true;
|
|
204
|
+
if (lifecycle === "beta") return ctx.betaAccessEnabled === true || ctx.isDevelopment === true;
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
function getPermissionSource(ctx) {
|
|
208
|
+
return ctx.permissions ?? ctx.membership?.effectivePermissions;
|
|
209
|
+
}
|
|
210
|
+
function hasRequiredPermission(key, rolePermission, ctx) {
|
|
211
|
+
const permissionSource = getPermissionSource(ctx);
|
|
212
|
+
if (permissionSource === void 0 || permissionSource === null) return true;
|
|
213
|
+
const requiredPermission = rolePermission ?? `${key.systemPath}.${key.action}`;
|
|
214
|
+
return permissionSource.includes(requiredPermission);
|
|
215
|
+
}
|
|
216
|
+
function hasExplicitRequiredPermission(rolePermission, ctx) {
|
|
217
|
+
const permissionSource = getPermissionSource(ctx);
|
|
218
|
+
return rolePermission !== void 0 && permissionSource !== void 0 && permissionSource !== null ? permissionSource.includes(rolePermission) : false;
|
|
219
|
+
}
|
|
220
|
+
function checkAccess(input, ctx) {
|
|
221
|
+
if (isPlatformAdmin(ctx.profile)) return PLATFORM_ADMIN_BYPASS;
|
|
222
|
+
const parsed = (() => {
|
|
223
|
+
try {
|
|
224
|
+
return normalizeAccessKey(input);
|
|
225
|
+
} catch {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
})();
|
|
229
|
+
if (parsed === null) return deny("catalog", "invalid-access-key");
|
|
230
|
+
const catalog = ctx.accessCatalog ?? deriveAccessKeyCatalog(ctx.organizationModel);
|
|
231
|
+
const catalogEntry = findAccessCatalogEntry(catalog, parsed);
|
|
232
|
+
if (catalogEntry === void 0) return deny("catalog", "unknown-access-key");
|
|
233
|
+
const membership = ctx.membership;
|
|
234
|
+
if (membership === void 0 || membership === null) return deny("membership", "missing-membership");
|
|
235
|
+
if (membership.organizationId !== ctx.organizationId) return deny("membership", "organization-mismatch");
|
|
236
|
+
if (parsed.systemPath === PLATFORM_ADMIN_ACCESS_KEY) {
|
|
237
|
+
return deny("role-permission", "role-permission-denied");
|
|
238
|
+
}
|
|
239
|
+
if (catalogEntry.source === "diagnostic") {
|
|
240
|
+
if (!diagnosticAllowlistHas(ctx.diagnosticAllowlist, parsed.systemPath)) {
|
|
241
|
+
return deny("diagnostic-allowlist", "diagnostic-key-not-allowed");
|
|
242
|
+
}
|
|
243
|
+
if (parsed.action !== DEFAULT_ACCESS_ACTION && !hasRequiredPermission(parsed, catalogEntry.rolePermission, ctx)) {
|
|
244
|
+
return deny("role-permission", "role-permission-denied");
|
|
245
|
+
}
|
|
246
|
+
return ALLOWED;
|
|
247
|
+
}
|
|
248
|
+
if (catalogEntry.source === "permission") {
|
|
249
|
+
if (!hasExplicitRequiredPermission(catalogEntry.rolePermission, ctx)) {
|
|
250
|
+
return deny("role-permission", "role-permission-denied");
|
|
251
|
+
}
|
|
252
|
+
return ALLOWED;
|
|
253
|
+
}
|
|
254
|
+
const system = getSystem(ctx.organizationModel, parsed.systemPath);
|
|
255
|
+
if (system === void 0 || !lifecycleAllowsAccess(system.lifecycle, ctx)) {
|
|
256
|
+
return deny("system-lifecycle", "system-not-active");
|
|
257
|
+
}
|
|
258
|
+
if (parsed.action !== DEFAULT_ACCESS_ACTION && !hasRequiredPermission(parsed, catalogEntry.rolePermission, ctx)) {
|
|
259
|
+
return deny("role-permission", "role-permission-denied");
|
|
260
|
+
}
|
|
261
|
+
return ALLOWED;
|
|
262
|
+
}
|
|
263
|
+
function createAccessModel(organizationModel) {
|
|
264
|
+
const catalog = deriveAccessKeyCatalog(organizationModel);
|
|
265
|
+
return {
|
|
266
|
+
catalog,
|
|
267
|
+
checkAccess: (key, ctx) => checkAccess(key, { ...ctx, organizationModel, accessCatalog: catalog })
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/hooks/access/useAccess.ts
|
|
272
|
+
var MISSING_CONTEXT_ANSWER = {
|
|
273
|
+
allowed: false,
|
|
274
|
+
restrictedBy: "membership",
|
|
275
|
+
reason: "missing-membership"
|
|
276
|
+
};
|
|
277
|
+
function readStringArray(value) {
|
|
278
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
|
|
279
|
+
}
|
|
280
|
+
function membershipPermissions(membership) {
|
|
281
|
+
if (!membership || typeof membership !== "object") return void 0;
|
|
282
|
+
const record = membership;
|
|
283
|
+
return readStringArray(record.effectivePermissions) ?? readStringArray(record.effective_permissions);
|
|
284
|
+
}
|
|
285
|
+
function resolveOrganizationId(organization) {
|
|
286
|
+
const membership = organization?.currentMembership;
|
|
287
|
+
return organization?.currentSupabaseOrganizationId ?? membership?.organizationId ?? membership?.organization?.id ?? null;
|
|
288
|
+
}
|
|
289
|
+
function toAccessMembership(membership, organizationId, permissions) {
|
|
290
|
+
if (!membership || !organizationId) return null;
|
|
291
|
+
return {
|
|
292
|
+
id: membership.id,
|
|
293
|
+
organizationId: membership.organizationId ?? organizationId,
|
|
294
|
+
role: membership.role?.slug ?? null,
|
|
295
|
+
effectivePermissions: permissions
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
function useAccess(key) {
|
|
299
|
+
const initialization = useContext(InitializationContext);
|
|
300
|
+
const organization = useContext(OrganizationContext);
|
|
301
|
+
const services = useContext(ElevasisServiceContext);
|
|
302
|
+
const systems = useOptionalElevasisSystems();
|
|
303
|
+
const profile = initialization?.profile ?? null;
|
|
304
|
+
const isPlatformAdmin2 = profile?.is_platform_admin === true;
|
|
305
|
+
const organizationId = resolveOrganizationId(organization);
|
|
306
|
+
const membership = organization?.currentMembership ?? null;
|
|
307
|
+
const organizationModel = systems?.organizationModel ?? DEFAULT_ORGANIZATION_MODEL;
|
|
308
|
+
const permissionsFromMembership = useMemo(() => membershipPermissions(membership), [membership]);
|
|
309
|
+
const shouldFetchPermissions = Boolean(services?.isReady && organizationId && !isPlatformAdmin2);
|
|
310
|
+
const permissionsQuery = useQuery({
|
|
311
|
+
queryKey: ["access-permissions", organizationId],
|
|
312
|
+
queryFn: () => services.apiRequest(`/memberships/my-permissions/${organizationId}`),
|
|
313
|
+
enabled: shouldFetchPermissions,
|
|
314
|
+
staleTime: STALE_TIME_DEFAULT
|
|
315
|
+
});
|
|
316
|
+
const permissions = useMemo(
|
|
317
|
+
() => isPlatformAdmin2 ? Object.values(PERMISSIONS) : permissionsQuery.data?.permissions ?? permissionsFromMembership ?? [],
|
|
318
|
+
[isPlatformAdmin2, permissionsFromMembership, permissionsQuery.data?.permissions]
|
|
319
|
+
);
|
|
320
|
+
const accessMembership = useMemo(
|
|
321
|
+
() => toAccessMembership(membership, organizationId, permissions),
|
|
322
|
+
[membership, organizationId, permissions]
|
|
323
|
+
);
|
|
324
|
+
const accessModel = useMemo(() => createAccessModel(organizationModel), [organizationModel]);
|
|
325
|
+
const answer = useMemo(() => {
|
|
326
|
+
if (!organizationId && !isPlatformAdmin2) return MISSING_CONTEXT_ANSWER;
|
|
327
|
+
return accessModel.checkAccess(key, {
|
|
328
|
+
organizationId: organizationId ?? "",
|
|
329
|
+
organizationModel,
|
|
330
|
+
membership: accessMembership,
|
|
331
|
+
profile,
|
|
332
|
+
permissions,
|
|
333
|
+
diagnosticAllowlist: DIAGNOSTIC_VIEW_ACCESS_KEYS,
|
|
334
|
+
isDevelopment: import.meta.env?.DEV ?? false
|
|
335
|
+
});
|
|
336
|
+
}, [accessMembership, accessModel, isPlatformAdmin2, key, organizationId, organizationModel, permissions, profile]);
|
|
337
|
+
const providerReady = initialization?.organizationReady ?? Boolean(organizationId && accessMembership && systems?.organizationModel);
|
|
338
|
+
const permissionsReady = !shouldFetchPermissions || !permissionsQuery.isPending;
|
|
339
|
+
const isReady = isPlatformAdmin2 ? initialization?.userReady ?? true : providerReady && permissionsReady;
|
|
340
|
+
return {
|
|
341
|
+
...answer,
|
|
342
|
+
isReady,
|
|
343
|
+
isPlatformAdmin: isPlatformAdmin2,
|
|
344
|
+
permissions
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export { AccessKeys, useAccess };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useRouterContext } from './chunk-Q7DJKLEN.js';
|
|
2
|
+
import { useOptionalElevasisSystems } from './chunk-NYNOMAAS.js';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
|
|
5
|
+
var useBreadcrumbs = (options = {}) => {
|
|
6
|
+
const { currentPath } = useRouterContext();
|
|
7
|
+
const systemContext = useOptionalElevasisSystems();
|
|
8
|
+
const { labelsByPath = {} } = options;
|
|
9
|
+
return useMemo(() => {
|
|
10
|
+
const shellModel = systemContext?.shellModel;
|
|
11
|
+
const overriddenLabel = labelsByPath[currentPath];
|
|
12
|
+
if (overriddenLabel) {
|
|
13
|
+
return [{ label: overriddenLabel, isActive: true }];
|
|
14
|
+
}
|
|
15
|
+
if (shellModel) {
|
|
16
|
+
const matchedNode = shellModel.findByPath(currentPath);
|
|
17
|
+
if (matchedNode) {
|
|
18
|
+
return shellModel.ancestorsOf(matchedNode.id).map((node, index, items) => ({
|
|
19
|
+
label: labelsByPath[node.path ?? ""] ?? node.label,
|
|
20
|
+
path: index === items.length - 1 ? void 0 : node.path,
|
|
21
|
+
isActive: index === items.length - 1
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const segments = currentPath.split("/").filter(Boolean);
|
|
26
|
+
if (segments.length === 0) {
|
|
27
|
+
return [{ label: "Dashboard", isActive: true }];
|
|
28
|
+
}
|
|
29
|
+
const breadcrumbs = [{ label: "Dashboard", path: "/" }];
|
|
30
|
+
let currentSegmentPath = "";
|
|
31
|
+
for (let i = 0; i < segments.length; i++) {
|
|
32
|
+
currentSegmentPath += `/${segments[i]}`;
|
|
33
|
+
const isLast = i === segments.length - 1;
|
|
34
|
+
const label = labelsByPath[currentSegmentPath] ?? formatSegmentLabel(segments[i]);
|
|
35
|
+
breadcrumbs.push({
|
|
36
|
+
label,
|
|
37
|
+
path: isLast ? void 0 : currentSegmentPath,
|
|
38
|
+
isActive: isLast
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return breadcrumbs;
|
|
42
|
+
}, [currentPath, systemContext, labelsByPath]);
|
|
43
|
+
};
|
|
44
|
+
function formatSegmentLabel(segment) {
|
|
45
|
+
const decodedSegment = safeDecodeURIComponent(segment);
|
|
46
|
+
const routeLabel = formatRouteIdLabel(decodedSegment);
|
|
47
|
+
if (routeLabel) return routeLabel;
|
|
48
|
+
return titleCaseSegment(decodedSegment);
|
|
49
|
+
}
|
|
50
|
+
function safeDecodeURIComponent(value) {
|
|
51
|
+
try {
|
|
52
|
+
return decodeURIComponent(value);
|
|
53
|
+
} catch {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function formatRouteIdLabel(segment) {
|
|
58
|
+
if (segment.startsWith("group:")) {
|
|
59
|
+
const groupKey = segment.slice("group:".length);
|
|
60
|
+
return groupKey === "graph" ? "Ontology" : titleCaseSegment(groupKey);
|
|
61
|
+
}
|
|
62
|
+
if (segment.startsWith("domain:")) {
|
|
63
|
+
return titleCaseSegment(segment.slice("domain:".length));
|
|
64
|
+
}
|
|
65
|
+
if (segment.startsWith("item:")) {
|
|
66
|
+
const rest = segment.slice("item:".length);
|
|
67
|
+
const separatorIndex = rest.indexOf(":");
|
|
68
|
+
const itemId = separatorIndex === -1 ? rest : rest.slice(separatorIndex + 1);
|
|
69
|
+
return formatOntologyOrIdLabel(itemId);
|
|
70
|
+
}
|
|
71
|
+
if (segment.startsWith("ontology:")) {
|
|
72
|
+
return formatOntologyOrIdLabel(segment);
|
|
73
|
+
}
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
function formatOntologyOrIdLabel(value) {
|
|
77
|
+
const localId = value.includes("/") ? value.slice(value.lastIndexOf("/") + 1) : value;
|
|
78
|
+
const suffix = localId.includes(":") ? localId.slice(localId.lastIndexOf(":") + 1) : localId;
|
|
79
|
+
return titleCaseSegment(suffix);
|
|
80
|
+
}
|
|
81
|
+
function titleCaseSegment(segment) {
|
|
82
|
+
return segment.split("-").flatMap((part) => part.split("_")).flatMap((part) => part.split(".")).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { useBreadcrumbs };
|