@memberjunction/core-entities 5.29.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 (105) 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/PermissionEngine.d.ts +142 -0
  86. package/dist/engines/PermissionEngine.d.ts.map +1 -0
  87. package/dist/engines/PermissionEngine.js +343 -0
  88. package/dist/engines/PermissionEngine.js.map +1 -0
  89. package/dist/engines/UserInfoEngine.d.ts +6 -1
  90. package/dist/engines/UserInfoEngine.d.ts.map +1 -1
  91. package/dist/engines/UserInfoEngine.js +21 -5
  92. package/dist/engines/UserInfoEngine.js.map +1 -1
  93. package/dist/engines/conversations.d.ts +35 -0
  94. package/dist/engines/conversations.d.ts.map +1 -1
  95. package/dist/engines/conversations.js +103 -16
  96. package/dist/engines/conversations.js.map +1 -1
  97. package/dist/generated/entity_subclasses.d.ts +579 -52
  98. package/dist/generated/entity_subclasses.d.ts.map +1 -1
  99. package/dist/generated/entity_subclasses.js +697 -66
  100. package/dist/generated/entity_subclasses.js.map +1 -1
  101. package/dist/index.d.ts +4 -0
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +8 -0
  104. package/dist/index.js.map +1 -1
  105. package/package.json +5 -5
