@memberjunction/core-entities-server 6.1.0-edge.5 → 6.1.0-edge.7

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 (57) hide show
  1. package/dist/custom/MJAIBridgeProviderEntityServer.server.d.ts +1 -5
  2. package/dist/custom/MJAIBridgeProviderEntityServer.server.d.ts.map +1 -1
  3. package/dist/custom/MJAIBridgeProviderEntityServer.server.js +13 -12
  4. package/dist/custom/MJAIBridgeProviderEntityServer.server.js.map +1 -1
  5. package/dist/custom/MJAIRemoteBrowserProviderEntityServer.server.d.ts +2 -6
  6. package/dist/custom/MJAIRemoteBrowserProviderEntityServer.server.d.ts.map +1 -1
  7. package/dist/custom/MJAIRemoteBrowserProviderEntityServer.server.js +16 -14
  8. package/dist/custom/MJAIRemoteBrowserProviderEntityServer.server.js.map +1 -1
  9. package/dist/custom/MJActionEntityServer.server.d.ts +2 -2
  10. package/dist/custom/MJActionEntityServer.server.d.ts.map +1 -1
  11. package/dist/custom/MJActionEntityServer.server.js +8 -6
  12. package/dist/custom/MJActionEntityServer.server.js.map +1 -1
  13. package/dist/custom/MJApplicationEntityServer.server.d.ts +2 -2
  14. package/dist/custom/MJApplicationEntityServer.server.d.ts.map +1 -1
  15. package/dist/custom/MJApplicationEntityServer.server.js +4 -4
  16. package/dist/custom/MJApplicationEntityServer.server.js.map +1 -1
  17. package/dist/custom/MJEntityEntityServer.server.d.ts +36 -0
  18. package/dist/custom/MJEntityEntityServer.server.d.ts.map +1 -0
  19. package/dist/custom/MJEntityEntityServer.server.js +77 -0
  20. package/dist/custom/MJEntityEntityServer.server.js.map +1 -0
  21. package/dist/custom/MJEntityFieldPermissionEntityServer.server.d.ts +167 -0
  22. package/dist/custom/MJEntityFieldPermissionEntityServer.server.d.ts.map +1 -0
  23. package/dist/custom/MJEntityFieldPermissionEntityServer.server.js +347 -0
  24. package/dist/custom/MJEntityFieldPermissionEntityServer.server.js.map +1 -0
  25. package/dist/custom/MJRemoteOperationEntityServer.server.d.ts +2 -2
  26. package/dist/custom/MJRemoteOperationEntityServer.server.d.ts.map +1 -1
  27. package/dist/custom/MJRemoteOperationEntityServer.server.js +6 -4
  28. package/dist/custom/MJRemoteOperationEntityServer.server.js.map +1 -1
  29. package/dist/custom/MJRoleEntityServer.server.d.ts +78 -0
  30. package/dist/custom/MJRoleEntityServer.server.d.ts.map +1 -0
  31. package/dist/custom/MJRoleEntityServer.server.js +131 -0
  32. package/dist/custom/MJRoleEntityServer.server.js.map +1 -0
  33. package/dist/custom/MJUserEntityServer.server.d.ts +243 -0
  34. package/dist/custom/MJUserEntityServer.server.d.ts.map +1 -0
  35. package/dist/custom/MJUserEntityServer.server.js +335 -0
  36. package/dist/custom/MJUserEntityServer.server.js.map +1 -0
  37. package/dist/custom/MJUserRoleEntityServer.server.d.ts +243 -0
  38. package/dist/custom/MJUserRoleEntityServer.server.d.ts.map +1 -0
  39. package/dist/custom/MJUserRoleEntityServer.server.js +376 -0
  40. package/dist/custom/MJUserRoleEntityServer.server.js.map +1 -0
  41. package/dist/custom/MJUserViewEntityServer.server.d.ts +12 -1
  42. package/dist/custom/MJUserViewEntityServer.server.d.ts.map +1 -1
  43. package/dist/custom/MJUserViewEntityServer.server.js +33 -1
  44. package/dist/custom/MJUserViewEntityServer.server.js.map +1 -1
  45. package/dist/custom/fieldPermissionDelta.d.ts +57 -0
  46. package/dist/custom/fieldPermissionDelta.d.ts.map +1 -0
  47. package/dist/custom/fieldPermissionDelta.js +196 -0
  48. package/dist/custom/fieldPermissionDelta.js.map +1 -0
  49. package/dist/custom/fieldPermissionReconciler.d.ts +34 -0
  50. package/dist/custom/fieldPermissionReconciler.d.ts.map +1 -0
  51. package/dist/custom/fieldPermissionReconciler.js +96 -0
  52. package/dist/custom/fieldPermissionReconciler.js.map +1 -0
  53. package/dist/index.d.ts +7 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +7 -0
  56. package/dist/index.js.map +1 -1
  57. package/package.json +28 -28
