@memberjunction/core-entities 5.28.0 → 5.30.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.
Files changed (109) hide show
  1. package/dist/custom/MJConversationDetailEntityExtended.d.ts +31 -0
  2. package/dist/custom/MJConversationDetailEntityExtended.d.ts.map +1 -0
  3. package/dist/custom/MJConversationDetailEntityExtended.js +106 -0
  4. package/dist/custom/MJConversationDetailEntityExtended.js.map +1 -0
  5. package/dist/custom/PermissionProviders/AIAgentPermissionProvider.d.ts +31 -0
  6. package/dist/custom/PermissionProviders/AIAgentPermissionProvider.d.ts.map +1 -0
  7. package/dist/custom/PermissionProviders/AIAgentPermissionProvider.js +151 -0
  8. package/dist/custom/PermissionProviders/AIAgentPermissionProvider.js.map +1 -0
  9. package/dist/custom/PermissionProviders/AccessControlRuleProvider.d.ts +45 -0
  10. package/dist/custom/PermissionProviders/AccessControlRuleProvider.d.ts.map +1 -0
  11. package/dist/custom/PermissionProviders/AccessControlRuleProvider.js +253 -0
  12. package/dist/custom/PermissionProviders/AccessControlRuleProvider.js.map +1 -0
  13. package/dist/custom/PermissionProviders/ApplicationRolePermissionProvider.d.ts +28 -0
  14. package/dist/custom/PermissionProviders/ApplicationRolePermissionProvider.d.ts.map +1 -0
  15. package/dist/custom/PermissionProviders/ApplicationRolePermissionProvider.js +144 -0
  16. package/dist/custom/PermissionProviders/ApplicationRolePermissionProvider.js.map +1 -0
  17. package/dist/custom/PermissionProviders/ArtifactPermissionProvider.d.ts +45 -0
  18. package/dist/custom/PermissionProviders/ArtifactPermissionProvider.d.ts.map +1 -0
  19. package/dist/custom/PermissionProviders/ArtifactPermissionProvider.js +169 -0
  20. package/dist/custom/PermissionProviders/ArtifactPermissionProvider.js.map +1 -0
  21. package/dist/custom/PermissionProviders/CollectionPermissionProvider.d.ts +40 -0
  22. package/dist/custom/PermissionProviders/CollectionPermissionProvider.d.ts.map +1 -0
  23. package/dist/custom/PermissionProviders/CollectionPermissionProvider.js +220 -0
  24. package/dist/custom/PermissionProviders/CollectionPermissionProvider.js.map +1 -0
  25. package/dist/custom/PermissionProviders/DashboardPermissionProvider.d.ts +47 -0
  26. package/dist/custom/PermissionProviders/DashboardPermissionProvider.d.ts.map +1 -0
  27. package/dist/custom/PermissionProviders/DashboardPermissionProvider.js +218 -0
  28. package/dist/custom/PermissionProviders/DashboardPermissionProvider.js.map +1 -0
  29. package/dist/custom/PermissionProviders/EntityPermissionProvider.d.ts +25 -0
  30. package/dist/custom/PermissionProviders/EntityPermissionProvider.d.ts.map +1 -0
  31. package/dist/custom/PermissionProviders/EntityPermissionProvider.js +129 -0
  32. package/dist/custom/PermissionProviders/EntityPermissionProvider.js.map +1 -0
  33. package/dist/custom/PermissionProviders/QueryPermissionProvider.d.ts +24 -0
  34. package/dist/custom/PermissionProviders/QueryPermissionProvider.d.ts.map +1 -0
  35. package/dist/custom/PermissionProviders/QueryPermissionProvider.js +123 -0
  36. package/dist/custom/PermissionProviders/QueryPermissionProvider.js.map +1 -0
  37. package/dist/custom/PermissionProviders/ResourcePermissionProvider.d.ts +39 -0
  38. package/dist/custom/PermissionProviders/ResourcePermissionProvider.d.ts.map +1 -0
  39. package/dist/custom/PermissionProviders/ResourcePermissionProvider.js +193 -0
  40. package/dist/custom/PermissionProviders/ResourcePermissionProvider.js.map +1 -0
  41. package/dist/custom/PermissionProviders/index.d.ts +16 -0
  42. package/dist/custom/PermissionProviders/index.d.ts.map +1 -0
  43. package/dist/custom/PermissionProviders/index.js +41 -0
  44. package/dist/custom/PermissionProviders/index.js.map +1 -0
  45. package/dist/custom/Permissions/BaseShareEntityExtended.d.ts +105 -0
  46. package/dist/custom/Permissions/BaseShareEntityExtended.d.ts.map +1 -0
  47. package/dist/custom/Permissions/BaseShareEntityExtended.js +162 -0
  48. package/dist/custom/Permissions/BaseShareEntityExtended.js.map +1 -0
  49. package/dist/custom/Permissions/MJAccessControlRuleEntityExtended.d.ts +22 -0
  50. package/dist/custom/Permissions/MJAccessControlRuleEntityExtended.d.ts.map +1 -0
  51. package/dist/custom/Permissions/MJAccessControlRuleEntityExtended.js +75 -0
  52. package/dist/custom/Permissions/MJAccessControlRuleEntityExtended.js.map +1 -0
  53. package/dist/custom/Permissions/MJArtifactPermissionEntityExtended.d.ts +22 -0
  54. package/dist/custom/Permissions/MJArtifactPermissionEntityExtended.d.ts.map +1 -0
  55. package/dist/custom/Permissions/MJArtifactPermissionEntityExtended.js +114 -0
  56. package/dist/custom/Permissions/MJArtifactPermissionEntityExtended.js.map +1 -0
  57. package/dist/custom/Permissions/MJCollectionPermissionEntityExtended.d.ts +25 -0
  58. package/dist/custom/Permissions/MJCollectionPermissionEntityExtended.d.ts.map +1 -0
  59. package/dist/custom/Permissions/MJCollectionPermissionEntityExtended.js +101 -0
  60. package/dist/custom/Permissions/MJCollectionPermissionEntityExtended.js.map +1 -0
  61. package/dist/custom/Permissions/MJDashboardPermissionEntityExtended.d.ts +32 -0
  62. package/dist/custom/Permissions/MJDashboardPermissionEntityExtended.d.ts.map +1 -0
  63. package/dist/custom/Permissions/MJDashboardPermissionEntityExtended.js +95 -0
  64. package/dist/custom/Permissions/MJDashboardPermissionEntityExtended.js.map +1 -0
  65. package/dist/custom/Permissions/index.d.ts +13 -0
  66. package/dist/custom/Permissions/index.d.ts.map +1 -0
  67. package/dist/custom/Permissions/index.js +22 -0
  68. package/dist/custom/Permissions/index.js.map +1 -0
  69. package/dist/custom/Permissions/shareNotification.d.ts +72 -0
  70. package/dist/custom/Permissions/shareNotification.d.ts.map +1 -0
  71. package/dist/custom/Permissions/shareNotification.js +98 -0
  72. package/dist/custom/Permissions/shareNotification.js.map +1 -0
  73. package/dist/custom/ResourcePermissions/MJResourcePermissionEntityExtended.d.ts +63 -1
  74. package/dist/custom/ResourcePermissions/MJResourcePermissionEntityExtended.d.ts.map +1 -1
  75. package/dist/custom/ResourcePermissions/MJResourcePermissionEntityExtended.js +244 -27
  76. package/dist/custom/ResourcePermissions/MJResourcePermissionEntityExtended.js.map +1 -1
  77. package/dist/custom/ResourcePermissions/ResourcePermissionEngine.d.ts +7 -0
  78. package/dist/custom/ResourcePermissions/ResourcePermissionEngine.d.ts.map +1 -1
  79. package/dist/custom/ResourcePermissions/ResourcePermissionEngine.js +13 -0
  80. package/dist/custom/ResourcePermissions/ResourcePermissionEngine.js.map +1 -1
  81. package/dist/engines/GeoDataEngine.d.ts +42 -8
  82. package/dist/engines/GeoDataEngine.d.ts.map +1 -1
  83. package/dist/engines/GeoDataEngine.js +191 -36
  84. package/dist/engines/GeoDataEngine.js.map +1 -1
  85. package/dist/engines/MCPEngine.d.ts +20 -1
  86. package/dist/engines/MCPEngine.d.ts.map +1 -1
  87. package/dist/engines/MCPEngine.js +31 -0
  88. package/dist/engines/MCPEngine.js.map +1 -1
  89. package/dist/engines/PermissionEngine.d.ts +142 -0
  90. package/dist/engines/PermissionEngine.d.ts.map +1 -0
  91. package/dist/engines/PermissionEngine.js +343 -0
  92. package/dist/engines/PermissionEngine.js.map +1 -0
  93. package/dist/engines/UserInfoEngine.d.ts +6 -1
  94. package/dist/engines/UserInfoEngine.d.ts.map +1 -1
  95. package/dist/engines/UserInfoEngine.js +21 -5
  96. package/dist/engines/UserInfoEngine.js.map +1 -1
  97. package/dist/engines/conversations.d.ts +35 -0
  98. package/dist/engines/conversations.d.ts.map +1 -1
  99. package/dist/engines/conversations.js +103 -16
  100. package/dist/engines/conversations.js.map +1 -1
  101. package/dist/generated/entity_subclasses.d.ts +1593 -78
  102. package/dist/generated/entity_subclasses.d.ts.map +1 -1
  103. package/dist/generated/entity_subclasses.js +2440 -352
  104. package/dist/generated/entity_subclasses.js.map +1 -1
  105. package/dist/index.d.ts +4 -0
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +8 -0
  108. package/dist/index.js.map +1 -1
  109. package/package.json +5 -5