@@ -0,0 +1,101 @@
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 { MJCollectionPermissionEntity } from '../../generated/entity_subclasses.js';
10
+ import { assertCallerMayCreateShare, buildActionsSummary, checkShareManagePermission, dispatchShareNotificationAfterSave, } from './BaseShareEntityExtended.js';
11
+ /**
12
+ * Extended Collection Permission entity — same dual-purpose pattern as
13
+ * {@link MJDashboardPermissionEntityExtended}. See that class for rationale.
14
+ *
15
+ * Note: Collections have no entry in the `MJ: Resource Type` catalog, so
16
+ * `ResourceTypeName` is omitted and the notification's `ResourceTypeID` is
17
+ * left null. The bell icon still shows the title/message; click-through
18
+ * deep-linking can be added later if a Collection ResourceType is seeded.
19
+ */
20
+ let MJCollectionPermissionEntityExtended = class MJCollectionPermissionEntityExtended extends MJCollectionPermissionEntity {
21
+ CheckPermissions(type, throwError) {
22
+ if (type === EntityPermissionType.Update || type === EntityPermissionType.Delete) {
23
+ const user = this.ActiveUser;
24
+ if (user && checkShareManagePermission(user, this.SharedByUserID))
25
+ return true;
26
+ }
27
+ return super.CheckPermissions(type, throwError);
28
+ }
29
+ async Save(options) {
30
+ const isNewShare = !this.IsSaved;
31
+ const allowed = await assertCallerMayCreateShare(this, isNewShare, () => this.callerMayShareCollection(), 'Only the collection owner or someone with Share permission on this collection can create a new share.');
32
+ if (!allowed)
33
+ return false;
34
+ const saved = await super.Save(options);
35
+ if (saved) {
36
+ await dispatchShareNotificationAfterSave(this, isNewShare, this.SharedByUserID, (provider, grantorId) => ({
37
+ Provider: provider,
38
+ ContextUser: this.ContextCurrentUser,
39
+ GrantorUserID: grantorId,
40
+ GranteeUserID: this.UserID,
41
+ ResourceTypeLabel: 'Collection',
42
+ // No ResourceTypeName — Collections aren't in the Resource Type catalog
43
+ ResourceName: this.Collection ?? null,
44
+ ResourceRecordID: this.CollectionID,
45
+ ActionsSummary: this.actionsSummary(),
46
+ ExtraConfiguration: { PermissionID: this.ID },
47
+ }));
48
+ }
49
+ return saved;
50
+ }
51
+ actionsSummary() {
52
+ return buildActionsSummary({
53
+ view: this.CanRead,
54
+ edit: this.CanEdit,
55
+ delete: this.CanDelete,
56
+ share: this.CanShare,
57
+ });
58
+ }
59
+ /**
60
+ * Authorization for CREATING a new CollectionPermission row. Caller must
61
+ * be the collection owner or hold an existing Share-capable grant. Same
62
+ * two-query pattern as {@link MJArtifactPermissionEntityExtended.callerMayShareArtifact}.
63
+ */
64
+ async callerMayShareCollection() {
65
+ const user = this.ContextCurrentUser;
66
+ if (!user)
67
+ return false;
68
+ const rv = new RunView();
69
+ const [ownerResult, grantResult] = await rv.RunViews([
70
+ {
71
+ EntityName: 'MJ: Collections',
72
+ ExtraFilter: `ID='${this.CollectionID}'`,
73
+ Fields: ['ID', 'OwnerID'],
74
+ MaxRows: 1,
75
+ ResultType: 'simple',
76
+ },
77
+ {
78
+ EntityName: 'MJ: Collection Permissions',
79
+ ExtraFilter: `CollectionID='${this.CollectionID}' AND UserID='${user.ID}' AND CanShare=1`,
80
+ Fields: ['ID'],
81
+ MaxRows: 1,
82
+ ResultType: 'simple',
83
+ },
84
+ ]);
85
+ const ownerId = ownerResult.Success
86
+ ? ownerResult.Results?.[0]?.OwnerID
87
+ : undefined;
88
+ if (ownerId && UUIDsEqual(ownerId, user.ID))
89
+ return true;
90
+ return grantResult.Success && (grantResult.Results?.length ?? 0) > 0;
91
+ }
92
+ };
93
+ MJCollectionPermissionEntityExtended = __decorate([
94
+ RegisterClass(BaseEntity, 'MJ: Collection Permissions')
95
+ ], MJCollectionPermissionEntityExtended);
96
+ export { MJCollectionPermissionEntityExtended };
97
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
98
+ export function LoadMJCollectionPermissionEntityExtended() {
99
+ // intentionally empty
100
+ }
101
+ //# sourceMappingURL=MJCollectionPermissionEntityExtended.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJCollectionPermissionEntityExtended.js","sourceRoot":"","sources":["../../../src/custom/Permissions/MJCollectionPermissionEntityExtended.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { EntityPermissionType, EntitySaveOptions } from '@memberjunction/core';
2
+ import { MJDashboardPermissionEntity } from '../../generated/entity_subclasses.js';
3
+ /**
4
+ * Extended Dashboard Permission entity. Adds two behaviors on top of the
5
+ * generated base:
6
+ *
7
+ * 1. **CheckPermissions override** — grantor and dashboard owner can always
8
+ * Update/Delete their own grant. Without this, UI/Developer users can't
9
+ * revoke their own shares because neither role has `CanDelete` on
10
+ * `MJ: Dashboard Permissions`. The owner fallback also covers the
11
+ * `SharedByUserID IS NULL` legacy case.
12
+ *
13
+ * 2. **Save override** — notifies the grantee via the shared `CreateShareNotification`
14
+ * pipeline so `NotificationEngine` honors their in-app / email / SMS
15
+ * preferences uniformly.
16
+ */
17
+ export declare class MJDashboardPermissionEntityExtended extends MJDashboardPermissionEntity {
18
+ CheckPermissions(type: EntityPermissionType, throwError: boolean): boolean;
19
+ Save(options?: EntitySaveOptions): Promise<boolean>;
20
+ private isDashboardOwner;
21
+ /**
22
+ * Authorization for CREATING a new DashboardPermission row. Matches the
23
+ * `MJResourcePermissionEntityExtended.callerMayGrantShare` pattern:
24
+ * caller is either the dashboard owner, or holds an existing DashboardPermission
25
+ * on the same dashboard with `CanShare=true`.
26
+ */
27
+ private callerMayShareDashboard;
28
+ private actionsSummary;
29
+ }
30
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
31
+ export declare function LoadMJDashboardPermissionEntityExtended(): void;
32
+ //# sourceMappingURL=MJDashboardPermissionEntityExtended.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJDashboardPermissionEntityExtended.d.ts","sourceRoot":"","sources":["../../../src/custom/Permissions/MJDashboardPermissionEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAI3F,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;AAQhF;;;;;;;;;;;;;GAaG;AACH,qBACa,mCAAoC,SAAQ,2BAA2B;IACvE,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO;IAUpE,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BlE,OAAO,CAAC,gBAAgB;IAKxB;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,cAAc;CAQzB;AAED,+EAA+E;AAC/E,wBAAgB,uCAAuC,IAAI,IAAI,CAE9D"}
@@ -0,0 +1,95 @@
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 } from '@memberjunction/core';
8
+ import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
9
+ import { DashboardEngine } from '../../engines/dashboards.js';
10
+ import { MJDashboardPermissionEntity } from '../../generated/entity_subclasses.js';
11
+ import { assertCallerMayCreateShare, buildActionsSummary, checkShareManagePermission, dispatchShareNotificationAfterSave, } from './BaseShareEntityExtended.js';
12
+ /**
13
+ * Extended Dashboard Permission entity. Adds two behaviors on top of the
14
+ * generated base:
15
+ *
16
+ * 1. **CheckPermissions override** — grantor and dashboard owner can always
17
+ * Update/Delete their own grant. Without this, UI/Developer users can't
18
+ * revoke their own shares because neither role has `CanDelete` on
19
+ * `MJ: Dashboard Permissions`. The owner fallback also covers the
20
+ * `SharedByUserID IS NULL` legacy case.
21
+ *
22
+ * 2. **Save override** — notifies the grantee via the shared `CreateShareNotification`
23
+ * pipeline so `NotificationEngine` honors their in-app / email / SMS
24
+ * preferences uniformly.
25
+ */
26
+ let MJDashboardPermissionEntityExtended = class MJDashboardPermissionEntityExtended extends MJDashboardPermissionEntity {
27
+ CheckPermissions(type, throwError) {
28
+ if (type === EntityPermissionType.Update || type === EntityPermissionType.Delete) {
29
+ const user = this.ActiveUser;
30
+ if (user && checkShareManagePermission(user, this.SharedByUserID, (userId) => this.isDashboardOwner(userId))) {
31
+ return true;
32
+ }
33
+ }
34
+ return super.CheckPermissions(type, throwError);
35
+ }
36
+ async Save(options) {
37
+ const isNewShare = !this.IsSaved;
38
+ const allowed = await assertCallerMayCreateShare(this, isNewShare, () => this.callerMayShareDashboard(), 'Only the dashboard owner or someone with Share permission on this dashboard can create a new share.');
39
+ if (!allowed)
40
+ return false;
41
+ const saved = await super.Save(options);
42
+ if (saved) {
43
+ await dispatchShareNotificationAfterSave(this, isNewShare, this.SharedByUserID, (provider, grantorId) => ({
44
+ Provider: provider,
45
+ ContextUser: this.ContextCurrentUser,
46
+ GrantorUserID: grantorId,
47
+ GranteeUserID: this.UserID,
48
+ ResourceTypeLabel: 'Dashboard',
49
+ ResourceTypeName: 'Dashboards',
50
+ ResourceName: this.Dashboard ?? null,
51
+ ResourceRecordID: this.DashboardID,
52
+ ActionsSummary: this.actionsSummary(),
53
+ ExtraConfiguration: { PermissionID: this.ID },
54
+ }));
55
+ }
56
+ return saved;
57
+ }
58
+ isDashboardOwner(userId) {
59
+ const dashboard = DashboardEngine.Instance.Dashboards.find((d) => UUIDsEqual(d.ID, this.DashboardID));
60
+ return !!dashboard?.UserID && UUIDsEqual(dashboard.UserID, userId);
61
+ }
62
+ /**
63
+ * Authorization for CREATING a new DashboardPermission row. Matches the
64
+ * `MJResourcePermissionEntityExtended.callerMayGrantShare` pattern:
65
+ * caller is either the dashboard owner, or holds an existing DashboardPermission
66
+ * on the same dashboard with `CanShare=true`.
67
+ */
68
+ callerMayShareDashboard() {
69
+ const user = this.ContextCurrentUser;
70
+ if (!user)
71
+ return false;
72
+ if (this.isDashboardOwner(user.ID))
73
+ return true;
74
+ return DashboardEngine.Instance.DashboardPermissions.some((p) => UUIDsEqual(p.DashboardID, this.DashboardID) &&
75
+ UUIDsEqual(p.UserID, user.ID) &&
76
+ p.CanShare === true);
77
+ }
78
+ actionsSummary() {
79
+ return buildActionsSummary({
80
+ view: this.CanRead,
81
+ edit: this.CanEdit,
82
+ delete: this.CanDelete,
83
+ share: this.CanShare,
84
+ });
85
+ }
86
+ };
87
+ MJDashboardPermissionEntityExtended = __decorate([
88
+ RegisterClass(BaseEntity, 'MJ: Dashboard Permissions')
89
+ ], MJDashboardPermissionEntityExtended);
90
+ export { MJDashboardPermissionEntityExtended };
91
+ /** Tree-shaking prevention — referenced from the custom/Permissions barrel. */
92
+ export function LoadMJDashboardPermissionEntityExtended() {
93
+ // intentionally empty
94
+ }
95
+ //# sourceMappingURL=MJDashboardPermissionEntityExtended.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MJDashboardPermissionEntityExtended.js","sourceRoot":"","sources":["../../../src/custom/Permissions/MJDashboardPermissionEntityExtended.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export * from './MJDashboardPermissionEntityExtended.js';
2
+ export * from './MJCollectionPermissionEntityExtended.js';
3
+ export * from './MJArtifactPermissionEntityExtended.js';
4
+ export * from './MJAccessControlRuleEntityExtended.js';
5
+ export * from './shareNotification.js';
6
+ export * from './BaseShareEntityExtended.js';
7
+ /**
8
+ * Forces all extended permission entity classes to load so their @RegisterClass
9
+ * decorators fire and override the generated entity classes in the ClassFactory.
10
+ * Called from `@memberjunction/core-entities` barrel on package import.
11
+ */
12
+ export declare function LoadPermissionEntityExtensions(): void;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/custom/Permissions/index.ts"],"names":[],"mappings":"AAAA,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AACpD,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAO1C;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAKrD"}
@@ -0,0 +1,22 @@
1
+ export * from './MJDashboardPermissionEntityExtended.js';
2
+ export * from './MJCollectionPermissionEntityExtended.js';
3
+ export * from './MJArtifactPermissionEntityExtended.js';
4
+ export * from './MJAccessControlRuleEntityExtended.js';
5
+ export * from './shareNotification.js';
6
+ export * from './BaseShareEntityExtended.js';
7
+ import { LoadMJDashboardPermissionEntityExtended } from './MJDashboardPermissionEntityExtended.js';
8
+ import { LoadMJCollectionPermissionEntityExtended } from './MJCollectionPermissionEntityExtended.js';
9
+ import { LoadMJArtifactPermissionEntityExtended } from './MJArtifactPermissionEntityExtended.js';
10
+ import { LoadMJAccessControlRuleEntityExtended } from './MJAccessControlRuleEntityExtended.js';
11
+ /**
12
+ * Forces all extended permission entity classes to load so their @RegisterClass
13
+ * decorators fire and override the generated entity classes in the ClassFactory.
14
+ * Called from `@memberjunction/core-entities` barrel on package import.
15
+ */
16
+ export function LoadPermissionEntityExtensions() {
17
+ LoadMJDashboardPermissionEntityExtended();
18
+ LoadMJCollectionPermissionEntityExtended();
19
+ LoadMJArtifactPermissionEntityExtended();
20
+ LoadMJAccessControlRuleEntityExtended();
21
+ }
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/custom/Permissions/index.ts"],"names":[],"mappings":"AAAA,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AACpD,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAE1C,OAAO,EAAE,uCAAuC,EAAE,MAAM,uCAAuC,CAAC;AAChG,OAAO,EAAE,wCAAwC,EAAE,MAAM,wCAAwC,CAAC;AAClG,OAAO,EAAE,sCAAsC,EAAE,MAAM,sCAAsC,CAAC;AAC9F,OAAO,EAAE,qCAAqC,EAAE,MAAM,qCAAqC,CAAC;AAE5F;;;;GAIG;AACH,MAAM,UAAU,8BAA8B;IAC1C,uCAAuC,EAAE,CAAC;IAC1C,wCAAwC,EAAE,CAAC;IAC3C,sCAAsC,EAAE,CAAC;IACzC,qCAAqC,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { IMetadataProvider } from '@memberjunction/core';
2
+ /**
3
+ * Input to {@link CreateShareNotification} — everything needed to deliver a
4
+ * share notification to the grantee of a newly-created permission record.
5
+ */
6
+ export interface ShareNotificationInput {
7
+ /** Metadata provider — must be the Database provider (server-side). */
8
+ Provider: IMetadataProvider;
9
+ /** Context user to authorize the save. */
10
+ ContextUser: import('@memberjunction/core').UserInfo;
11
+ /** ID of the user who granted the share — the `from`. */
12
+ GrantorUserID: string;
13
+ /** ID of the user receiving the share — the `to` and the notification recipient. */
14
+ GranteeUserID: string;
15
+ /**
16
+ * Human-readable resource type label used in notification text (e.g., "Dashboard",
17
+ * "Collection"). Distinct from `ResourceTypeName` below — this is purely cosmetic.
18
+ */
19
+ ResourceTypeLabel: string;
20
+ /**
21
+ * Optional name from the {@link MJResourceTypeEntity} catalog (e.g., `"Dashboards"`,
22
+ * `"Artifacts"`, `"Records"`). When provided AND found in the catalog, the resolved
23
+ * ResourceType.ID is written to `MJUserNotification.ResourceTypeID` so the bell icon
24
+ * can deep-link via the matching `DriverClass`.
25
+ */
26
+ ResourceTypeName?: string;
27
+ /** Optional display name for the shared resource. */
28
+ ResourceName?: string | null;
29
+ /** Primary key of the shared resource. */
30
+ ResourceRecordID: string;
31
+ /** Short sentence describing what was granted. Goes in the notification body. */
32
+ ActionsSummary?: string;
33
+ /** Extra JSON payload for the notification (e.g., PermissionID, DomainName). */
34
+ ExtraConfiguration?: Record<string, unknown>;
35
+ /**
36
+ * Optional override for the notification title. When omitted, the dispatcher
37
+ * auto-generates `"<grantor> shared <resource> with you"`. Used by
38
+ * access-request workflow notifications (e.g., "New request for access to …")
39
+ * that don't match the default share-event phrasing.
40
+ */
41
+ Title?: string;
42
+ /**
43
+ * Optional override for the notification message body. When omitted, the
44
+ * dispatcher auto-generates a short sentence from `ActionsSummary`.
45
+ */
46
+ Message?: string;
47
+ }
48
+ /**
49
+ * Registerable handler that actually delivers a share notification. Declared
50
+ * here so server-side code (e.g., `@memberjunction/notifications`) can plug in
51
+ * richer delivery (in-app + email + SMS via `NotificationEngine`) without
52
+ * `@memberjunction/core-entities` having to import the notifications package —
53
+ * that direction would create a circular dependency.
54
+ */
55
+ export type ShareNotificationHandler = (input: ShareNotificationInput) => Promise<boolean>;
56
+ /**
57
+ * Register a custom dispatcher (e.g., one backed by `NotificationEngine.SendNotification`).
58
+ * Typically called once at server startup. Subsequent calls replace the handler.
59
+ * Passing `null` restores the default in-app-only behavior.
60
+ */
61
+ export declare function RegisterShareNotificationHandler(handler: ShareNotificationHandler | null): void;
62
+ /**
63
+ * Create and deliver a share notification. If a custom handler has been
64
+ * registered via {@link RegisterShareNotificationHandler}, it's called first;
65
+ * otherwise (and as a fallback on handler error) we write an in-app
66
+ * `MJ: User Notifications` row directly.
67
+ *
68
+ * Returns `true` when the notification was delivered successfully. Never
69
+ * throws — sharing succeeds even if notification delivery fails.
70
+ */
71
+ export declare function CreateShareNotification(input: ShareNotificationInput): Promise<boolean>;
72
+ //# sourceMappingURL=shareNotification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shareNotification.d.ts","sourceRoot":"","sources":["../../../src/custom/Permissions/shareNotification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAY,MAAM,sBAAsB,CAAC;AAKnE;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACnC,uEAAuE;IACvE,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,0CAA0C;IAC1C,WAAW,EAAE,OAAO,sBAAsB,EAAE,QAAQ,CAAC;IACrD,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,0CAA0C;IAC1C,gBAAgB,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAI3F;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,IAAI,CAE/F;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB7F"}
@@ -0,0 +1,98 @@
1
+ import { LogError } from '@memberjunction/core';
2
+ import { ResourcePermissionEngine } from '../ResourcePermissions/ResourcePermissionEngine.js';
3
+ let registeredHandler = null;
4
+ /**
5
+ * Register a custom dispatcher (e.g., one backed by `NotificationEngine.SendNotification`).
6
+ * Typically called once at server startup. Subsequent calls replace the handler.
7
+ * Passing `null` restores the default in-app-only behavior.
8
+ */
9
+ export function RegisterShareNotificationHandler(handler) {
10
+ registeredHandler = handler;
11
+ }
12
+ /**
13
+ * Create and deliver a share notification. If a custom handler has been
14
+ * registered via {@link RegisterShareNotificationHandler}, it's called first;
15
+ * otherwise (and as a fallback on handler error) we write an in-app
16
+ * `MJ: User Notifications` row directly.
17
+ *
18
+ * Returns `true` when the notification was delivered successfully. Never
19
+ * throws — sharing succeeds even if notification delivery fails.
20
+ */
21
+ export async function CreateShareNotification(input) {
22
+ // Self-shares are a no-op (guards against duplicate-notification loops on seeded data).
23
+ if (input.GrantorUserID === input.GranteeUserID)
24
+ return true;
25
+ if (!input.GranteeUserID || !input.ResourceRecordID)
26
+ return true;
27
+ if (registeredHandler) {
28
+ try {
29
+ return await registeredHandler(input);
30
+ }
31
+ catch (err) {
32
+ LogError(`Share notification handler threw; falling back to in-app only delivery: ${err instanceof Error ? err.message : String(err)}`);
33
+ // Fall through to default implementation below
34
+ }
35
+ }
36
+ return defaultInAppDispatch(input);
37
+ }
38
+ /**
39
+ * Default dispatcher: saves a single `MJ: User Notifications` row. No email /
40
+ * SMS delivery. Used when no custom handler is registered (e.g., on the client,
41
+ * or before the server startup wires up the NotificationEngine handler).
42
+ */
43
+ async function defaultInAppDispatch(input) {
44
+ try {
45
+ const grantor = await input.Provider.GetEntityObject('MJ: Users', input.ContextUser);
46
+ await grantor.Load(input.GrantorUserID);
47
+ const grantorName = grantor.Name || grantor.Email || 'Another user';
48
+ const notification = await input.Provider.GetEntityObject('MJ: User Notifications', input.ContextUser);
49
+ const resourceLabel = input.ResourceName
50
+ ? `"${input.ResourceName}"`
51
+ : `a ${input.ResourceTypeLabel.toLowerCase()}`;
52
+ notification.UserID = input.GranteeUserID;
53
+ notification.Title = input.Title ?? `${grantorName} shared ${resourceLabel} with you`;
54
+ notification.Message =
55
+ input.Message ??
56
+ (input.ActionsSummary
57
+ ? `${grantorName} shared ${resourceLabel} with you (${input.ActionsSummary}).`
58
+ : `${grantorName} shared ${resourceLabel} with you.`);
59
+ notification.Unread = true;
60
+ const resolvedTypeId = await resolveResourceTypeId(input.ResourceTypeName, input.ContextUser);
61
+ if (resolvedTypeId)
62
+ notification.ResourceTypeID = resolvedTypeId;
63
+ notification.ResourceRecordID = input.ResourceRecordID;
64
+ notification.ResourceConfiguration = JSON.stringify({
65
+ DomainName: input.ResourceTypeLabel,
66
+ ...input.ExtraConfiguration,
67
+ });
68
+ const saved = await notification.Save();
69
+ if (!saved) {
70
+ LogError(`CreateShareNotification (default): save failed — ${notification.LatestResult?.CompleteMessage ?? 'unknown error'}`);
71
+ return false;
72
+ }
73
+ return true;
74
+ }
75
+ catch (err) {
76
+ LogError(`CreateShareNotification (default): ${err instanceof Error ? err.message : String(err)}`);
77
+ return false;
78
+ }
79
+ }
80
+ /**
81
+ * Ensure the `ResourcePermissionEngine` is configured, then resolve
82
+ * `MJ: Resource Type.Name → ID`. Returns null when the engine fails to load or
83
+ * the type isn't in the catalog.
84
+ */
85
+ async function resolveResourceTypeId(name, contextUser) {
86
+ if (!name)
87
+ return null;
88
+ try {
89
+ const engine = ResourcePermissionEngine.Instance;
90
+ await engine.Config(false, contextUser);
91
+ return engine.ResourceTypeIdByName(name);
92
+ }
93
+ catch (err) {
94
+ LogError(`resolveResourceTypeId('${name}'): ${err instanceof Error ? err.message : String(err)}`);
95
+ return null;
96
+ }
97
+ }
98
+ //# sourceMappingURL=shareNotification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shareNotification.js","sourceRoot":"","sources":["../../../src/custom/Permissions/shareNotification.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,64 @@
1
- import { EntitySaveOptions } from "@memberjunction/core";
1
+ import { EntityDeleteOptions, EntityPermissionType, EntitySaveOptions } from "@memberjunction/core";
2
2
  import { MJResourcePermissionEntity } from "../../generated/entity_subclasses.js";