@@ -0,0 +1,196 @@
1
+ import { FieldPermissionAccess } from '@memberjunction/core';
2
+ /**
3
+ * Computes the field-permission rows an entity is missing and the ones it should no longer
4
+ * have. Pure — no I/O, no entity objects, no provider. Everything comes off `EntityInfo`.
5
+ *
6
+ * **Snapshot defaults mirror entity-level permissions**, so enabling field security on an
7
+ * entity changes no behavior until an administrator tightens a specific field. A role that can
8
+ * read the entity gets `ReadAccess = 'Allow'`; its Update and Create follow the entity-level
9
+ * grants, defaulting to `No Access`.
10
+ *
11
+ * **A role without entity-level read gets no rows at all.** The entity-level gate already
12
+ * excludes it, so rows would be noise — and a row granting Update without Read would violate
13
+ * the Read-required CHECK constraint anyway.
14
+ *
15
+ * **Unrestrictable fields (primary keys, `__mj_` columns) get no rows.** They are forced open
16
+ * in the aggregation regardless, so rows for them are clutter that would also trip the
17
+ * save-time guard.
18
+ *
19
+ * **No role is excluded — including the ones the MJ system user holds.** Those rows are what
20
+ * keeps the system user working now that the aggregation has no bypass for it: it holds the
21
+ * standard roles (UI, Developer, Integration), which carry entity read on essentially
22
+ * everything, so the snapshot grants them `Allow` here and the save-time guards refuse any
23
+ * later `Deny` aimed at them. Access the server relies on is therefore visible in the data
24
+ * rather than implied by an exemption in code.
25
+ */
26
+ export function ComputeFieldPermissionDelta(entity) {
27
+ const accessByRoleID = buildRoleEntityAccessMap(entity);
28
+ const rolesWithEntityPermission = buildRolesWithAnyEntityPermission(entity);
29
+ const restrictableFields = entity.Fields.filter(isRestrictable);
30
+ // The two halves ask DIFFERENT questions of the same permission rows, and must not share an
31
+ // answer. Creating a snapshot row is a grant, so it is offered only to roles that can actually
32
+ // READ the entity (`accessByRoleID`). Deleting a row destroys an administrator's configuration,
33
+ // so it is justified only when the row can no longer influence any decision — which turns on
34
+ // whether the role relates to the entity at all, never on the strength of that relationship.
35
+ return {
36
+ ToInsert: computeMissingRows(restrictableFields, accessByRoleID),
37
+ ToDelete: computeOrphanRowIDs(entity, rolesWithEntityPermission),
38
+ };
39
+ }
40
+ /**
41
+ * A field is restrictable when field security could meaningfully apply to it. Primary keys and
42
+ * `__mj_` system columns are not, and neither is any field on the security-configuration or
43
+ * identity entities.
44
+ */
45
+ function isRestrictable(field) {
46
+ return !field.IsUnrestrictableField && !field.IsOnUnrestrictableEntity;
47
+ }
48
+ /**
49
+ * Every role holding ANY entity-permission row for this entity, whatever it grants and whichever
50
+ * `Type` it carries.
51
+ *
52
+ * This is the orphan test's criterion, and it is deliberately weaker than
53
+ * {@link buildRoleEntityAccessMap}. A field rule bound to a role is live at runtime purely on ROLE
54
+ * MEMBERSHIP — `EntityFieldInfo.AggregateFieldRulesForUser` matches on
55
+ * `user.UserRoles.find(...)` and never consults that role's entity-level access. So a role that
56
+ * grants nothing at entity level still contributes its field rules to the aggregate of any user who
57
+ * holds it AND gets entity access from a different role. Judging such a row inert because its own
58
+ * role cannot read the entity confuses a per-role fact with a per-user one, and deleting it on that
59
+ * basis destroys a `Deny` that was fully in force — turning "a Deny always wins" into
60
+ * "a Deny wins until reconciliation runs".
61
+ *
62
+ * Membership of this set is what `MJEntityFieldPermissionEntityServer.Validate()` requires before a
63
+ * field rule may be written at all, so the rule reconciliation enforces on cleanup is the same one
64
+ * authoring enforces on write.
65
+ */
66
+ function buildRolesWithAnyEntityPermission(entity) {
67
+ const roleIDs = new Set();
68
+ for (const permission of entity.Permissions) {
69
+ const roleID = normalizeID(permission.RoleID);
70
+ if (roleID) {
71
+ roleIDs.add(roleID);
72
+ }
73
+ }
74
+ return roleIDs;
75
+ }
76
+ /**
77
+ * Each role's effective entity-level access, aggregating its own Allow/Deny rows the same way
78
+ * `EntityInfo.GetUserPermisions` does one level up: a Deny beats an Allow for the same action.
79
+ *
80
+ * Roles resolving to no read access are omitted entirely, so callers can treat presence in the
81
+ * map as "this role should have rows."
82
+ */
83
+ function buildRoleEntityAccessMap(entity) {
84
+ const allow = new Map();
85
+ const deny = new Map();
86
+ for (const permission of entity.Permissions) {
87
+ const roleID = normalizeID(permission.RoleID);
88
+ if (!roleID) {
89
+ continue;
90
+ }
91
+ const bucket = isDenyPermission(permission) ? deny : allow;
92
+ foldPermissionInto(bucket, roleID, permission);
93
+ }
94
+ const effective = new Map();
95
+ for (const [roleID, granted] of allow) {
96
+ const blocked = deny.get(roleID) ?? { CanRead: false, CanUpdate: false, CanCreate: false };
97
+ const access = {
98
+ CanRead: granted.CanRead && !blocked.CanRead,
99
+ CanUpdate: granted.CanUpdate && !blocked.CanUpdate,
100
+ CanCreate: granted.CanCreate && !blocked.CanCreate,
101
+ };
102
+ if (access.CanRead) {
103
+ effective.set(roleID, access);
104
+ }
105
+ }
106
+ return effective;
107
+ }
108
+ function isDenyPermission(permission) {
109
+ return (permission.Type ?? 'Allow').trim().toLowerCase() === 'deny';
110
+ }
111
+ function foldPermissionInto(bucket, roleID, permission) {
112
+ const current = bucket.get(roleID) ?? { CanRead: false, CanUpdate: false, CanCreate: false };
113
+ current.CanRead = current.CanRead || !!permission.CanRead;
114
+ current.CanUpdate = current.CanUpdate || !!permission.CanUpdate;
115
+ current.CanCreate = current.CanCreate || !!permission.CanCreate;
116
+ bucket.set(roleID, current);
117
+ }
118
+ /**
119
+ * Every (restrictable field × qualifying role) pair that has no row yet, at snapshot defaults.
120
+ */
121
+ function computeMissingRows(fields, accessByRoleID) {
122
+ const missing = [];
123
+ for (const field of fields) {
124
+ const existingRoleIDs = new Set(field.FieldPermissions.map(fp => normalizeID(fp.RoleID)).filter(Boolean));
125
+ for (const [roleID, access] of accessByRoleID) {
126
+ if (existingRoleIDs.has(roleID)) {
127
+ continue;
128
+ }
129
+ // A read-only field cannot be written through the API by anyone — it is excluded from
130
+ // the generated create input and from the update SET list — so an Update or Create
131
+ // verb on it can never decide anything. Writing `Allow` there would author a rule
132
+ // that reads as a granted permission and is in fact inert, on ~1,000 fields x every
133
+ // qualifying role. Read stays meaningful and is untouched: restricting a foreign-key
134
+ // display column ("who does this record belong to") is a legitimate and common use.
135
+ const writable = !field.ReadOnly;
136
+ missing.push({
137
+ EntityFieldID: field.ID,
138
+ RoleID: roleID,
139
+ // Read is Allow by construction — buildRoleEntityAccessMap omits roles without
140
+ // it — which is what keeps these rows on the right side of the Read-required
141
+ // CHECK constraint no matter what Update and Create resolve to.
142
+ ReadAccess: FieldPermissionAccess.Allow,
143
+ UpdateAccess: writable && access.CanUpdate ? FieldPermissionAccess.Allow : FieldPermissionAccess.NoAccess,
144
+ CreateAccess: writable && access.CanCreate ? FieldPermissionAccess.Allow : FieldPermissionAccess.NoAccess,
145
+ });
146
+ }
147
+ }
148
+ return missing;
149
+ }
150
+ /**
151
+ * Rows that should no longer exist. Two ways a row becomes an orphan:
152
+ *
153
+ * - its field is no longer restrictable (a column was made a primary key, or the entity joined
154
+ * the unrestrictable list), so the aggregation returns fully-open for it regardless of any rule;
155
+ * - its role holds no entity-permission row for this entity at all, so no user can carry the rule
156
+ * into an aggregate through this entity — which also covers a role that no longer exists.
157
+ *
158
+ * A row whose FIELD was dropped disappears with the field's cascade, so it never reaches this
159
+ * walk — `entity.Fields` is the live set.
160
+ *
161
+ * **A role's entity-level ACCESS is deliberately not part of this test**, and an earlier version of
162
+ * this function that used it was wrong. It reasoned that a role without entity read is excluded by
163
+ * the entity gate, so its field rules cannot matter. But `EntityInfo.GetUserPermisions` aggregates
164
+ * the entity gate across ALL of a user's roles, exactly as the field aggregation does — so a user
165
+ * reading the entity through role S still carries role R's field rules, whatever R grants on its
166
+ * own. Deleting them silently restored access an administrator had explicitly denied, and
167
+ * `computeMissingRows` only ever writes `Allow`, so it never came back.
168
+ */
169
+ function computeOrphanRowIDs(entity, rolesWithEntityPermission) {
170
+ const orphans = [];
171
+ for (const field of entity.Fields) {
172
+ const fieldIsRestrictable = isRestrictable(field);
173
+ for (const permission of field.FieldPermissions) {
174
+ const roleID = normalizeID(permission.RoleID);
175
+ if (!fieldIsRestrictable || !roleID || !rolesWithEntityPermission.has(roleID)) {
176
+ orphans.push(permission.ID);
177
+ }
178
+ }
179
+ }
180
+ return orphans;
181
+ }
182
+ /**
183
+ * Lowercased ID for map keys. UUIDs arrive with different casing depending on their source, so
184
+ * normalize once here rather than scanning with a comparator on every lookup.
185
+ */
186
+ function normalizeID(id) {
187
+ return (id ?? '').trim().toLowerCase();
188
+ }
189
+ /**
190
+ * True when the delta would change nothing, so callers can skip opening a transaction at all.
191
+ * Reconciliation runs on ordinary saves, and the overwhelmingly common answer is "nothing to do".
192
+ */
193
+ export function IsEmptyFieldPermissionDelta(delta) {
194
+ return delta.ToInsert.length === 0 && delta.ToDelete.length === 0;
195
+ }
196
+ //# sourceMappingURL=fieldPermissionDelta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldPermissionDelta.js","sourceRoot":"","sources":["../../src/custom/fieldPermissionDelta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { EntityInfo, IMetadataProvider, UserInfo } from '@memberjunction/core';
2
+ /** What a reconciliation run actually wrote. */
3
+ export type FieldPermissionReconcileResult = {
4
+ Inserted: number;
5
+ Deleted: number;
6
+ };
7
+ /**
8
+ * Brings an entity's field-permission rows in line with its fields and entity-level
9
+ * permissions, writing the whole delta in one transaction.
10
+ *
11
+ * Every row goes through `BaseEntity.Save()` / `.Delete()` rather than direct SQL, so the
12
+ * save-time target guard, validation and entity actions all run — the delta function and the
13
+ * guard agree instead of one bypassing the other. `AllowDirectSQLInsert` stays off.
14
+ *
15
+ * Returns immediately when there is nothing to do, which is the overwhelmingly common case:
16
+ * reconciliation is triggered from ordinary saves, and a transaction opened to write zero rows
17
+ * is pure cost.
18
+ *
19
+ * @param entity the entity to reconcile — its `Fields` and `Permissions` are the desired state
20
+ * @param provider the provider to transact on and to build entity objects from
21
+ * @param contextUser the user the writes are attributed to
22
+ */
23
+ export declare function ReconcileFieldPermissions(entity: EntityInfo, provider: IMetadataProvider, contextUser: UserInfo): Promise<FieldPermissionReconcileResult>;
24
+ /**
25
+ * Runs {@link ReconcileFieldPermissions} and swallows failures into a logged error.
26
+ *
27
+ * For the adapters that reconcile as a SIDE EFFECT of some other save — a role being granted
28
+ * entity access, say. The triggering save has already committed by then, so throwing would
29
+ * report a failure for work that succeeded. The rows stay missing until the next reconciliation,
30
+ * which is a visible loss of access rather than a silent loss of protection: a field with no row
31
+ * on an enabled entity is denied.
32
+ */
33
+ export declare function ReconcileFieldPermissionsQuietly(entity: EntityInfo, provider: IMetadataProvider, contextUser: UserInfo): Promise<FieldPermissionReconcileResult>;
34
+ //# sourceMappingURL=fieldPermissionReconciler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldPermissionReconciler.d.ts","sourceRoot":"","sources":["../../src/custom/fieldPermissionReconciler.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,UAAU,EACV,iBAAiB,EAIjB,QAAQ,EACX,MAAM,sBAAsB,CAAC;AAI9B,gDAAgD;AAChD,MAAM,MAAM,8BAA8B,GAAG;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAIF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,yBAAyB,CAC3C,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,8BAA8B,CAAC,CAmBzC;AAuDD;;;;;;;;GAQG;AACH,wBAAsB,gCAAgC,CAClD,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,QAAQ,GACtB,OAAO,CAAC,8BAA8B,CAAC,CAOzC"}
@@ -0,0 +1,96 @@
1
+ import { LogDebug, LogError, RunInEntityTransaction, } from '@memberjunction/core';
2
+ import { ComputeFieldPermissionDelta, IsEmptyFieldPermissionDelta } from './fieldPermissionDelta.js';
3
+ const NOTHING_DONE = { Inserted: 0, Deleted: 0 };
4
+ /**
5
+ * Brings an entity's field-permission rows in line with its fields and entity-level
6
+ * permissions, writing the whole delta in one transaction.
7
+ *
8
+ * Every row goes through `BaseEntity.Save()` / `.Delete()` rather than direct SQL, so the
9
+ * save-time target guard, validation and entity actions all run — the delta function and the
10
+ * guard agree instead of one bypassing the other. `AllowDirectSQLInsert` stays off.
11
+ *
12
+ * Returns immediately when there is nothing to do, which is the overwhelmingly common case:
13
+ * reconciliation is triggered from ordinary saves, and a transaction opened to write zero rows
14
+ * is pure cost.
15
+ *
16
+ * @param entity the entity to reconcile — its `Fields` and `Permissions` are the desired state
17
+ * @param provider the provider to transact on and to build entity objects from
18
+ * @param contextUser the user the writes are attributed to
19
+ */
20
+ export async function ReconcileFieldPermissions(entity, provider, contextUser) {
21
+ if (!entity || !provider) {
22
+ return NOTHING_DONE;
23
+ }
24
+ const delta = ComputeFieldPermissionDelta(entity);
25
+ if (IsEmptyFieldPermissionDelta(delta)) {
26
+ return NOTHING_DONE;
27
+ }
28
+ LogDebug(`[FieldSecurity] Reconciling '${entity.Name}': ` +
29
+ `${delta.ToInsert.length} row(s) to add, ${delta.ToDelete.length} to remove`);
30
+ return RunInEntityTransaction(provider, async () => {
31
+ const deleted = await deleteRows(delta.ToDelete, provider, contextUser);
32
+ const inserted = await insertRows(delta.ToInsert, provider, contextUser, entity);
33
+ return { Inserted: inserted, Deleted: deleted };
34
+ });
35
+ }
36
+ /**
37
+ * Deletes happen BEFORE inserts. A row can be an orphan for one (field, role) while the same
38
+ * pair needs a fresh row at snapshot defaults — doing it the other way round would collide on
39
+ * the (EntityFieldID, RoleID) uniqueness constraint.
40
+ */
41
+ async function deleteRows(ids, provider, contextUser) {
42
+ let deleted = 0;
43
+ for (const id of ids) {
44
+ const row = await provider.GetEntityObject('MJ: Entity Field Permissions', contextUser);
45
+ if (!(await row.Load(id))) {
46
+ // Already gone — another reconciliation, or a cascade from a dropped field.
47
+ continue;
48
+ }
49
+ if (await row.Delete()) {
50
+ deleted++;
51
+ }
52
+ else {
53
+ throw new Error(`Field-permission reconciliation could not remove row '${id}': ` +
54
+ `${row.LatestResult?.CompleteMessage ?? 'no error reported'}`);
55
+ }
56
+ }
57
+ return deleted;
58
+ }
59
+ async function insertRows(rows, provider, contextUser, entity) {
60
+ let inserted = 0;
61
+ for (const spec of rows) {
62
+ const row = await provider.GetEntityObject('MJ: Entity Field Permissions', contextUser);
63
+ row.NewRecord();
64
+ row.EntityFieldID = spec.EntityFieldID;
65
+ row.RoleID = spec.RoleID;
66
+ row.ReadAccess = spec.ReadAccess;
67
+ row.UpdateAccess = spec.UpdateAccess;
68
+ row.CreateAccess = spec.CreateAccess;
69
+ if (!(await row.Save())) {
70
+ throw new Error(`Field-permission reconciliation could not add a row for '${entity.Name}' ` +
71
+ `(field ${spec.EntityFieldID}, role ${spec.RoleID}): ` +
72
+ `${row.LatestResult?.CompleteMessage ?? 'no error reported'}`);
73
+ }
74
+ inserted++;
75
+ }
76
+ return inserted;
77
+ }
78
+ /**
79
+ * Runs {@link ReconcileFieldPermissions} and swallows failures into a logged error.
80
+ *
81
+ * For the adapters that reconcile as a SIDE EFFECT of some other save — a role being granted
82
+ * entity access, say. The triggering save has already committed by then, so throwing would
83
+ * report a failure for work that succeeded. The rows stay missing until the next reconciliation,
84
+ * which is a visible loss of access rather than a silent loss of protection: a field with no row
85
+ * on an enabled entity is denied.
86
+ */
87
+ export async function ReconcileFieldPermissionsQuietly(entity, provider, contextUser) {
88
+ try {
89
+ return await ReconcileFieldPermissions(entity, provider, contextUser);
90
+ }
91
+ catch (e) {
92
+ LogError(`[FieldSecurity] Reconciliation of '${entity?.Name}' failed`, undefined, e);
93
+ return NOTHING_DONE;
94
+ }
95
+ }
96
+ //# sourceMappingURL=fieldPermissionReconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldPermissionReconciler.js","sourceRoot":"","sources":["../../src/custom/fieldPermissionReconciler.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -35,11 +35,18 @@ export * from './custom/MJMaterializedResultEntityServer.server.js';
35
35
  export * from './custom/MJAISkillPermissionEntityServer.server.js';