@@ -0,0 +1,105 @@
1
+ import { BaseEntity, EntityPermissionType, EntitySaveOptions, IMetadataProvider, UserInfo } from '@memberjunction/core';
2
+ import { ShareNotificationInput } from './shareNotification.js';
3
+ /**
4
+ * Shared lifecycle for the four user-grantee sharing permission entities
5
+ * (Dashboard, Artifact, Collection, Access Control Rule). Each of those
6
+ * classes delegates three repetitive behaviors to the helpers in this module:
7
+ *
8
+ * 1. **Grantor Update/Delete relaxation** — {@link checkShareManagePermission}
9
+ * Lets the grantor (and, via the optional `additional` hook, resource owners
10
+ * or other privileged parties) revoke or edit their own grant without needing
11
+ * broader CRUD on the permission entity itself.
12
+ *
13
+ * 2. **Post-save share notification dispatch** — {@link dispatchShareNotificationAfterSave}
14
+ * After a successful server-side save of a new share, asks the caller for
15
+ * a notification payload and fires it off through `CreateShareNotification`.
16
+ * Returning `null` from the payload builder short-circuits (used by Access
17
+ * Control Rules for Role / Everyone grantees who have no single recipient).
18
+ *
19
+ * 3. **Action summary rendering** — {@link buildActionsSummary}
20
+ * Turns `{ view: this.CanRead, edit: this.CanEdit, … }` into `"view, edit"`.
21
+ *
22
+ * The original class inheritance shape is preserved (each extended class still
23
+ * extends its generated entity base) — these are plain functions the subclasses
24
+ * call from their `CheckPermissions` / `Save` overrides. We use functions rather
25
+ * than another class in the chain because each permission entity already has a
26
+ * fixed generated base, and multiple inheritance isn't available in TypeScript.
27
+ */
28
+ /**
29
+ * Determine whether `user` may Update/Delete a share row they don't own via
30
+ * role permissions. Returns true when the user is the grantor, or when the
31
+ * optional `additional(userId)` predicate says they have some domain-specific
32
+ * management right (e.g., dashboard owner, Owner-level grantee).
33
+ *
34
+ * Use:
35
+ * ```typescript
36
+ * override CheckPermissions(type, throwError) {
37
+ * if ((type === Update || Delete) && this.ActiveUser &&
38
+ * checkShareManagePermission(this.ActiveUser, this.SharedByUserID, (u) => …)) {
39
+ * return true;
40
+ * }
41
+ * return super.CheckPermissions(type, throwError);
42
+ * }
43
+ * ```
44
+ */
45
+ export declare function checkShareManagePermission(user: UserInfo, grantorUserId: string | null | undefined, additional?: (userId: string) => boolean): boolean;
46
+ /**
47
+ * Post-save share-notification dispatcher for extended permission entities.
48
+ * Call immediately after `super.Save(options)` returns `true`:
49
+ *
50
+ * ```typescript
51
+ * const saved = await super.Save(options);
52
+ * if (saved) {
53
+ * await dispatchShareNotificationAfterSave(this, isNewShare, async (provider, grantorId) => {
54
+ * return { Provider: provider, ContextUser: this.ContextCurrentUser, … };
55
+ * });
56
+ * }
57
+ * return saved;
58
+ * ```
59
+ *
60
+ * Handles the boilerplate each previous implementation repeated:
61
+ * - bail on client-side saves (`ProviderType !== 'Database'`)
62
+ * - bail on updates (`isNewShare === false`)
63
+ * - resolve the effective grantor ID (falls back to ContextCurrentUser.ID)
64
+ * - let `payloadBuilder` return `null` to skip (e.g., Role-grantee ACRs)
65
+ * - fire-and-forget via `void CreateShareNotification(...)` — notification
66
+ * failures never fail the save.
67
+ */
68
+ export declare function dispatchShareNotificationAfterSave(entity: BaseEntity, isNewShare: boolean, grantorUserId: string | null | undefined, payloadBuilder: (provider: IMetadataProvider, grantorId: string) => Promise<ShareNotificationInput | null> | ShareNotificationInput | null): Promise<void>;
69
+ /**
70
+ * Turn `{ view: this.CanRead, edit: this.CanEdit, … }` into `"view, edit"`.
71
+ * Truthy verbs are emitted in declaration order. Replaces the hand-rolled
72
+ * `actionsSummary()` method each sharing entity used to carry.
73
+ */
74
+ export declare function buildActionsSummary(flags: Record<string, boolean | null | undefined>): string;
75
+ /**
76
+ * Server-side gate for CREATING a new share. Blocks users who hold role-level
77
+ * `CanCreate` on a sharing entity but don't own the target resource and don't
78
+ * already hold a Share-capable grant on it.
79
+ *
80
+ * Separate from `checkShareManagePermission` (which handles Update/Delete) because
81
+ * Angular's default role-based check can't express "the caller owns the underlying
82
+ * resource" — that requires a resource-specific lookup.
83
+ *
84
+ * Usage in an extended entity's `Save()` override:
85
+ * ```typescript
86
+ * const isNewShare = !this.IsSaved;
87
+ * if (!assertCallerMayCreateShare(this, isNewShare, () => this.callerIsAuthorizedToShare())) {
88
+ * return false; // save is short-circuited; LatestResult carries the reason
89
+ * }
90
+ * const saved = await super.Save(options);
91
+ * ```
92
+ *
93
+ * Returns `true` when the save should proceed, `false` to short-circuit.
94
+ * On `false`, sets `entity.LatestResult` with `Success=false` and a user-visible
95
+ * `Message`, and emits a `LogError` for server logs.
96
+ *
97
+ * Short-circuits to `true` (allows the save) when:
98
+ * - `isNewShare` is false (not a create — Update/Delete handled by CheckPermissions)
99
+ * - provider is not the Database provider (client-side save, already trusted)
100
+ * - `entity.ContextCurrentUser` is missing (defer to downstream auth layers)
101
+ */
102
+ export declare function assertCallerMayCreateShare(entity: BaseEntity, isNewShare: boolean, authorized: () => boolean | Promise<boolean>, reason?: string): Promise<boolean> | boolean;
103
+ /** Re-export for ergonomic `import { EntityPermissionType } from '...'` in subclasses. */
104
+ export { EntityPermissionType, EntitySaveOptions };
105
+ //# sourceMappingURL=BaseShareEntityExtended.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseShareEntityExtended.d.ts","sourceRoot":"","sources":["../../../src/custom/Permissions/BaseShareEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,iBAAiB,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGlI,OAAO,EAA2B,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,0BAA0B,CACtC,IAAI,EAAE,QAAQ,EACd,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GACzC,OAAO,CAIT;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,kCAAkC,CACpD,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,OAAO,EACnB,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,cAAc,EAAE,CAAC,QAAQ,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,sBAAsB,GAAG,IAAI,GAC3I,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAM7F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EAC5C,MAAM,GAAE,MAA0F,GACnG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAY5B;AAgBD,0FAA0F;AAC1F,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,162 @@
1
+ import { EntityPermissionType, EntitySaveOptions, LogError } from '@memberjunction/core';
2
+ import { UUIDsEqual } from '@memberjunction/global';
3
+ import { CreateShareNotification } from './shareNotification.js';
4
+ /**
5
+ * Shared lifecycle for the four user-grantee sharing permission entities
6
+ * (Dashboard, Artifact, Collection, Access Control Rule). Each of those
7
+ * classes delegates three repetitive behaviors to the helpers in this module:
8
+ *
9
+ * 1. **Grantor Update/Delete relaxation** — {@link checkShareManagePermission}
10
+ * Lets the grantor (and, via the optional `additional` hook, resource owners
11
+ * or other privileged parties) revoke or edit their own grant without needing
12
+ * broader CRUD on the permission entity itself.
13
+ *
14
+ * 2. **Post-save share notification dispatch** — {@link dispatchShareNotificationAfterSave}
15
+ * After a successful server-side save of a new share, asks the caller for
16
+ * a notification payload and fires it off through `CreateShareNotification`.
17
+ * Returning `null` from the payload builder short-circuits (used by Access
18
+ * Control Rules for Role / Everyone grantees who have no single recipient).
19
+ *
20
+ * 3. **Action summary rendering** — {@link buildActionsSummary}
21
+ * Turns `{ view: this.CanRead, edit: this.CanEdit, … }` into `"view, edit"`.
22
+ *
23
+ * The original class inheritance shape is preserved (each extended class still
24
+ * extends its generated entity base) — these are plain functions the subclasses
25
+ * call from their `CheckPermissions` / `Save` overrides. We use functions rather
26
+ * than another class in the chain because each permission entity already has a
27
+ * fixed generated base, and multiple inheritance isn't available in TypeScript.
28
+ */
29
+ /**
30
+ * Determine whether `user` may Update/Delete a share row they don't own via
31
+ * role permissions. Returns true when the user is the grantor, or when the
32
+ * optional `additional(userId)` predicate says they have some domain-specific
33
+ * management right (e.g., dashboard owner, Owner-level grantee).
34
+ *
35
+ * Use:
36
+ * ```typescript
37
+ * override CheckPermissions(type, throwError) {
38
+ * if ((type === Update || Delete) && this.ActiveUser &&
39
+ * checkShareManagePermission(this.ActiveUser, this.SharedByUserID, (u) => …)) {
40
+ * return true;
41
+ * }
42
+ * return super.CheckPermissions(type, throwError);
43
+ * }
44
+ * ```
45
+ */
46
+ export function checkShareManagePermission(user, grantorUserId, additional) {
47
+ if (grantorUserId && UUIDsEqual(grantorUserId, user.ID))
48
+ return true;
49
+ if (additional && additional(user.ID))
50
+ return true;
51
+ return false;
52
+ }
53
+ /**
54
+ * Post-save share-notification dispatcher for extended permission entities.
55
+ * Call immediately after `super.Save(options)` returns `true`:
56
+ *
57
+ * ```typescript
58
+ * const saved = await super.Save(options);
59
+ * if (saved) {
60
+ * await dispatchShareNotificationAfterSave(this, isNewShare, async (provider, grantorId) => {
61
+ * return { Provider: provider, ContextUser: this.ContextCurrentUser, … };
62
+ * });
63
+ * }
64
+ * return saved;
65
+ * ```
66
+ *
67
+ * Handles the boilerplate each previous implementation repeated:
68
+ * - bail on client-side saves (`ProviderType !== 'Database'`)
69
+ * - bail on updates (`isNewShare === false`)
70
+ * - resolve the effective grantor ID (falls back to ContextCurrentUser.ID)
71
+ * - let `payloadBuilder` return `null` to skip (e.g., Role-grantee ACRs)
72
+ * - fire-and-forget via `void CreateShareNotification(...)` — notification
73
+ * failures never fail the save.
74
+ */
75
+ export async function dispatchShareNotificationAfterSave(entity, isNewShare, grantorUserId, payloadBuilder) {
76
+ const provider = entity.ProviderToUse;
77
+ const isServerSide = provider?.ProviderType === 'Database';
78
+ if (!isServerSide || !isNewShare)
79
+ return;
80
+ const grantorId = grantorUserId ?? entity.ContextCurrentUser?.ID ?? null;
81
+ if (!grantorId)
82
+ return;
83
+ try {
84
+ const input = await payloadBuilder(provider, grantorId);
85
+ if (input)
86
+ void CreateShareNotification(input);
87
+ }
88
+ catch {
89
+ // Defensive: payload builder never fails the save.
90
+ }
91
+ }
92
+ /**
93
+ * Turn `{ view: this.CanRead, edit: this.CanEdit, … }` into `"view, edit"`.
94
+ * Truthy verbs are emitted in declaration order. Replaces the hand-rolled
95
+ * `actionsSummary()` method each sharing entity used to carry.
96
+ */
97
+ export function buildActionsSummary(flags) {
98
+ const parts = [];
99
+ for (const [label, enabled] of Object.entries(flags)) {
100
+ if (enabled)
101
+ parts.push(label);
102
+ }
103
+ return parts.join(', ');
104
+ }
105
+ /**
106
+ * Server-side gate for CREATING a new share. Blocks users who hold role-level
107
+ * `CanCreate` on a sharing entity but don't own the target resource and don't
108
+ * already hold a Share-capable grant on it.
109
+ *
110
+ * Separate from `checkShareManagePermission` (which handles Update/Delete) because
111
+ * Angular's default role-based check can't express "the caller owns the underlying
112
+ * resource" — that requires a resource-specific lookup.
113
+ *
114
+ * Usage in an extended entity's `Save()` override:
115
+ * ```typescript
116
+ * const isNewShare = !this.IsSaved;
117
+ * if (!assertCallerMayCreateShare(this, isNewShare, () => this.callerIsAuthorizedToShare())) {
118
+ * return false; // save is short-circuited; LatestResult carries the reason
119
+ * }
120
+ * const saved = await super.Save(options);
121
+ * ```
122
+ *
123
+ * Returns `true` when the save should proceed, `false` to short-circuit.
124
+ * On `false`, sets `entity.LatestResult` with `Success=false` and a user-visible
125
+ * `Message`, and emits a `LogError` for server logs.
126
+ *
127
+ * Short-circuits to `true` (allows the save) when:
128
+ * - `isNewShare` is false (not a create — Update/Delete handled by CheckPermissions)
129
+ * - provider is not the Database provider (client-side save, already trusted)
130
+ * - `entity.ContextCurrentUser` is missing (defer to downstream auth layers)
131
+ */
132
+ export function assertCallerMayCreateShare(entity, isNewShare, authorized, reason = 'Only the resource owner or someone with Share permission can create this share.') {
133
+ if (!isNewShare)
134
+ return true;
135
+ const provider = entity.ProviderToUse;
136
+ if (provider?.ProviderType !== 'Database')
137
+ return true;
138
+ const user = entity.ContextCurrentUser;
139
+ if (!user)
140
+ return true;
141
+ const result = authorized();
142
+ if (result instanceof Promise) {
143
+ return result.then((ok) => ok || failSave(entity, user, reason));
144
+ }
145
+ return result || failSave(entity, user, reason);
146
+ }
147
+ /**
148
+ * Fail-the-save helper: marks `LatestResult` so the UI sees the reason, logs
149
+ * server-side. Always returns `false` so callers can `return failSave(...)`.
150
+ */
151
+ function failSave(entity, user, reason) {
152
+ LogError(`${entity.constructor.name}: user ${user.ID} (${user.Email ?? user.Name ?? 'unknown'}) blocked from creating share — ${reason}`);
153
+ const latest = entity.LatestResult;
154
+ if (latest) {
155
+ latest.Success = false;
156
+ latest.Message = reason;
157
+ }
158
+ return false;
159
+ }
160
+ /** Re-export for ergonomic `import { EntityPermissionType } from '...'` in subclasses. */
161
+ export { EntityPermissionType, EntitySaveOptions };
162
+ //# sourceMappingURL=BaseShareEntityExtended.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseShareEntityExtended.js","sourceRoot":"","sources":["../../../src/custom/Permissions/BaseShareEntityExtended.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { EntityPermissionType, EntitySaveOptions } from '@memberjunction/core';
2
+ import { MJAccessControlRuleEntity } from '../../generated/entity_subclasses.js';
3
+ /**
4
+ * Extended Access Control Rule entity — same dual-purpose pattern as
5
+ * {@link MJDashboardPermissionEntityExtended}, with two differences:
6
+ *
7
+ * - Uses `GrantedByUserID` instead of `SharedByUserID` (ACR column naming).
8
+ * - Only notifies when `GranteeType === 'User'` and `GranteeID` is populated.
9
+ * Role / Everyone / Public grants don't have a single identifiable recipient,
10
+ * so the payload builder returns `null` to skip.
11
+ *
12
+ * Notifications use the generic `Records` Resource Type from the catalog because
13
+ * ACRs target arbitrary entities — there's no single ResourceType that fits.
14
+ */
15
+ export declare class MJAccessControlRuleEntityExtended extends MJAccessControlRuleEntity {
16
+ CheckPermissions(type: EntityPermissionType, throwError: boolean): boolean;
17
+ Save(options?: EntitySaveOptions): Promise<boolean>;
18
+ private actionsSummary;
19
+ }
20
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
21
+ export declare function LoadMJAccessControlRuleEntityExtended(): void;
22
+ //# sourceMappingURL=MJAccessControlRuleEntityExtended.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJAccessControlRuleEntityExtended.d.ts","sourceRoot":"","sources":["../../../src/custom/Permissions/MJAccessControlRuleEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,oBAAoB,EAAE,iBAAiB,EAAY,MAAM,sBAAsB,CAAC;AAGrG,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAO9E;;;;;;;;;;;GAWG;AACH,qBACa,iCAAkC,SAAQ,yBAAyB;IACnE,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO;IAQpE,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BlE,OAAO,CAAC,cAAc;CASzB;AAED,+EAA+E;AAC/E,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D"}
@@ -0,0 +1,75 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { BaseEntity, EntityPermissionType, Metadata } from '@memberjunction/core';
8
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
9
+ import { MJAccessControlRuleEntity } from '../../generated/entity_subclasses.js';
10
+ import { buildActionsSummary, checkShareManagePermission, dispatchShareNotificationAfterSave, } from './BaseShareEntityExtended.js';
11
+ /**
12
+ * Extended Access Control Rule entity — same dual-purpose pattern as
13
+ * {@link MJDashboardPermissionEntityExtended}, with two differences:
14
+ *
15
+ * - Uses `GrantedByUserID` instead of `SharedByUserID` (ACR column naming).
16
+ * - Only notifies when `GranteeType === 'User'` and `GranteeID` is populated.
17
+ * Role / Everyone / Public grants don't have a single identifiable recipient,
18
+ * so the payload builder returns `null` to skip.
19
+ *
20
+ * Notifications use the generic `Records` Resource Type from the catalog because
21
+ * ACRs target arbitrary entities — there's no single ResourceType that fits.
22
+ */
23
+ let MJAccessControlRuleEntityExtended = class MJAccessControlRuleEntityExtended extends MJAccessControlRuleEntity {
24
+ CheckPermissions(type, throwError) {
25
+ if (type === EntityPermissionType.Update || type === EntityPermissionType.Delete) {
26
+ const user = this.ActiveUser;
27
+ if (user && checkShareManagePermission(user, this.GrantedByUserID))
28
+ return true;
29
+ }
30
+ return super.CheckPermissions(type, throwError);
31
+ }
32
+ async Save(options) {
33
+ const isNewShare = !this.IsSaved;
34
+ const saved = await super.Save(options);
35
+ if (saved) {
36
+ await dispatchShareNotificationAfterSave(this, isNewShare, this.GrantedByUserID, (provider, grantorId) => {
37
+ // Only user grantees get individual notifications.
38
+ if (this.GranteeType !== 'User' || !this.GranteeID)
39
+ return null;
40
+ const entityInfo = new Metadata().Entities.find((e) => UUIDsEqual(e.ID, this.EntityID));
41
+ return {
42
+ Provider: provider,
43
+ ContextUser: this.ContextCurrentUser,
44
+ GrantorUserID: grantorId,
45
+ GranteeUserID: this.GranteeID,
46
+ ResourceTypeLabel: entityInfo?.Name ?? 'Record',
47
+ ResourceTypeName: 'Records',
48
+ ResourceName: null,
49
+ ResourceRecordID: this.RecordID,
50
+ ActionsSummary: this.actionsSummary(),
51
+ ExtraConfiguration: { AccessControlRuleID: this.ID, EntityID: this.EntityID },
52
+ };
53
+ });
54
+ }
55
+ return saved;
56
+ }
57
+ actionsSummary() {
58
+ return buildActionsSummary({
59
+ view: this.CanRead,
60
+ create: this.CanCreate,
61
+ edit: this.CanUpdate,
62
+ delete: this.CanDelete,
63
+ share: this.CanShare,
64
+ });
65
+ }
66
+ };
67
+ MJAccessControlRuleEntityExtended = __decorate([
68
+ RegisterClass(BaseEntity, 'MJ: Access Control Rules')
69
+ ], MJAccessControlRuleEntityExtended);
70
+ export { MJAccessControlRuleEntityExtended };
71
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
72
+ export function LoadMJAccessControlRuleEntityExtended() {
73
+ // intentionally empty
74
+ }
75
+ //# sourceMappingURL=MJAccessControlRuleEntityExtended.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJAccessControlRuleEntityExtended.js","sourceRoot":"","sources":["../../../src/custom/Permissions/MJAccessControlRuleEntityExtended.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAqB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EACH,mBAAmB,EACnB,0BAA0B,EAC1B,kCAAkC,GACrC,MAAM,2BAA2B,CAAC;AAEnC;;;;;;;;;;;GAWG;AAEI,IAAM,iCAAiC,GAAvC,MAAM,iCAAkC,SAAQ,yBAAyB;IACnE,gBAAgB,CAAC,IAA0B,EAAE,UAAmB;QACrE,IAAI,IAAI,KAAK,oBAAoB,CAAC,MAAM,IAAI,IAAI,KAAK,oBAAoB,CAAC,MAAM,EAAE,CAAC;YAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;YAC7B,IAAI,IAAI,IAAI,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC;gBAAE,OAAO,IAAI,CAAC;QACpF,CAAC;QACD,OAAO,KAAK,CAAC,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAC,OAA2B;QAC3C,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,kCAAkC,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE;gBACrG,mDAAmD;gBACnD,IAAI,IAAI,CAAC,WAAW,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS;oBAAE,OAAO,IAAI,CAAC;gBAEhE,MAAM,UAAU,GAAG,IAAI,QAAQ,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACxF,OAAO;oBACH,QAAQ,EAAE,QAAQ;oBAClB,WAAW,EAAE,IAAI,CAAC,kBAAkB;oBACpC,aAAa,EAAE,SAAS;oBACxB,aAAa,EAAE,IAAI,CAAC,SAAS;oBAC7B,iBAAiB,EAAE,UAAU,EAAE,IAAI,IAAI,QAAQ;oBAC/C,gBAAgB,EAAE,SAAS;oBAC3B,YAAY,EAAE,IAAI;oBAClB,gBAAgB,EAAE,IAAI,CAAC,QAAQ;oBAC/B,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE;oBACrC,kBAAkB,EAAE,EAAE,mBAAmB,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;iBAChF,CAAC;YACN,CAAC,CAAC,CAAC;QACP,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,cAAc;QAClB,OAAO,mBAAmB,CAAC;YACvB,IAAI,EAAE,IAAI,CAAC,OAAO;YAClB,MAAM,EAAE,IAAI,CAAC,SAAS;YACtB,IAAI,EAAE,IAAI,CAAC,SAAS;YACpB,MAAM,EAAE,IAAI,CAAC,SAAS;YACtB,KAAK,EAAE,IAAI,CAAC,QAAQ;SACvB,CAAC,CAAC;IACP,CAAC;CACJ,CAAA;AA5CY,iCAAiC;IAD7C,aAAa,CAAC,UAAU,EAAE,0BAA0B,CAAC;GACzC,iCAAiC,CA4C7C;;AAED,+EAA+E;AAC/E,MAAM,UAAU,qCAAqC;IACjD,sBAAsB;AAC1B,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { EntityPermissionType, EntitySaveOptions } from '@memberjunction/core';
2
+ import { MJArtifactPermissionEntity } from '../../generated/entity_subclasses.js';
3
+ /**
4
+ * Extended Artifact Permission entity — same dual-purpose pattern as
5
+ * {@link MJDashboardPermissionEntityExtended}. See that class for rationale.
6
+ */
7
+ export declare class MJArtifactPermissionEntityExtended extends MJArtifactPermissionEntity {
8
+ CheckPermissions(type: EntityPermissionType, throwError: boolean): boolean;
9
+ Save(options?: EntitySaveOptions): Promise<boolean>;
10
+ private actionsSummary;
11
+ /**
12
+ * Authorization for CREATING a new ArtifactPermission row.
13
+ * Same pattern as MJDashboardPermissionEntityExtended.callerMayShareDashboard
14
+ * but without an in-memory engine — we fetch the artifact and the caller's
15
+ * existing grant row directly.
16
+ */
17
+ private callerMayShareArtifact;
18
+ private fetchArtifactName;
19
+ }
20
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
21
+ export declare function LoadMJArtifactPermissionEntityExtended(): void;
22
+ //# sourceMappingURL=MJArtifactPermissionEntityExtended.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJArtifactPermissionEntityExtended.d.ts","sourceRoot":"","sources":["../../../src/custom/Permissions/MJArtifactPermissionEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,oBAAoB,EAAE,iBAAiB,EAAW,MAAM,sBAAsB,CAAC;AAGpG,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAQ/E;;;GAGG;AACH,qBACa,kCAAmC,SAAQ,0BAA0B;IACrE,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO;IAQpE,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgClE,OAAO,CAAC,cAAc;IAStB;;;;;OAKG;YACW,sBAAsB;YA6BtB,iBAAiB;CAWlC;AAED,+EAA+E;AAC/E,wBAAgB,sCAAsC,IAAI,IAAI,CAE7D"}
@@ -0,0 +1,114 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { BaseEntity, EntityPermissionType, RunView } from '@memberjunction/core';
8
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
9
+ import { MJArtifactPermissionEntity } from '../../generated/entity_subclasses.js';
10
+ import { assertCallerMayCreateShare, buildActionsSummary, checkShareManagePermission, dispatchShareNotificationAfterSave, } from './BaseShareEntityExtended.js';
11
+ /**
12
+ * Extended Artifact Permission entity — same dual-purpose pattern as
13
+ * {@link MJDashboardPermissionEntityExtended}. See that class for rationale.
14
+ */
15
+ let MJArtifactPermissionEntityExtended = class MJArtifactPermissionEntityExtended extends MJArtifactPermissionEntity {
16
+ CheckPermissions(type, throwError) {
17
+ if (type === EntityPermissionType.Update || type === EntityPermissionType.Delete) {
18
+ const user = this.ActiveUser;
19
+ if (user && checkShareManagePermission(user, this.SharedByUserID))
20
+ return true;
21
+ }
22
+ return super.CheckPermissions(type, throwError);
23
+ }
24
+ async Save(options) {
25
+ const isNewShare = !this.IsSaved;
26
+ const allowed = await assertCallerMayCreateShare(this, isNewShare, () => this.callerMayShareArtifact(), 'Only the artifact owner or someone with Share permission on this artifact can create a new share.');
27
+ if (!allowed)
28
+ return false;
29
+ const saved = await super.Save(options);
30
+ if (saved) {
31
+ await dispatchShareNotificationAfterSave(this, isNewShare, this.SharedByUserID, async (provider, grantorId) => {
32
+ // The Artifact view doesn't denormalize Name onto the permission row — look it up.
33
+ const artifactName = await this.fetchArtifactName();
34
+ return {
35
+ Provider: provider,
36
+ ContextUser: this.ContextCurrentUser,
37
+ GrantorUserID: grantorId,
38
+ GranteeUserID: this.UserID,
39
+ ResourceTypeLabel: 'Artifact',
40
+ ResourceTypeName: 'Artifacts',
41
+ ResourceName: artifactName,
42
+ ResourceRecordID: this.ArtifactID,
43
+ ActionsSummary: this.actionsSummary(),
44
+ ExtraConfiguration: { PermissionID: this.ID },
45
+ };
46
+ });
47
+ }
48
+ return saved;
49
+ }
50
+ actionsSummary() {
51
+ return buildActionsSummary({
52
+ view: this.CanRead,
53
+ edit: this.CanEdit,
54
+ delete: this.CanDelete,
55
+ share: this.CanShare,
56
+ });
57
+ }
58
+ /**
59
+ * Authorization for CREATING a new ArtifactPermission row.
60
+ * Same pattern as MJDashboardPermissionEntityExtended.callerMayShareDashboard
61
+ * but without an in-memory engine — we fetch the artifact and the caller's
62
+ * existing grant row directly.
63
+ */
64
+ async callerMayShareArtifact() {
65
+ const user = this.ContextCurrentUser;
66
+ if (!user)
67
+ return false;
68
+ const rv = new RunView();
69
+ // One round-trip: fetch the artifact's owner AND any existing Share-capable
70
+ // permission row for this caller on this artifact.
71
+ const [ownerResult, grantResult] = await rv.RunViews([
72
+ {
73
+ EntityName: 'MJ: Artifacts',
74
+ ExtraFilter: `ID='${this.ArtifactID}'`,
75
+ Fields: ['ID', 'UserID'],
76
+ MaxRows: 1,
77
+ ResultType: 'simple',
78
+ },
79
+ {
80
+ EntityName: 'MJ: Artifact Permissions',
81
+ ExtraFilter: `ArtifactID='${this.ArtifactID}' AND UserID='${user.ID}' AND CanShare=1`,
82
+ Fields: ['ID'],
83
+ MaxRows: 1,
84
+ ResultType: 'simple',
85
+ },
86
+ ]);
87
+ const ownerId = ownerResult.Success
88
+ ? ownerResult.Results?.[0]?.UserID
89
+ : undefined;
90
+ if (ownerId && UUIDsEqual(ownerId, user.ID))
91
+ return true;
92
+ return grantResult.Success && (grantResult.Results?.length ?? 0) > 0;
93
+ }
94
+ async fetchArtifactName() {
95
+ const rv = new RunView();
96
+ const result = await rv.RunView({
97
+ EntityName: 'MJ: Artifacts',
98
+ ExtraFilter: `ID='${this.ArtifactID}'`,
99
+ Fields: ['ID', 'Name'],
100
+ MaxRows: 1,
101
+ ResultType: 'simple',
102
+ });
103
+ return result.Success ? result.Results?.[0]?.Name ?? null : null;
104
+ }
105
+ };
106
+ MJArtifactPermissionEntityExtended = __decorate([
107
+ RegisterClass(BaseEntity, 'MJ: Artifact Permissions')
108
+ ], MJArtifactPermissionEntityExtended);
109
+ export { MJArtifactPermissionEntityExtended };
110
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
111
+ export function LoadMJArtifactPermissionEntityExtended() {
112
+ // intentionally empty
113
+ }
114
+ //# sourceMappingURL=MJArtifactPermissionEntityExtended.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJArtifactPermissionEntityExtended.js","sourceRoot":"","sources":["../../../src/custom/Permissions/MJArtifactPermissionEntityExtended.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { EntityPermissionType, EntitySaveOptions } from '@memberjunction/core';
2
+ import { MJCollectionPermissionEntity } from '../../generated/entity_subclasses.js';
3
+ /**
4
+ * Extended Collection Permission entity — same dual-purpose pattern as
5
+ * {@link MJDashboardPermissionEntityExtended}. See that class for rationale.
6
+ *
7
+ * Note: Collections have no entry in the `MJ: Resource Type` catalog, so
8
+ * `ResourceTypeName` is omitted and the notification's `ResourceTypeID` is
9
+ * left null. The bell icon still shows the title/message; click-through
10
+ * deep-linking can be added later if a Collection ResourceType is seeded.
11
+ */
12
+ export declare class MJCollectionPermissionEntityExtended extends MJCollectionPermissionEntity {
13
+ CheckPermissions(type: EntityPermissionType, throwError: boolean): boolean;
14
+ Save(options?: EntitySaveOptions): Promise<boolean>;
15
+ private actionsSummary;
16
+ /**
17
+ * Authorization for CREATING a new CollectionPermission row. Caller must
18
+ * be the collection owner or hold an existing Share-capable grant. Same
19
+ * two-query pattern as {@link MJArtifactPermissionEntityExtended.callerMayShareArtifact}.
20
+ */
21
+ private callerMayShareCollection;
22
+ }
23
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
24
+ export declare function LoadMJCollectionPermissionEntityExtended(): void;
25
+ //# sourceMappingURL=MJCollectionPermissionEntityExtended.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJCollectionPermissionEntityExtended.d.ts","sourceRoot":"","sources":["../../../src/custom/Permissions/MJCollectionPermissionEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,oBAAoB,EAAE,iBAAiB,EAAW,MAAM,sBAAsB,CAAC;AAGpG,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAQjF;;;;;;;;GAQG;AACH,qBACa,oCAAqC,SAAQ,4BAA4B;IACzE,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO;IAQpE,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BlE,OAAO,CAAC,cAAc;IAStB;;;;OAIG;YACW,wBAAwB;CA0BzC;AAED,+EAA+E;AAC/E,wBAAgB,wCAAwC,IAAI,IAAI,CAE/D"}