3
3
  /**
4
4
  * Subclass for the Resource Permissiosn entity that implements some workflow logic
5
5
  */
6
6
  export declare class MJResourcePermissionEntityExtended extends MJResourcePermissionEntity {
7
+ /**
8
+ * Set by the async `Delete`/`Save` overrides after they confirm the
9
+ * context user is authorized via resource ownership or Owner-level grant.
10
+ * Read by the (sync) `CheckPermissions` override to bypass the role-based
11
+ * gate that would otherwise block non-admin users from revoking shares.
12
+ */
13
+ private _authorizedByOwnerOverride;
14
+ /**
15
+ * Relaxes the default role-based Update/Delete gate for three parties
16
+ * who legitimately need to manage a share:
17
+ *
18
+ * 1. **Grantor** — whoever created the grant (`SharedByUserID`).
19
+ * 2. **Resource owner** — the user who owns the underlying resource.
20
+ * Checked synchronously via in-memory engine caches (currently
21
+ * `ConversationEngine` for Conversations; add other engines as
22
+ * resource types adopt this pattern).
23
+ * 3. **Owner-level grantee** — anyone else holding an `Owner` permission
24
+ * on the same resource, consulted via the cached
25
+ * `ResourcePermissionEngine.Permissions`.
26
+ *
27
+ * Without this, resource owners can't revoke shares other users created —
28
+ * the UI/Developer roles don't have `CanDelete` on `MJ: Resource Permissions`.
29
+ */
30
+ CheckPermissions(type: EntityPermissionType, throwError: boolean): boolean;
31
+ /**
32
+ * Async owner lookup that loads the target resource and returns `true`
33
+ * if the context user owns it. Generic — uses the resource type catalog
34
+ * to find the owner field name, so any resource type seeded in
35
+ * `MJ: Resource Types` works without per-type code here.
36
+ */
37
+ private currentUserOwnsResourceAsync;
38
+ /**
39
+ * Compute whether the context user may Update/Delete this permission row.
40
+ * Combines the sync checks (fast path, uses engine caches) with the async
41
+ * resource-owner lookup (works on the server where caches aren't populated).
42
+ */
43
+ private callerMayManageShare;
44
+ /**
45
+ * Async wrapper that runs the full authorization check (including the
46
+ * async resource-owner lookup) before delegating to the base delete. Sets
47
+ * `_authorizedByOwnerOverride` so the sync `CheckPermissions` called by
48
+ * the base class will bypass the role-based gate.
49
+ */
50
+ Delete(options?: EntityDeleteOptions): Promise<boolean>;
51
+ /**
52
+ * Checks resource-type-specific engine caches synchronously to decide
53
+ * whether `userId` owns the record this permission row points at.
54
+ */
55
+ private currentUserOwnsResource;
56
+ /**
57
+ * Owner-level grantees (direct or via role) can manage shares on the
58
+ * resource. Reads from `ResourcePermissionEngine`'s cached permissions —
59
+ * must already be configured; on the server this happens at startup.
60
+ */
61
+ private currentUserHasOwnerGrant;
7
62
  /**
8
63
  * This override encapsulates some busienss logic for the Resource Permissions entity as follows:
9
64
  * 1) Whenever a new permission record is created that has a status of "Requested", we generate a new Notifications record for the owner of the resource being requested
@@ -12,5 +67,12 @@ export declare class MJResourcePermissionEntityExtended extends MJResourcePermis
12
67
  * @param options
13
68
  */
14
69
  Save(options?: EntitySaveOptions): Promise<boolean>;
70
+ /**
71
+ * `true` when the context user may create an Approved grant on this resource:
72
+ * they are either the resource's owner, or they already hold an Owner-level
73
+ * `MJ: Resource Permissions` row on it (direct or via role). Returns `false`
74
+ * when there is no context user.
75
+ */
76
+ private callerMayGrantShare;
15
77
  }