36
36
  export * from './custom/MJAISkillEntityServer.server.js';
37
37
  export * from './custom/MJMLTrainingPipelineEntityServer.server.js';
38
+ export * from './custom/MJUserEntityServer.server.js';
39
+ export * from './custom/MJRoleEntityServer.server.js';
40
+ export * from './custom/MJUserRoleEntityServer.server.js';
38
41
  export * from './custom/MJUserRoutineEntityServer.server.js';
39
42
  export * from './custom/MJUserRoutineRecipientEntityServer.server.js';
40
43
  export * from './custom/MJAPIKeyScopeEntityServer.server.js';
41
44
  export * from './custom/MJAPIApplicationScopeEntityServer.server.js';
42
45
  export * from './custom/MJRowLevelSecurityFilterEntityServer.server.js';
46
+ export * from './custom/MJEntityFieldPermissionEntityServer.server.js';
47
+ export * from './custom/MJEntityEntityServer.server.js';
48
+ export * from './custom/fieldPermissionDelta.js';
49
+ export * from './custom/fieldPermissionReconciler.js';
43
50
  export * from './custom/rowFilterValidation.js';
44
51
  export * from './custom/json-schema-lite.js';
45
52
  export * from './custom/IntegrationLLMPKCallback.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,kDAAkD,CAAC;AACjE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4CAA4C,CAAC;AAC3D,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,wCAAwC,CAAC;AACvD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,qDAAqD,CAAC;AACpE,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AACnE,cAAc,+DAA+D,CAAC;AAC9E,cAAc,uDAAuD,CAAC;AACtE,cAAc,kDAAkD,CAAC;AACjE,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,kDAAkD,CAAC;AACjE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,sDAAsD,CAAC;AACrE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,eAAe,CAAC;AAE9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,kDAAkD,CAAC;AACjE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4CAA4C,CAAC;AAC3D,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,wCAAwC,CAAC;AACvD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,qDAAqD,CAAC;AACpE,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AACnE,cAAc,+DAA+D,CAAC;AAC9E,cAAc,uDAAuD,CAAC;AACtE,cAAc,kDAAkD,CAAC;AACjE,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,kDAAkD,CAAC;AACjE,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,sDAAsD,CAAC;AACrE,cAAc,qDAAqD,CAAC;AACpE,cAAc,sCAAsC,CAAC;AACrD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,eAAe,CAAC;AAE9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC"}
