@stndrds/schema 1.0.0-alpha.77 → 1.0.0-alpha.79
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/{chunk-JZO52C3F.js → chunk-7WT53FJ4.js} +14 -9
- package/dist/{chunk-6P3NPTYV.mjs → chunk-AGBBH7PL.mjs} +15 -10
- package/dist/{chunk-XF46EJU7.mjs → chunk-K5MARJCD.mjs} +201 -55
- package/dist/{chunk-7JHBQL6H.js → chunk-Y4FDI32G.js} +376 -230
- package/dist/default-roles-5K3GHJTS.js +23 -0
- package/dist/{default-roles-OAMHLOCS.mjs → default-roles-6D3HQ3DQ.mjs} +3 -3
- package/dist/index.d.mts +91 -23
- package/dist/index.d.ts +91 -23
- package/dist/index.js +38 -24
- package/dist/index.mjs +36 -22
- package/dist/{runtime-kH9dOaQt.d.mts → runtime-BU3qnMH0.d.mts} +134 -29
- package/dist/{runtime-DE2X2kPp.d.ts → runtime-CjZp8UsJ.d.ts} +134 -29
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +2 -3
- package/dist/runtime.mjs +1 -2
- package/dist/validation/validators.d.mts +1 -1
- package/dist/validation/validators.d.ts +1 -1
- package/dist/{validators-BxPuQ2GT.d.ts → validators-5RPbTlXa.d.ts} +2 -0
- package/dist/{validators-DUB0tEzp.d.mts → validators-DVfMzWfY.d.mts} +2 -0
- package/package.json +2 -2
- package/dist/default-roles-76HUWY6T.js +0 -23
|
@@ -2,16 +2,20 @@
|
|
|
2
2
|
var SYSTEM_RESOURCES = {
|
|
3
3
|
/** User profiles, invitations, roles and permissions management */
|
|
4
4
|
PEOPLE: "people",
|
|
5
|
-
/**
|
|
6
|
-
WORKSPACE: "workspace"
|
|
5
|
+
/** Tenant settings, audit logs, workflow execution, document generation */
|
|
6
|
+
WORKSPACE: "workspace",
|
|
7
|
+
/** Object definitions, attributes, views, workflow definitions */
|
|
8
|
+
ARCHITECT: "architect"
|
|
7
9
|
};
|
|
8
10
|
var ALL_SYSTEM_RESOURCES = [
|
|
9
11
|
SYSTEM_RESOURCES.PEOPLE,
|
|
10
|
-
SYSTEM_RESOURCES.WORKSPACE
|
|
12
|
+
SYSTEM_RESOURCES.WORKSPACE,
|
|
13
|
+
SYSTEM_RESOURCES.ARCHITECT
|
|
11
14
|
];
|
|
12
15
|
var SYSTEM_RESOURCE_LABELS = {
|
|
13
16
|
people: "People",
|
|
14
|
-
workspace: "Workspace"
|
|
17
|
+
workspace: "Workspace",
|
|
18
|
+
architect: "Architect"
|
|
15
19
|
};
|
|
16
20
|
var DEFAULT_ROLES = {
|
|
17
21
|
/** Full platform access - can manage everything */
|
|
@@ -34,16 +38,17 @@ var DEFAULT_ROLE_PERMISSIONS = {
|
|
|
34
38
|
object: [{ target: "*", actions: ALL_ACTIONS }]
|
|
35
39
|
},
|
|
36
40
|
member: {
|
|
37
|
-
system: [
|
|
41
|
+
system: [
|
|
42
|
+
{ target: "people", actions: ["read"] },
|
|
43
|
+
{ target: "workspace", actions: ["read"] }
|
|
44
|
+
],
|
|
38
45
|
object: [{ target: "*", actions: ALL_ACTIONS }]
|
|
39
46
|
}
|
|
40
47
|
};
|
|
48
|
+
var DEFAULT_ROLE_FOR_NEW_USERS = "member";
|
|
41
49
|
function isDefaultRole(roleName) {
|
|
42
50
|
return Object.values(DEFAULT_ROLES).includes(roleName);
|
|
43
51
|
}
|
|
44
|
-
function isAdminRole(roleName) {
|
|
45
|
-
return roleName === DEFAULT_ROLES.OWNER;
|
|
46
|
-
}
|
|
47
52
|
|
|
48
53
|
|
|
49
54
|
|
|
@@ -55,4 +60,4 @@ function isAdminRole(roleName) {
|
|
|
55
60
|
|
|
56
61
|
|
|
57
62
|
|
|
58
|
-
exports.SYSTEM_RESOURCES = SYSTEM_RESOURCES; exports.ALL_SYSTEM_RESOURCES = ALL_SYSTEM_RESOURCES; exports.SYSTEM_RESOURCE_LABELS = SYSTEM_RESOURCE_LABELS; exports.DEFAULT_ROLES = DEFAULT_ROLES; exports.DEFAULT_ROLE_LABELS = DEFAULT_ROLE_LABELS; exports.DEFAULT_ROLE_DESCRIPTIONS = DEFAULT_ROLE_DESCRIPTIONS; exports.DEFAULT_ROLE_PERMISSIONS = DEFAULT_ROLE_PERMISSIONS; exports.
|
|
63
|
+
exports.SYSTEM_RESOURCES = SYSTEM_RESOURCES; exports.ALL_SYSTEM_RESOURCES = ALL_SYSTEM_RESOURCES; exports.SYSTEM_RESOURCE_LABELS = SYSTEM_RESOURCE_LABELS; exports.DEFAULT_ROLES = DEFAULT_ROLES; exports.DEFAULT_ROLE_LABELS = DEFAULT_ROLE_LABELS; exports.DEFAULT_ROLE_DESCRIPTIONS = DEFAULT_ROLE_DESCRIPTIONS; exports.DEFAULT_ROLE_PERMISSIONS = DEFAULT_ROLE_PERMISSIONS; exports.DEFAULT_ROLE_FOR_NEW_USERS = DEFAULT_ROLE_FOR_NEW_USERS; exports.isDefaultRole = isDefaultRole;
|
|
@@ -2,16 +2,20 @@
|
|
|
2
2
|
var SYSTEM_RESOURCES = {
|
|
3
3
|
/** User profiles, invitations, roles and permissions management */
|
|
4
4
|
PEOPLE: "people",
|
|
5
|
-
/**
|
|
6
|
-
WORKSPACE: "workspace"
|
|
5
|
+
/** Tenant settings, audit logs, workflow execution, document generation */
|
|
6
|
+
WORKSPACE: "workspace",
|
|
7
|
+
/** Object definitions, attributes, views, workflow definitions */
|
|
8
|
+
ARCHITECT: "architect"
|
|
7
9
|
};
|
|
8
10
|
var ALL_SYSTEM_RESOURCES = [
|
|
9
11
|
SYSTEM_RESOURCES.PEOPLE,
|
|
10
|
-
SYSTEM_RESOURCES.WORKSPACE
|
|
12
|
+
SYSTEM_RESOURCES.WORKSPACE,
|
|
13
|
+
SYSTEM_RESOURCES.ARCHITECT
|
|
11
14
|
];
|
|
12
15
|
var SYSTEM_RESOURCE_LABELS = {
|
|
13
16
|
people: "People",
|
|
14
|
-
workspace: "Workspace"
|
|
17
|
+
workspace: "Workspace",
|
|
18
|
+
architect: "Architect"
|
|
15
19
|
};
|
|
16
20
|
var DEFAULT_ROLES = {
|
|
17
21
|
/** Full platform access - can manage everything */
|
|
@@ -34,16 +38,17 @@ var DEFAULT_ROLE_PERMISSIONS = {
|
|
|
34
38
|
object: [{ target: "*", actions: ALL_ACTIONS }]
|
|
35
39
|
},
|
|
36
40
|
member: {
|
|
37
|
-
system: [
|
|
41
|
+
system: [
|
|
42
|
+
{ target: "people", actions: ["read"] },
|
|
43
|
+
{ target: "workspace", actions: ["read"] }
|
|
44
|
+
],
|
|
38
45
|
object: [{ target: "*", actions: ALL_ACTIONS }]
|
|
39
46
|
}
|
|
40
47
|
};
|
|
48
|
+
var DEFAULT_ROLE_FOR_NEW_USERS = "member";
|
|
41
49
|
function isDefaultRole(roleName) {
|
|
42
50
|
return Object.values(DEFAULT_ROLES).includes(roleName);
|
|
43
51
|
}
|
|
44
|
-
function isAdminRole(roleName) {
|
|
45
|
-
return roleName === DEFAULT_ROLES.OWNER;
|
|
46
|
-
}
|
|
47
52
|
|
|
48
53
|
export {
|
|
49
54
|
SYSTEM_RESOURCES,
|
|
@@ -53,6 +58,6 @@ export {
|
|
|
53
58
|
DEFAULT_ROLE_LABELS,
|
|
54
59
|
DEFAULT_ROLE_DESCRIPTIONS,
|
|
55
60
|
DEFAULT_ROLE_PERMISSIONS,
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
DEFAULT_ROLE_FOR_NEW_USERS,
|
|
62
|
+
isDefaultRole
|
|
58
63
|
};
|
|
@@ -13,9 +13,6 @@ import {
|
|
|
13
13
|
validateObject,
|
|
14
14
|
validateObjectOrThrow
|
|
15
15
|
} from "./chunk-5SZ5OISG.mjs";
|
|
16
|
-
import {
|
|
17
|
-
isAdminRole
|
|
18
|
-
} from "./chunk-6P3NPTYV.mjs";
|
|
19
16
|
import {
|
|
20
17
|
__require
|
|
21
18
|
} from "./chunk-Y6FXYEAI.mjs";
|
|
@@ -1295,6 +1292,23 @@ function createQueryBuilder(recordService, adapter, objectName, options) {
|
|
|
1295
1292
|
return new QueryBuilder(recordService, adapter, objectName, initialState);
|
|
1296
1293
|
}
|
|
1297
1294
|
|
|
1295
|
+
// src/types/flows.ts
|
|
1296
|
+
function isFlowFieldsRow(row) {
|
|
1297
|
+
return !row.type || row.type === "fields";
|
|
1298
|
+
}
|
|
1299
|
+
function isLayoutRow(row) {
|
|
1300
|
+
return !!row.type && row.type !== "fields";
|
|
1301
|
+
}
|
|
1302
|
+
function isFlowDefinition(obj) {
|
|
1303
|
+
return typeof obj === "object" && obj !== null && "slots" in obj && "pages" in obj && "relations" in obj && "status" in obj;
|
|
1304
|
+
}
|
|
1305
|
+
function isFlowPublished(flow) {
|
|
1306
|
+
return flow.status === "published";
|
|
1307
|
+
}
|
|
1308
|
+
function isSystemFlow(flow) {
|
|
1309
|
+
return flow.system === true;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1298
1312
|
// src/types/workflows/nodes.ts
|
|
1299
1313
|
function isSimpleFormNode(node) {
|
|
1300
1314
|
return node.fields !== void 0 && node.rows === void 0;
|
|
@@ -1462,6 +1476,11 @@ function setContextValue(context, path, value) {
|
|
|
1462
1476
|
current[parts[parts.length - 1]] = value;
|
|
1463
1477
|
}
|
|
1464
1478
|
|
|
1479
|
+
// src/types/workflows/form-context.ts
|
|
1480
|
+
function isFormFieldsRow(row) {
|
|
1481
|
+
return !row.type || row.type === "fields";
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1465
1484
|
// src/types/workflows/theme.ts
|
|
1466
1485
|
var DEFAULT_THEME = {
|
|
1467
1486
|
borderRadius: 8,
|
|
@@ -1554,14 +1573,40 @@ var FlowRowFieldSchema = z.object({
|
|
|
1554
1573
|
id: z.string().min(1),
|
|
1555
1574
|
slotId: z.string().min(1),
|
|
1556
1575
|
attribute: z.string().min(1),
|
|
1557
|
-
label: z.string().optional(),
|
|
1576
|
+
label: z.string().max(200).optional(),
|
|
1577
|
+
tooltip: z.string().max(1e3).optional(),
|
|
1558
1578
|
required: z.boolean().optional()
|
|
1559
1579
|
});
|
|
1560
|
-
var
|
|
1580
|
+
var FlowFieldsRowSchema = z.object({
|
|
1561
1581
|
id: z.string().min(1),
|
|
1562
1582
|
order: z.number(),
|
|
1583
|
+
type: z.literal("fields").optional(),
|
|
1563
1584
|
fields: z.array(FlowRowFieldSchema)
|
|
1564
1585
|
});
|
|
1586
|
+
var FlowHeadingRowSchema = z.object({
|
|
1587
|
+
id: z.string().min(1),
|
|
1588
|
+
order: z.number(),
|
|
1589
|
+
type: z.literal("heading"),
|
|
1590
|
+
content: z.string().min(1).max(200),
|
|
1591
|
+
level: z.union([z.literal(1), z.literal(2), z.literal(3)]).optional()
|
|
1592
|
+
});
|
|
1593
|
+
var FlowSeparatorRowSchema = z.object({
|
|
1594
|
+
id: z.string().min(1),
|
|
1595
|
+
order: z.number(),
|
|
1596
|
+
type: z.literal("separator")
|
|
1597
|
+
});
|
|
1598
|
+
var FlowTextRowSchema = z.object({
|
|
1599
|
+
id: z.string().min(1),
|
|
1600
|
+
order: z.number(),
|
|
1601
|
+
type: z.literal("text"),
|
|
1602
|
+
content: z.string().min(1).max(5e3)
|
|
1603
|
+
});
|
|
1604
|
+
var FlowRowSchema = z.union([
|
|
1605
|
+
FlowHeadingRowSchema,
|
|
1606
|
+
FlowSeparatorRowSchema,
|
|
1607
|
+
FlowTextRowSchema,
|
|
1608
|
+
FlowFieldsRowSchema
|
|
1609
|
+
]);
|
|
1565
1610
|
var FormNodeSchema = z.object({
|
|
1566
1611
|
type: z.literal("form"),
|
|
1567
1612
|
id: z.string().min(1),
|
|
@@ -2237,9 +2282,11 @@ var FormExecutor = class {
|
|
|
2237
2282
|
}
|
|
2238
2283
|
if (node.rows) {
|
|
2239
2284
|
for (const row of node.rows) {
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2285
|
+
if (isFlowFieldsRow(row)) {
|
|
2286
|
+
for (const field of row.fields) {
|
|
2287
|
+
if (field.slotId) {
|
|
2288
|
+
slotIds.add(field.slotId);
|
|
2289
|
+
}
|
|
2243
2290
|
}
|
|
2244
2291
|
}
|
|
2245
2292
|
}
|
|
@@ -2304,9 +2351,11 @@ var FormExecutor = class {
|
|
|
2304
2351
|
}
|
|
2305
2352
|
if (node.rows) {
|
|
2306
2353
|
for (const row of node.rows) {
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2354
|
+
if (isFlowFieldsRow(row)) {
|
|
2355
|
+
for (const field of row.fields) {
|
|
2356
|
+
if (field.slotId && field.attribute) {
|
|
2357
|
+
refs.push({ slotId: field.slotId, attribute: field.attribute });
|
|
2358
|
+
}
|
|
2310
2359
|
}
|
|
2311
2360
|
}
|
|
2312
2361
|
}
|
|
@@ -4401,9 +4450,12 @@ function createMockUserProfilesRepository(stores) {
|
|
|
4401
4450
|
if (!existing) {
|
|
4402
4451
|
return Promise.reject(new Error(`UserProfile ${id} not found`));
|
|
4403
4452
|
}
|
|
4453
|
+
const sanitized = Object.fromEntries(
|
|
4454
|
+
Object.entries(data).map(([k, v]) => [k, v === null ? void 0 : v])
|
|
4455
|
+
);
|
|
4404
4456
|
const updated = {
|
|
4405
4457
|
...existing,
|
|
4406
|
-
...
|
|
4458
|
+
...sanitized,
|
|
4407
4459
|
updatedAt: /* @__PURE__ */ new Date()
|
|
4408
4460
|
};
|
|
4409
4461
|
stores.userProfiles.set(id, updated);
|
|
@@ -4590,8 +4642,6 @@ function createMockPermissionsRepository(stores) {
|
|
|
4590
4642
|
getEffectivePermissions(userProfileId) {
|
|
4591
4643
|
const tenantId = getTenantId();
|
|
4592
4644
|
const userRoleIds = Array.from(stores.userRoles.values()).filter((ur) => ur.userProfileId === userProfileId && ur.tenantId === tenantId).map((ur) => ur.roleId);
|
|
4593
|
-
const userRoles = Array.from(stores.roles.values()).filter((r) => userRoleIds.includes(r.id));
|
|
4594
|
-
const hasAdmin = userRoles.some((r) => isAdminRole(r.name));
|
|
4595
4645
|
const userPermissions = Array.from(stores.permissions.values()).filter(
|
|
4596
4646
|
(p) => userRoleIds.includes(p.roleId)
|
|
4597
4647
|
);
|
|
@@ -4618,7 +4668,7 @@ function createMockPermissionsRepository(stores) {
|
|
|
4618
4668
|
}
|
|
4619
4669
|
}
|
|
4620
4670
|
}
|
|
4621
|
-
return Promise.resolve({
|
|
4671
|
+
return Promise.resolve({ objectPermissions, systemPermissions });
|
|
4622
4672
|
},
|
|
4623
4673
|
countUsersWithRole(roleName) {
|
|
4624
4674
|
const tenantId = getTenantId();
|
|
@@ -5636,7 +5686,10 @@ var NON_SORTABLE_TYPES = /* @__PURE__ */ new Set([
|
|
|
5636
5686
|
"richtext",
|
|
5637
5687
|
"file",
|
|
5638
5688
|
"document",
|
|
5639
|
-
"location"
|
|
5689
|
+
"location",
|
|
5690
|
+
"user",
|
|
5691
|
+
"multiselect",
|
|
5692
|
+
"relation"
|
|
5640
5693
|
]);
|
|
5641
5694
|
function isAttributeSortable(attr) {
|
|
5642
5695
|
return !NON_SORTABLE_TYPES.has(attr.type);
|
|
@@ -8371,8 +8424,10 @@ var WorkflowBuilder = class {
|
|
|
8371
8424
|
}
|
|
8372
8425
|
if (node.rows) {
|
|
8373
8426
|
for (const row of node.rows) {
|
|
8374
|
-
|
|
8375
|
-
|
|
8427
|
+
if (isFlowFieldsRow(row)) {
|
|
8428
|
+
for (const field of row.fields) {
|
|
8429
|
+
referencedSlots.add(field.slotId);
|
|
8430
|
+
}
|
|
8376
8431
|
}
|
|
8377
8432
|
}
|
|
8378
8433
|
}
|
|
@@ -9867,15 +9922,31 @@ var AuditService = class extends BaseService {
|
|
|
9867
9922
|
if (!this.adapter.audit) {
|
|
9868
9923
|
return;
|
|
9869
9924
|
}
|
|
9925
|
+
const resolved = await this.resolveActorEmail(entry);
|
|
9870
9926
|
if (this.options?.async) {
|
|
9871
|
-
this.buffer.push(
|
|
9927
|
+
this.buffer.push(resolved);
|
|
9872
9928
|
const batchSize = this.options.batchSize ?? 10;
|
|
9873
9929
|
if (this.buffer.length >= batchSize) {
|
|
9874
9930
|
await this.flush();
|
|
9875
9931
|
}
|
|
9876
9932
|
} else {
|
|
9877
|
-
await this.adapter.audit.create(
|
|
9933
|
+
await this.adapter.audit.create(resolved);
|
|
9934
|
+
}
|
|
9935
|
+
}
|
|
9936
|
+
/**
|
|
9937
|
+
* Resolve actorEmail from user profiles if not already set
|
|
9938
|
+
*/
|
|
9939
|
+
async resolveActorEmail(entry) {
|
|
9940
|
+
if (!entry.actorEmail && entry.actorId) {
|
|
9941
|
+
try {
|
|
9942
|
+
const profile = await this.adapter.userProfiles.findById(entry.actorId);
|
|
9943
|
+
if (profile?.email) {
|
|
9944
|
+
return { ...entry, actorEmail: profile.email };
|
|
9945
|
+
}
|
|
9946
|
+
} catch {
|
|
9947
|
+
}
|
|
9878
9948
|
}
|
|
9949
|
+
return entry;
|
|
9879
9950
|
}
|
|
9880
9951
|
/**
|
|
9881
9952
|
* Start the flush timer for async mode
|
|
@@ -15123,6 +15194,74 @@ var UserProfileService = class extends BaseService {
|
|
|
15123
15194
|
await this.invalidateCache(cacheKeys.userProfileByEmail(this.tenantId, email));
|
|
15124
15195
|
}
|
|
15125
15196
|
}
|
|
15197
|
+
// ============================================================================
|
|
15198
|
+
// AVATAR URL RESOLUTION
|
|
15199
|
+
// ============================================================================
|
|
15200
|
+
/**
|
|
15201
|
+
* Resolve avatar storage path to a signed URL.
|
|
15202
|
+
* External URLs (https://) pass through unchanged.
|
|
15203
|
+
* Storage paths are resolved to fresh signed URLs (1h expiry).
|
|
15204
|
+
*/
|
|
15205
|
+
async resolveAvatarUrl(profile) {
|
|
15206
|
+
if (!profile.avatarUrl || profile.avatarUrl.startsWith("https://")) {
|
|
15207
|
+
return profile;
|
|
15208
|
+
}
|
|
15209
|
+
if (!this.adapter.storage) return profile;
|
|
15210
|
+
try {
|
|
15211
|
+
const signedUrl = await this.adapter.storage.getSignedUrl(profile.avatarUrl, {
|
|
15212
|
+
expiresIn: 3600
|
|
15213
|
+
});
|
|
15214
|
+
return { ...profile, avatarUrl: signedUrl };
|
|
15215
|
+
} catch {
|
|
15216
|
+
return profile;
|
|
15217
|
+
}
|
|
15218
|
+
}
|
|
15219
|
+
async resolveAvatarUrls(profiles) {
|
|
15220
|
+
return Promise.all(profiles.map((p) => this.resolveAvatarUrl(p)));
|
|
15221
|
+
}
|
|
15222
|
+
// ============================================================================
|
|
15223
|
+
// AVATAR MANAGEMENT
|
|
15224
|
+
// ============================================================================
|
|
15225
|
+
/**
|
|
15226
|
+
* Upload a new avatar for the user.
|
|
15227
|
+
* Deletes previous avatar from storage if it was an internal upload.
|
|
15228
|
+
* Stores the storagePath — resolved to signed URL at read time.
|
|
15229
|
+
*/
|
|
15230
|
+
async uploadAvatar(profileId, input) {
|
|
15231
|
+
if (!this.adapter.storage) {
|
|
15232
|
+
throw new Error("StorageAdapter is not configured.");
|
|
15233
|
+
}
|
|
15234
|
+
if (!input.mimeType.startsWith("image/")) {
|
|
15235
|
+
throw new Error("Only image files are allowed for avatars.");
|
|
15236
|
+
}
|
|
15237
|
+
const profile = await this.getProfileOrThrow(profileId);
|
|
15238
|
+
if (profile.avatarUrl && !profile.avatarUrl.startsWith("https://")) {
|
|
15239
|
+
await this.adapter.storage.delete(profile.avatarUrl).catch(() => void 0);
|
|
15240
|
+
}
|
|
15241
|
+
const result = await this.adapter.storage.upload({
|
|
15242
|
+
content: input.content,
|
|
15243
|
+
fileName: input.fileName,
|
|
15244
|
+
mimeType: input.mimeType,
|
|
15245
|
+
size: input.size,
|
|
15246
|
+
tenantId: this.tenantId,
|
|
15247
|
+
folderPath: "avatars"
|
|
15248
|
+
});
|
|
15249
|
+
return await this.updateProfile(profileId, { avatarUrl: result.storagePath });
|
|
15250
|
+
}
|
|
15251
|
+
/**
|
|
15252
|
+
* Delete the user's avatar.
|
|
15253
|
+
* Removes file from storage if it was an internal upload, then clears avatarUrl.
|
|
15254
|
+
*/
|
|
15255
|
+
async deleteAvatar(profileId) {
|
|
15256
|
+
const profile = await this.getProfileOrThrow(profileId);
|
|
15257
|
+
if (profile.avatarUrl && !profile.avatarUrl.startsWith("https://")) {
|
|
15258
|
+
await this.adapter.storage?.delete(profile.avatarUrl).catch(() => void 0);
|
|
15259
|
+
}
|
|
15260
|
+
return await this.updateProfile(profileId, { avatarUrl: null });
|
|
15261
|
+
}
|
|
15262
|
+
// ============================================================================
|
|
15263
|
+
// CREATE
|
|
15264
|
+
// ============================================================================
|
|
15126
15265
|
/**
|
|
15127
15266
|
* Create a new user profile (typically after first auth).
|
|
15128
15267
|
* Automatically uses tenant context from AsyncLocalStorage.
|
|
@@ -15163,18 +15302,19 @@ var UserProfileService = class extends BaseService {
|
|
|
15163
15302
|
targetUserEmail: profile.email
|
|
15164
15303
|
});
|
|
15165
15304
|
}
|
|
15166
|
-
return profile;
|
|
15305
|
+
return this.resolveAvatarUrl(profile);
|
|
15167
15306
|
}
|
|
15168
15307
|
/**
|
|
15169
15308
|
* Get user profile by ID.
|
|
15170
15309
|
* Results are cached if a CacheAdapter is configured.
|
|
15171
15310
|
*/
|
|
15172
15311
|
async getProfile(profileId) {
|
|
15173
|
-
|
|
15312
|
+
const profile = await this.cachedBy(
|
|
15174
15313
|
"userProfileById",
|
|
15175
15314
|
profileId,
|
|
15176
15315
|
() => this.adapter.userProfiles.findById(profileId)
|
|
15177
15316
|
);
|
|
15317
|
+
return profile ? this.resolveAvatarUrl(profile) : null;
|
|
15178
15318
|
}
|
|
15179
15319
|
/**
|
|
15180
15320
|
* Get user profile by ID or throw
|
|
@@ -15196,11 +15336,12 @@ var UserProfileService = class extends BaseService {
|
|
|
15196
15336
|
* @returns User profile or null
|
|
15197
15337
|
*/
|
|
15198
15338
|
async getProfileByAuthId(authId) {
|
|
15199
|
-
|
|
15339
|
+
const profile = await this.cachedBy(
|
|
15200
15340
|
"userProfileByAuthId",
|
|
15201
15341
|
authId,
|
|
15202
15342
|
() => this.adapter.userProfiles.findByAuthId(authId)
|
|
15203
15343
|
);
|
|
15344
|
+
return profile ? this.resolveAvatarUrl(profile) : null;
|
|
15204
15345
|
}
|
|
15205
15346
|
/**
|
|
15206
15347
|
* Get or create user profile (idempotent operation)
|
|
@@ -15239,11 +15380,11 @@ var UserProfileService = class extends BaseService {
|
|
|
15239
15380
|
const updated = await this.adapter.userProfiles.update(profileId, data);
|
|
15240
15381
|
await this.invalidateProfileCache(updated.id, updated.authId, updated.email);
|
|
15241
15382
|
if (this.auditService && this.userId) {
|
|
15242
|
-
const changes = buildAuditChanges(
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
"status"
|
|
15246
|
-
|
|
15383
|
+
const changes = buildAuditChanges(
|
|
15384
|
+
existing,
|
|
15385
|
+
data,
|
|
15386
|
+
["firstName", "lastName", "status"]
|
|
15387
|
+
);
|
|
15247
15388
|
if (changes.length > 0) {
|
|
15248
15389
|
await this.auditService.logUserAction({
|
|
15249
15390
|
action: "user.updated",
|
|
@@ -15254,7 +15395,7 @@ var UserProfileService = class extends BaseService {
|
|
|
15254
15395
|
});
|
|
15255
15396
|
}
|
|
15256
15397
|
}
|
|
15257
|
-
return updated;
|
|
15398
|
+
return this.resolveAvatarUrl(updated);
|
|
15258
15399
|
}
|
|
15259
15400
|
/**
|
|
15260
15401
|
* Delete user profile.
|
|
@@ -15291,7 +15432,8 @@ var UserProfileService = class extends BaseService {
|
|
|
15291
15432
|
* Automatically uses tenant context from AsyncLocalStorage.
|
|
15292
15433
|
*/
|
|
15293
15434
|
async listProfiles(options) {
|
|
15294
|
-
|
|
15435
|
+
const profiles = await this.adapter.userProfiles.list(options);
|
|
15436
|
+
return this.resolveAvatarUrls(profiles);
|
|
15295
15437
|
}
|
|
15296
15438
|
/**
|
|
15297
15439
|
* Update last login timestamp
|
|
@@ -15322,11 +15464,12 @@ var UserProfileService = class extends BaseService {
|
|
|
15322
15464
|
* Automatically uses tenant context from AsyncLocalStorage.
|
|
15323
15465
|
*/
|
|
15324
15466
|
async getProfileByEmail(email) {
|
|
15325
|
-
|
|
15467
|
+
const profile = await this.cachedBy(
|
|
15326
15468
|
"userProfileByEmail",
|
|
15327
15469
|
email,
|
|
15328
15470
|
() => this.adapter.userProfiles.findByEmail(email)
|
|
15329
15471
|
);
|
|
15472
|
+
return profile ? this.resolveAvatarUrl(profile) : null;
|
|
15330
15473
|
}
|
|
15331
15474
|
/**
|
|
15332
15475
|
* Invite a new user by email.
|
|
@@ -15359,6 +15502,21 @@ var UserProfileService = class extends BaseService {
|
|
|
15359
15502
|
throw new Error(`User with email "${data.email}" already exists in this tenant`);
|
|
15360
15503
|
}
|
|
15361
15504
|
const profile = await this.adapter.userProfiles.invite(data);
|
|
15505
|
+
if (this.adapter.permissions) {
|
|
15506
|
+
try {
|
|
15507
|
+
const roles = await this.adapter.permissions.getRoles();
|
|
15508
|
+
const defaultRole = roles.find((r) => r.name === "member" && r.system);
|
|
15509
|
+
if (defaultRole) {
|
|
15510
|
+
await this.adapter.permissions.assignRole({
|
|
15511
|
+
userProfileId: profile.id,
|
|
15512
|
+
roleId: defaultRole.id,
|
|
15513
|
+
tenantId: this.tenantId,
|
|
15514
|
+
assignedBy: this.userId ?? void 0
|
|
15515
|
+
});
|
|
15516
|
+
}
|
|
15517
|
+
} catch {
|
|
15518
|
+
}
|
|
15519
|
+
}
|
|
15362
15520
|
await this.invalidateProfileCache(profile.id, profile.authId, profile.email);
|
|
15363
15521
|
if (this.auditService && this.userId) {
|
|
15364
15522
|
await this.auditService.logUserAction({
|
|
@@ -15368,7 +15526,7 @@ var UserProfileService = class extends BaseService {
|
|
|
15368
15526
|
targetUserEmail: profile.email
|
|
15369
15527
|
});
|
|
15370
15528
|
}
|
|
15371
|
-
return profile;
|
|
15529
|
+
return this.resolveAvatarUrl(profile);
|
|
15372
15530
|
}
|
|
15373
15531
|
};
|
|
15374
15532
|
|
|
@@ -17041,14 +17199,11 @@ var FileService = class extends BaseService {
|
|
|
17041
17199
|
* @param userId - User ID to check
|
|
17042
17200
|
* @returns true if user can access the file
|
|
17043
17201
|
*/
|
|
17044
|
-
async checkAccess(fileId, userId
|
|
17202
|
+
async checkAccess(fileId, userId) {
|
|
17045
17203
|
const file2 = await this.getFile(fileId);
|
|
17046
17204
|
if (!file2) {
|
|
17047
17205
|
return false;
|
|
17048
17206
|
}
|
|
17049
|
-
if (options?.isAdmin) {
|
|
17050
|
-
return true;
|
|
17051
|
-
}
|
|
17052
17207
|
if (file2.visibility === "public") {
|
|
17053
17208
|
return true;
|
|
17054
17209
|
}
|
|
@@ -17332,9 +17487,6 @@ var PermissionService = class extends BaseService {
|
|
|
17332
17487
|
*/
|
|
17333
17488
|
async canAccessObject(userProfileId, objectName, action) {
|
|
17334
17489
|
const permissions = await this.getEffectivePermissions(userProfileId);
|
|
17335
|
-
if (permissions.isAdmin) {
|
|
17336
|
-
return true;
|
|
17337
|
-
}
|
|
17338
17490
|
const wildcardPerms = permissions.objectPermissions["*"];
|
|
17339
17491
|
if (wildcardPerms?.includes(action)) {
|
|
17340
17492
|
return true;
|
|
@@ -17366,9 +17518,6 @@ var PermissionService = class extends BaseService {
|
|
|
17366
17518
|
*/
|
|
17367
17519
|
async getObjectPermissions(userProfileId, objectName) {
|
|
17368
17520
|
const permissions = await this.getEffectivePermissions(userProfileId);
|
|
17369
|
-
if (permissions.isAdmin) {
|
|
17370
|
-
return { canRead: true, canCreate: true, canUpdate: true, canDelete: true };
|
|
17371
|
-
}
|
|
17372
17521
|
const wildcardPerms = permissions.objectPermissions["*"] ?? [];
|
|
17373
17522
|
const objectPerms = permissions.objectPermissions[objectName] ?? [];
|
|
17374
17523
|
const allPerms = /* @__PURE__ */ new Set([...wildcardPerms, ...objectPerms]);
|
|
@@ -17392,9 +17541,6 @@ var PermissionService = class extends BaseService {
|
|
|
17392
17541
|
*/
|
|
17393
17542
|
async canAccessSystem(userProfileId, resource, action) {
|
|
17394
17543
|
const permissions = await this.getEffectivePermissions(userProfileId);
|
|
17395
|
-
if (permissions.isAdmin) {
|
|
17396
|
-
return true;
|
|
17397
|
-
}
|
|
17398
17544
|
const wildcardPerms = permissions.systemPermissions?.["*"];
|
|
17399
17545
|
if (wildcardPerms?.includes(action)) {
|
|
17400
17546
|
return true;
|
|
@@ -17426,9 +17572,6 @@ var PermissionService = class extends BaseService {
|
|
|
17426
17572
|
*/
|
|
17427
17573
|
async getSystemPermissions(userProfileId, resource) {
|
|
17428
17574
|
const permissions = await this.getEffectivePermissions(userProfileId);
|
|
17429
|
-
if (permissions.isAdmin) {
|
|
17430
|
-
return { canRead: true, canCreate: true, canUpdate: true, canDelete: true };
|
|
17431
|
-
}
|
|
17432
17575
|
const wildcardPerms = permissions.systemPermissions?.["*"] ?? [];
|
|
17433
17576
|
const resourcePerms = permissions.systemPermissions?.[resource] ?? [];
|
|
17434
17577
|
const allPerms = /* @__PURE__ */ new Set([...wildcardPerms, ...resourcePerms]);
|
|
@@ -17633,9 +17776,8 @@ var PermissionService = class extends BaseService {
|
|
|
17633
17776
|
* Initialize default roles for the tenant if they don't exist.
|
|
17634
17777
|
*
|
|
17635
17778
|
* Creates the following roles with their default permissions:
|
|
17636
|
-
* - **
|
|
17637
|
-
* - **member**:
|
|
17638
|
-
* - **guest**: No system access, read-only access to objects
|
|
17779
|
+
* - **owner**: Full access to all system resources and objects
|
|
17780
|
+
* - **member**: Full CRUD on business data, read-only on system resources (people, workspace)
|
|
17639
17781
|
*
|
|
17640
17782
|
* This method is idempotent - it only creates roles that don't already exist.
|
|
17641
17783
|
* Should be called during tenant bootstrap or on first admin login.
|
|
@@ -17652,7 +17794,7 @@ var PermissionService = class extends BaseService {
|
|
|
17652
17794
|
DEFAULT_ROLE_LABELS,
|
|
17653
17795
|
DEFAULT_ROLE_DESCRIPTIONS,
|
|
17654
17796
|
DEFAULT_ROLE_PERMISSIONS
|
|
17655
|
-
} = await import("./default-roles-
|
|
17797
|
+
} = await import("./default-roles-6D3HQ3DQ.mjs");
|
|
17656
17798
|
const existingRoles = await this.getRoles();
|
|
17657
17799
|
const existingRoleNames = existingRoles.reduce((set, r) => set.add(r.name), /* @__PURE__ */ new Set());
|
|
17658
17800
|
for (const roleName of Object.values(DEFAULT_ROLES)) {
|
|
@@ -18591,9 +18733,7 @@ async function cleanupOrphanObjects(adapter, nativeObjects, result, options) {
|
|
|
18591
18733
|
const registryNames = nativeObjects.map((obj) => obj.name);
|
|
18592
18734
|
if (options.dryRun) {
|
|
18593
18735
|
const allObjects = await adapter.objects.list();
|
|
18594
|
-
const orphans = allObjects.filter(
|
|
18595
|
-
(obj) => obj.system && !registryNames.includes(obj.name)
|
|
18596
|
-
);
|
|
18736
|
+
const orphans = allObjects.filter((obj) => obj.system && !registryNames.includes(obj.name));
|
|
18597
18737
|
result.objectsDeleted += orphans.length;
|
|
18598
18738
|
if (options.verbose && orphans.length > 0) {
|
|
18599
18739
|
console.info(
|
|
@@ -18681,6 +18821,11 @@ export {
|
|
|
18681
18821
|
AttributeInUseError,
|
|
18682
18822
|
ObjectReferencedError,
|
|
18683
18823
|
getErrorMessage,
|
|
18824
|
+
isFlowFieldsRow,
|
|
18825
|
+
isLayoutRow,
|
|
18826
|
+
isFlowDefinition,
|
|
18827
|
+
isFlowPublished,
|
|
18828
|
+
isSystemFlow,
|
|
18684
18829
|
NoopGeocodingAdapter,
|
|
18685
18830
|
SYSTEM_FIELD_NAMES,
|
|
18686
18831
|
RESERVED_ATTRIBUTE_NAMES,
|
|
@@ -18723,6 +18868,7 @@ export {
|
|
|
18723
18868
|
createEmptyContext,
|
|
18724
18869
|
getContextValue,
|
|
18725
18870
|
setContextValue,
|
|
18871
|
+
isFormFieldsRow,
|
|
18726
18872
|
DEFAULT_THEME,
|
|
18727
18873
|
mergeWithDefaults,
|
|
18728
18874
|
generateCssVariables,
|