16
78
  //# sourceMappingURL=MJResourcePermissionEntityExtended.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MJResourcePermissionEntityExtended.d.ts","sourceRoot":"","sources":["../../../src/custom/ResourcePermissions/MJResourcePermissionEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,iBAAiB,EAAyC,MAAM,sBAAsB,CAAC;AAE1H,OAAO,EAAE,0BAA0B,EAA0C,MAAM,mCAAmC,CAAC;AAGvH;;GAEG;AACH,qBACa,kCAAmC,SAAQ,0BAA0B;IAC9E;;;;;;OAMG;IACY,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;CAmFrE"}
1
+ {"version":3,"file":"MJResourcePermissionEntityExtended.d.ts","sourceRoot":"","sources":["../../../src/custom/ResourcePermissions/MJResourcePermissionEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,mBAAmB,EAAE,oBAAoB,EAAE,iBAAiB,EAA+B,MAAM,sBAAsB,CAAC;AAE3J,OAAO,EAAE,0BAA0B,EAAgB,MAAM,mCAAmC,CAAC;AAS7F;;GAEG;AACH,qBACa,kCAAmC,SAAQ,0BAA0B;IAC9E;;;;;OAKG;IACH,OAAO,CAAC,0BAA0B,CAAS;IAC3C;;;;;;;;;;;;;;;OAeG;IACM,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO;IAanF;;;;;OAKG;YACW,4BAA4B;IAqC1C;;;;OAIG;YACW,oBAAoB;IASlC;;;;;OAKG;IACY,MAAM,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAetE;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAW/B;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAehC;;;;;;OAMG;IACY,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IA+IlE;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;CAa9B"}