package/dist/index.js CHANGED
@@ -35,11 +35,18 @@ export * from './custom/MJMaterializedResultEntityServer.server.js';
35
35
  export * from './custom/MJAISkillPermissionEntityServer.server.js';
36
36
  export * from './custom/MJAISkillEntityServer.server.js';
37
37
  export * from './custom/MJMLTrainingPipelineEntityServer.server.js';
38
+ export * from './custom/MJUserEntityServer.server.js';
39
+ export * from './custom/MJRoleEntityServer.server.js';
40
+ export * from './custom/MJUserRoleEntityServer.server.js';
38
41
  export * from './custom/MJUserRoutineEntityServer.server.js';
39
42
  export * from './custom/MJUserRoutineRecipientEntityServer.server.js';
40
43
  export * from './custom/MJAPIKeyScopeEntityServer.server.js';
41
44
  export * from './custom/MJAPIApplicationScopeEntityServer.server.js';
42
45
  export * from './custom/MJRowLevelSecurityFilterEntityServer.server.js';
46
+ export * from './custom/MJEntityFieldPermissionEntityServer.server.js';
47
+ export * from './custom/MJEntityEntityServer.server.js';
48
+ export * from './custom/fieldPermissionDelta.js';
49
+ export * from './custom/fieldPermissionReconciler.js';
43
50
  export * from './custom/rowFilterValidation.js';
44
51
  export * from './custom/json-schema-lite.js';
45
52
  export * from './custom/IntegrationLLMPKCallback.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,kDAAkD,CAAC;AACjE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4CAA4C,CAAC;AAC3D,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,wCAAwC,CAAC;AACvD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,qDAAqD,CAAC;AACpE,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AACnE,cAAc,+DAA+D,CAAC;AAC9E,cAAc,uDAAuD,CAAC;AACtE,cAAc,kDAAkD,CAAC;AACjE,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,kDAAkD,CAAC;AACjE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,sDAAsD,CAAC;AACrE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,eAAe,CAAC;AAE9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wCAAwC,CAAC;AACvD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,kDAAkD,CAAC;AACjE,cAAc,4DAA4D,CAAC;AAC3E,cAAc,4CAA4C,CAAC;AAC3D,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,8CAA8C,CAAC;AAC7D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,wCAAwC,CAAC;AACvD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,qDAAqD,CAAC;AACpE,cAAc,uDAAuD,CAAC;AACtE,cAAc,oDAAoD,CAAC;AACnE,cAAc,+DAA+D,CAAC;AAC9E,cAAc,uDAAuD,CAAC;AACtE,cAAc,kDAAkD,CAAC;AACjE,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,kDAAkD,CAAC;AACjE,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oDAAoD,CAAC;AACnE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,mDAAmD,CAAC;AAClE,cAAc,sDAAsD,CAAC;AACrE,cAAc,qDAAqD,CAAC;AACpE,cAAc,sCAAsC,CAAC;AACrD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mCAAmC,CAAC;AAClD,cAAc,eAAe,CAAC;AAE9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+CAA+C,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/core-entities-server",
3
3
  "type": "module",
4
- "version": "6.1.0-edge.5",
4
+ "version": "6.1.0-edge.7",
5
5
  "description": "Entity subclasses for the metadata layer of MemberJunction that are only used on server side applications like MJAPI, distributed as part of each release of MemberJunction",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -15,33 +15,33 @@
15
15
  "typescript": "^5.9.3"
16
16
  },
17
17
  "dependencies": {
18
- "@memberjunction/actions-base": "6.1.0-edge.5",
19
- "@memberjunction/ai": "6.1.0-edge.5",
20
- "@memberjunction/ai-core-plus": "6.1.0-edge.5",
21
- "@memberjunction/ai-engine-base": "6.1.0-edge.5",
22
- "@memberjunction/ai-prompts": "6.1.0-edge.5",
23
- "@memberjunction/ai-provider-bundle": "6.1.0-edge.5",
24
- "@memberjunction/ai-vector-dupe": "6.1.0-edge.5",
25
- "@memberjunction/ai-vectordb": "6.1.0-edge.5",
26
- "@memberjunction/ai-vectors-memory": "6.1.0-edge.5",
27
- "@memberjunction/aiengine": "6.1.0-edge.5",
28
- "@memberjunction/core": "6.1.0-edge.5",
29
- "@memberjunction/core-entities": "6.1.0-edge.5",
30
- "@memberjunction/predictive-studio-core": "6.1.0-edge.5",
31
- "@memberjunction/doc-utils": "6.1.0-edge.5",
32
- "@memberjunction/generic-database-provider": "6.1.0-edge.5",
33
- "@memberjunction/global": "6.1.0-edge.5",
34
- "@memberjunction/integration-engine": "6.1.0-edge.5",
35
- "@memberjunction/integration-pk-classifier": "6.1.0-edge.5",
36
- "@memberjunction/scheduling-engine": "6.1.0-edge.5",
37
- "@memberjunction/sql-converter": "6.1.0-edge.5",
38
- "@memberjunction/sql-dialect": "6.1.0-edge.5",
39
- "@memberjunction/sql-parser": "6.1.0-edge.5",
40
- "@memberjunction/sqlserver-dataprovider": "6.1.0-edge.5",
41
- "@memberjunction/tag-engine": "6.1.0-edge.5",
42
- "@memberjunction/communication-engine": "6.1.0-edge.5",
43
- "@memberjunction/communication-types": "6.1.0-edge.5",
44
- "@memberjunction/templates": "6.1.0-edge.5",
18
+ "@memberjunction/actions-base": "6.1.0-edge.7",
19
+ "@memberjunction/ai": "6.1.0-edge.7",
20
+ "@memberjunction/ai-core-plus": "6.1.0-edge.7",
21
+ "@memberjunction/ai-engine-base": "6.1.0-edge.7",
22
+ "@memberjunction/ai-prompts": "6.1.0-edge.7",
23
+ "@memberjunction/ai-provider-bundle": "6.1.0-edge.7",
24
+ "@memberjunction/ai-vector-dupe": "6.1.0-edge.7",
25
+ "@memberjunction/ai-vectordb": "6.1.0-edge.7",
26
+ "@memberjunction/ai-vectors-memory": "6.1.0-edge.7",
27
+ "@memberjunction/aiengine": "6.1.0-edge.7",
28
+ "@memberjunction/core": "6.1.0-edge.7",
29
+ "@memberjunction/core-entities": "6.1.0-edge.7",
30
+ "@memberjunction/predictive-studio-core": "6.1.0-edge.7",
31
+ "@memberjunction/doc-utils": "6.1.0-edge.7",
32
+ "@memberjunction/generic-database-provider": "6.1.0-edge.7",
33
+ "@memberjunction/global": "6.1.0-edge.7",
34
+ "@memberjunction/integration-engine": "6.1.0-edge.7",
35
+ "@memberjunction/integration-pk-classifier": "6.1.0-edge.7",
36
+ "@memberjunction/scheduling-engine": "6.1.0-edge.7",
37
+ "@memberjunction/sql-converter": "6.1.0-edge.7",
38
+ "@memberjunction/sql-dialect": "6.1.0-edge.7",
39
+ "@memberjunction/sql-parser": "6.1.0-edge.7",
40
+ "@memberjunction/sqlserver-dataprovider": "6.1.0-edge.7",
41
+ "@memberjunction/tag-engine": "6.1.0-edge.7",
42
+ "@memberjunction/communication-engine": "6.1.0-edge.7",
43
+ "@memberjunction/communication-types": "6.1.0-edge.7",
44
+ "@memberjunction/templates": "6.1.0-edge.7",
45
45
  "nunjucks": "3.2.4",
46
46
  "rxjs": "~7.8.1",
47
47
  "zod": "^3.25.0"