@memberjunction/generic-database-provider 6.1.0-edge.6 → 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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @fileoverview Startup backstop for the system user's field-level access.
3
+ *
4
+ * The save-time guards in `MJEntityFieldPermissionEntityServer` refuse a change that would leave
5
+ * the system user short of its entity-level access — but they only see changes that go through the
6
+ * entity layer with a warm user cache. Direct SQL, a migration, a role removed from the account,
7
+ * or a save made during another process's bootstrap all reach the same state unobserved.
8
+ *
9
+ * Field security has no runtime exemption for the system user, so that state is not inert: the
10
+ * server's own background work silently loses a column, and because engine caches are process-wide
11
+ * the partially loaded record it caches is then served to everyone. This makes it loud at the one
12
+ * moment someone is watching.
13
+ *
14
+ * @module @memberjunction/generic-database-provider
15
+ */
16
+ import { IMetadataProvider, IStartupSink, UserInfo } from '@memberjunction/core';
17
+ import { BaseSingleton } from '@memberjunction/global';
18
+ /**
19
+ * Reports — loudly, but without blocking boot — any field on an FLS-enabled entity that the MJ
20
+ * system user can no longer fully use.
21
+ *
22
+ * **Warns rather than refuses to start.** The condition is bad configuration, not a broken build,
23
+ * and a server that will not boot is a worse failure than one that boots and says exactly what is
24
+ * wrong. It is also self-inflicted-recovery-hostile: the administrator's route to fixing the rows
25
+ * is usually the application that would refuse to start.
26
+ *
27
+ * Costs nothing when nothing is enabled: entities with `EnableFieldLevelSecurity = false` are
28
+ * skipped on a boolean read, and there are no queries at any point.
29
+ */
30
+ export declare class SystemUserFieldAccessCheck extends BaseSingleton<SystemUserFieldAccessCheck> implements IStartupSink {
31
+ protected constructor();
32
+ static get Instance(): SystemUserFieldAccessCheck;
33
+ HandleStartup(_contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void>;
34
+ /**
35
+ * Reports field permission rows whose role holds no entity permission on the same entity.
36
+ *
37
+ * `MJEntityFieldPermissionEntityServer.Validate()` refuses to create such a row, and
38
+ * reconciliation deletes any it finds — but both only see writes that go through the entity
39
+ * layer. Direct SQL, a migration, or a `ReplayOnly` save can author one unobserved, and until
40
+ * the next reconciliation it is fully live: field-rule aggregation matches on role membership
41
+ * alone, so the rule applies to any user holding that role who reaches the entity through a
42
+ * different one. That makes it a real access change with no visible cause.
43
+ *
44
+ * Scoped to FLS-enabled entities, matching where reconciliation runs and where the rules
45
+ * actually decide anything — a rule on a disabled entity is dormant rather than wrong.
46
+ *
47
+ * Reads cached metadata only; no queries.
48
+ *
49
+ * @returns the number of orphaned rows found
50
+ */
51
+ RunOrphanedFieldRuleSweep(provider?: IMetadataProvider | null): number;
52
+ /**
53
+ * Runs the sweep and logs the outcome. Separate from {@link HandleStartup} so callers that
54
+ * already hold a provider — tests, a maintenance command — can invoke it directly.
55
+ *
56
+ * @returns the number of offending fields found
57
+ */
58
+ Run(provider?: IMetadataProvider | null): number;
59
+ }
60
+ /**
61
+ * Loader stub — keeps the class (and therefore its startup registration) from being tree-shaken.
62
+ */
63
+ export declare function LoadSystemUserFieldAccessCheck(): void;
64
+ //# sourceMappingURL=SystemUserFieldAccessCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SystemUserFieldAccessCheck.d.ts","sourceRoot":"","sources":["../src/SystemUserFieldAccessCheck.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAA2C,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1H,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAMvD;;;;;;;;;;;GAWG;AACH,qBAKa,0BAA2B,SAAQ,aAAa,CAAC,0BAA0B,CAAE,YAAW,YAAY;IAC7G,SAAS;IAIT,WAAkB,QAAQ,IAAI,0BAA0B,CAEvD;IAEY,aAAa,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhG;;;;;;;;;;;;;;;;OAgBG;IACI,yBAAyB,CAAC,QAAQ,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM;IAqC7E;;;;;OAKG;IACI,GAAG,CAAC,QAAQ,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,MAAM;CAoB1D;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
@@ -0,0 +1,137 @@
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
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ /**
11
+ * @fileoverview Startup backstop for the system user's field-level access.
12
+ *
13
+ * The save-time guards in `MJEntityFieldPermissionEntityServer` refuse a change that would leave
14
+ * the system user short of its entity-level access — but they only see changes that go through the
15
+ * entity layer with a warm user cache. Direct SQL, a migration, a role removed from the account,
16
+ * or a save made during another process's bootstrap all reach the same state unobserved.
17
+ *
18
+ * Field security has no runtime exemption for the system user, so that state is not inert: the
19
+ * server's own background work silently loses a column, and because engine caches are process-wide
20
+ * the partially loaded record it caches is then served to everyone. This makes it loud at the one
21
+ * moment someone is watching.
22
+ *
23
+ * @module @memberjunction/generic-database-provider
24
+ */
25
+ import { LogError, RegisterForStartup } from '@memberjunction/core';
26
+ import { BaseSingleton } from '@memberjunction/global';
27
+ import { FindSystemUserFieldAccessViolations } from './systemUserFieldAccess.js';
28
+ /** How many offending fields to name before summarising the rest. */
29
+ const MAX_REPORTED = 10;
30
+ /**
31
+ * Reports — loudly, but without blocking boot — any field on an FLS-enabled entity that the MJ
32
+ * system user can no longer fully use.
33
+ *
34
+ * **Warns rather than refuses to start.** The condition is bad configuration, not a broken build,
35
+ * and a server that will not boot is a worse failure than one that boots and says exactly what is
36
+ * wrong. It is also self-inflicted-recovery-hostile: the administrator's route to fixing the rows
37
+ * is usually the application that would refuse to start.
38
+ *
39
+ * Costs nothing when nothing is enabled: entities with `EnableFieldLevelSecurity = false` are
40
+ * skipped on a boolean read, and there are no queries at any point.
41
+ */
42
+ let SystemUserFieldAccessCheck = class SystemUserFieldAccessCheck extends BaseSingleton {
43
+ constructor() {
44
+ super();
45
+ }
46
+ static get Instance() {
47
+ return super.getInstance();
48
+ }
49
+ async HandleStartup(_contextUser, provider) {
50
+ this.Run(provider);
51
+ this.RunOrphanedFieldRuleSweep(provider);
52
+ }
53
+ /**
54
+ * Reports field permission rows whose role holds no entity permission on the same entity.
55
+ *
56
+ * `MJEntityFieldPermissionEntityServer.Validate()` refuses to create such a row, and
57
+ * reconciliation deletes any it finds — but both only see writes that go through the entity
58
+ * layer. Direct SQL, a migration, or a `ReplayOnly` save can author one unobserved, and until
59
+ * the next reconciliation it is fully live: field-rule aggregation matches on role membership
60
+ * alone, so the rule applies to any user holding that role who reaches the entity through a
61
+ * different one. That makes it a real access change with no visible cause.
62
+ *
63
+ * Scoped to FLS-enabled entities, matching where reconciliation runs and where the rules
64
+ * actually decide anything — a rule on a disabled entity is dormant rather than wrong.
65
+ *
66
+ * Reads cached metadata only; no queries.
67
+ *
68
+ * @returns the number of orphaned rows found
69
+ */
70
+ RunOrphanedFieldRuleSweep(provider) {
71
+ const entities = provider?.Entities ?? [];
72
+ const offenders = [];
73
+ for (const entity of entities) {
74
+ if (!entity.EnableFieldLevelSecurity) {
75
+ continue; // rules here decide nothing, so an orphan is dormant rather than wrong
76
+ }
77
+ const rolesWithEntityPermission = new Set(entity.Permissions.map((p) => (p.RoleID ?? '').trim().toLowerCase()).filter(Boolean));
78
+ for (const field of entity.Fields) {
79
+ for (const rule of field.FieldPermissions) {
80
+ const roleID = (rule.RoleID ?? '').trim().toLowerCase();
81
+ if (roleID && !rolesWithEntityPermission.has(roleID)) {
82
+ offenders.push(` - ${entity.Name}.${field.Name} (role ${rule.RoleID})`);
83
+ }
84
+ }
85
+ }
86
+ }
87
+ if (offenders.length === 0) {
88
+ return 0;
89
+ }
90
+ const shown = offenders.slice(0, MAX_REPORTED).join('\n');
91
+ const more = offenders.length > MAX_REPORTED ? `\n ...and ${offenders.length - MAX_REPORTED} more` : '';
92
+ LogError(`[FieldSecurity] ${offenders.length} field permission row(s) name a role with no entity permission on the ` +
93
+ `same entity. A field rule refines an entity permission, so these refine nothing on their own — yet they ` +
94
+ `still apply to any user who holds the role and reaches the entity through another one. The next ` +
95
+ `reconciliation will delete them. Grant the role an entity permission if the rule is intended, or remove ` +
96
+ `the rule.\n${shown}${more}`);
97
+ return offenders.length;
98
+ }
99
+ /**
100
+ * Runs the sweep and logs the outcome. Separate from {@link HandleStartup} so callers that
101
+ * already hold a provider — tests, a maintenance command — can invoke it directly.
102
+ *
103
+ * @returns the number of offending fields found
104
+ */
105
+ Run(provider) {
106
+ const violations = FindSystemUserFieldAccessViolations(provider);
107
+ if (violations.length === 0) {
108
+ return 0;
109
+ }
110
+ const shown = violations
111
+ .slice(0, MAX_REPORTED)
112
+ .map(v => ` - ${v.EntityName}.${v.FieldName} (cannot ${v.Verb})`)
113
+ .join('\n');
114
+ const more = violations.length > MAX_REPORTED ? `\n ...and ${violations.length - MAX_REPORTED} more` : '';
115
+ LogError(`[FieldSecurity] The MJ system user has lost field-level access to ${violations.length} field(s). ` +
116
+ `The server runs background work as that account and engine caches are process-wide, so it may cache ` +
117
+ `partially loaded records that every user then reads. Field security has no exempt user — restore an ` +
118
+ `'Allow' on a role the system user holds, or take the offending role off that account.\n${shown}${more}`);
119
+ return violations.length;
120
+ }
121
+ };
122
+ SystemUserFieldAccessCheck = __decorate([
123
+ RegisterForStartup({
124
+ priority: 900,
125
+ severity: 'warn',
126
+ description: 'Verifies the MJ system user retains its field-level access on FLS-enabled entities',
127
+ }),
128
+ __metadata("design:paramtypes", [])
129
+ ], SystemUserFieldAccessCheck);
130
+ export { SystemUserFieldAccessCheck };
131
+ /**
132
+ * Loader stub — keeps the class (and therefore its startup registration) from being tree-shaken.
133
+ */
134
+ export function LoadSystemUserFieldAccessCheck() {
135
+ // no-op
136
+ }
137
+ //# sourceMappingURL=SystemUserFieldAccessCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SystemUserFieldAccessCheck.js","sourceRoot":"","sources":["../src/SystemUserFieldAccessCheck.ts"],"names":[],"mappings":";;;;;;;;;AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAmC,QAAQ,EAAa,kBAAkB,EAAY,MAAM,sBAAsB,CAAC;AAC1H,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,mCAAmC,EAAE,MAAM,4BAA4B,CAAC;AAEjF,qEAAqE;AACrE,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB;;;;;;;;;;;GAWG;AAMI,IAAM,0BAA0B,GAAhC,MAAM,0BAA2B,SAAQ,aAAyC;IACrF;QACI,KAAK,EAAE,CAAC;IACZ,CAAC;IAEM,MAAM,KAAK,QAAQ;QACtB,OAAO,KAAK,CAAC,WAAW,EAA8B,CAAC;IAC3D,CAAC;IAEM,KAAK,CAAC,aAAa,CAAC,YAAuB,EAAE,QAA4B;QAC5E,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnB,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACI,yBAAyB,CAAC,QAAmC;QAChE,MAAM,QAAQ,GAAG,QAAQ,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAa,EAAE,CAAC;QAE/B,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,wBAAwB,EAAE,CAAC;gBACnC,SAAS,CAAC,uEAAuE;YACrF,CAAC;YACD,MAAM,yBAAyB,GAAG,IAAI,GAAG,CACrC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CACvF,CAAC;YACF,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;oBACxC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;oBACxD,IAAI,MAAM,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;wBACnD,SAAS,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,UAAU,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;oBAC7E,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,CAAC;QACb,CAAC;QAED,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,SAAS,CAAC,MAAM,GAAG,YAAY,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACzG,QAAQ,CACJ,mBAAmB,SAAS,CAAC,MAAM,wEAAwE;YAC3G,0GAA0G;YAC1G,kGAAkG;YAClG,0GAA0G;YAC1G,cAAc,KAAK,GAAG,IAAI,EAAE,CAC/B,CAAC;QACF,OAAO,SAAS,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED;;;;;OAKG;IACI,GAAG,CAAC,QAAmC;QAC1C,MAAM,UAAU,GAAG,mCAAmC,CAAC,QAAQ,CAAC,CAAC;QACjE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,CAAC;QACb,CAAC;QAED,MAAM,KAAK,GAAG,UAAU;aACnB,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;aACtB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,SAAS,YAAY,CAAC,CAAC,IAAI,GAAG,CAAC;aACjE,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,UAAU,CAAC,MAAM,GAAG,YAAY,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3G,QAAQ,CACJ,qEAAqE,UAAU,CAAC,MAAM,aAAa;YACnG,sGAAsG;YACtG,sGAAsG;YACtG,0FAA0F,KAAK,GAAG,IAAI,EAAE,CAC3G,CAAC;QACF,OAAO,UAAU,CAAC,MAAM,CAAC;IAC7B,CAAC;CACJ,CAAA;AA9FY,0BAA0B;IALtC,kBAAkB,CAAC;QAChB,QAAQ,EAAE,GAAG;QACb,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,oFAAoF;KACpG,CAAC;;GACW,0BAA0B,CA8FtC;;AAED;;GAEG;AACH,MAAM,UAAU,8BAA8B;IAC1C,QAAQ;AACZ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"UserCache.d.ts","sourceRoot":"","sources":["../src/UserCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAc,MAAM,wBAAwB,CAAC;AAenE;;;;;;;;;;;;GAYG;AACH,qBAAa,SAAU,SAAQ,aAAa,CAAC,SAAS,CAAC;IACnD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAkB;IAEhC;;OAEG;;IAKH,IAAW,cAAc,IAAI,MAAM,CAElC;IAED;;;;;;;OAOG;IACI,aAAa,IAAI,QAAQ;IAIhC;;;;;OAKG;IACU,OAAO,CAAC,QAAQ,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBnG;;;;;;;;;;;;;;;;;OAiBG;IACI,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI;IAIxC;;OAEG;cACa,SAAS,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC;IAa1F,WAAkB,QAAQ,IAAI,SAAS,CAEtC;IAED,IAAW,KAAK,IAAI,QAAQ,EAAE,CAE7B;IAED,MAAM,KAAK,KAAK,IAAI,QAAQ,EAAE,CAE7B;IAED;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,GAAE,OAAe,GAAG,QAAQ,GAAG,SAAS;CAOxF"}
1
+ {"version":3,"file":"UserCache.d.ts","sourceRoot":"","sources":["../src/UserCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAc,MAAM,wBAAwB,CAAC;AAcnE;;;;;;;;;;;;GAYG;AACH,qBAAa,SAAU,SAAQ,aAAa,CAAC,SAAS,CAAC;IACnD;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAkB;IAEhC;;OAEG;;IAKH,IAAW,cAAc,IAAI,MAAM,CAElC;IAED;;;;;;;OAOG;IACI,aAAa,IAAI,QAAQ;IAIhC;;;;;OAKG;IACU,OAAO,CAAC,QAAQ,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBnG;;;;;;;;;;;;;;;;;OAiBG;IACI,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI;IAIxC;;OAEG;cACa,SAAS,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC;IAa1F,WAAkB,QAAQ,IAAI,SAAS,CAEtC;IAED,IAAW,KAAK,IAAI,QAAQ,EAAE,CAE7B;IAED,MAAM,KAAK,KAAK,IAAI,QAAQ,EAAE,CAE7B;IAED;;;;;OAKG;IACI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,GAAE,OAAe,GAAG,QAAQ,GAAG,SAAS;CAOxF"}
package/dist/UserCache.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { LogError, UserInfo } from '@memberjunction/core';
2
2
  import { BaseSingleton, UUIDsEqual } from '@memberjunction/global';
3
- const SYSTEM_USER_ID = 'ecafccec-6a37-ef11-86d4-000d3a4e707e';
3
+ import { SystemUserID } from './systemUser.js';
4
4
  /**
5
5
  * Server side cache of users and their roles.
6
6
  *
@@ -28,7 +28,7 @@ export class UserCache extends BaseSingleton {
28
28
  this._users = [];
29
29
  }
30
30
  get SYSTEM_USER_ID() {
31
- return SYSTEM_USER_ID;
31
+ return SystemUserID;
32
32
  }
33
33
  /**
34
34
  * Returns the system user, or `undefined` when the cache has not been refreshed or the row is
@@ -1 +1 @@
1
- {"version":3,"file":"UserCache.js","sourceRoot":"","sources":["../src/UserCache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UserCache.js","sourceRoot":"","sources":["../src/UserCache.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  export { GenericDatabaseProvider, DoomedTransactionError, ExecuteSQLBatchOptions } from './GenericDatabaseProvider.js';
2
+ export { DatabaseWellKnownUserSource } from './DatabaseWellKnownUserSource.js';
3
+ export { SystemUserID } from './systemUser.js';
2
4
  export type { SaveCoercedValue, SaveCallBinding, SaveSQLFragment, RecordChangePayload, } from './saveTypes.js';
3
5
  export { CRUDSprocType, shouldIncludeFieldInParams, needsClearCompanionBroadRule, projectedParamCount, useJsonArgShape, } from './crudSprocFieldRules.js';
4
6
  export { resolveDbPlatformFromEnv } from './dbPlatformEnv.js';
5
7
  export { UserCache } from './UserCache.js';
8
+ export { SystemUserFieldAccessLossReason, FindSystemUserFieldAccessViolations, SystemUserFieldAccessViolation, SystemUserHoldsRole, SystemUserFieldAccessSweepOptions, } from './systemUserFieldAccess.js';
9
+ export { SystemUserFieldAccessCheck, LoadSystemUserFieldAccessCheck } from './SystemUserFieldAccessCheck.js';
6
10
  export { SqlLoggingOptions, SqlLoggingSession } from './types.js';
7
11
  export { SqlLoggingSessionImpl } from './SqlLogger.js';
8
12
  export { QueryCompositionEngine, CompositionCTEInfo, CompositionResult } from './queryCompositionEngine.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACvH,YAAY,EACR,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACH,aAAa,EACb,0BAA0B,EAC1B,4BAA4B,EAC5B,mBAAmB,EACnB,eAAe,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAC5G,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACtH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC7H,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,eAAe,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAGvH,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EACR,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACH,aAAa,EACb,0BAA0B,EAC1B,4BAA4B,EAC5B,mBAAmB,EACnB,eAAe,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACH,+BAA+B,EAC/B,mCAAmC,EACnC,8BAA8B,EAC9B,mBAAmB,EACnB,iCAAiC,GACpC,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,0BAA0B,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AAC7G,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAC5G,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACtH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC7H,YAAY,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,eAAe,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,15 @@
1
1
  export { GenericDatabaseProvider, DoomedTransactionError } from './GenericDatabaseProvider.js';
2
+ // Side-effect import: registers DatabaseWellKnownUserSource with the class factory so any
3
+ // process holding a database provider can resolve MJ's built-in accounts.
4
+ export { DatabaseWellKnownUserSource } from './DatabaseWellKnownUserSource.js';
5
+ export { SystemUserID } from './systemUser.js';
2
6
  export { shouldIncludeFieldInParams, needsClearCompanionBroadRule, projectedParamCount, useJsonArgShape, } from './crudSprocFieldRules.js';
3
7
  export { resolveDbPlatformFromEnv } from './dbPlatformEnv.js';
4
8
  export { UserCache } from './UserCache.js';
9
+ export { SystemUserFieldAccessLossReason, FindSystemUserFieldAccessViolations, SystemUserHoldsRole, } from './systemUserFieldAccess.js';
10
+ // Side-effect import: registers the startup sweep that reports a system user which has lost
11
+ // field-level access on an FLS-enabled entity.
12
+ export { SystemUserFieldAccessCheck, LoadSystemUserFieldAccessCheck } from './SystemUserFieldAccessCheck.js';
5
13
  export { SqlLoggingSessionImpl } from './SqlLogger.js';
6
14
  export { QueryCompositionEngine } from './queryCompositionEngine.js';
7
15
  export { QueryPagingEngine } from './queryPagingEngine.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAA0B,MAAM,8BAA8B,CAAC;AAOvH,OAAO,EAEH,0BAA0B,EAC1B,4BAA4B,EAC5B,mBAAmB,EACnB,eAAe,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAyC,MAAM,6BAA6B,CAAC;AAC5G,OAAO,EAAE,iBAAiB,EAAoB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAmE,MAAM,qBAAqB,CAAC;AACtH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,uEAAuE;AACvE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAA0B,MAAM,8BAA8B,CAAC;AACvH,0FAA0F;AAC1F,0EAA0E;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAO/C,OAAO,EAEH,0BAA0B,EAC1B,4BAA4B,EAC5B,mBAAmB,EACnB,eAAe,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACH,+BAA+B,EAC/B,mCAAmC,EAEnC,mBAAmB,GAEtB,MAAM,4BAA4B,CAAC;AACpC,4FAA4F;AAC5F,+CAA+C;AAC/C,OAAO,EAAE,0BAA0B,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AAE7G,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAyC,MAAM,6BAA6B,CAAC;AAC5G,OAAO,EAAE,iBAAiB,EAAoB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAmE,MAAM,qBAAqB,CAAC;AACtH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,uEAAuE;AACvE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC"}
@@ -97,6 +97,25 @@ export declare class QueryPagingEngine {
97
97
  * this method contains no `node-sql-parser` field knowledge.
98
98
  */
99
99
  private static applyMaxRowsViaAST;
100
+ /**
101
+ * Clauses that must come AFTER `LIMIT` in PostgreSQL, so a bare append would be illegal.
102
+ *
103
+ * Matched loosely and deliberately: a false positive (the word inside a string literal, a
104
+ * column alias, or a nested subquery) costs only a fall-through to the AST path, which is
105
+ * the behaviour that shipped before. A false negative would emit invalid SQL, so the test
106
+ * errs heavily toward abstaining.
107
+ */
108
+ private static readonly CLAUSES_THAT_FOLLOW_LIMIT;
109
+ /**
110
+ * Returns `sql` with the row cap appended as a trailing clause, or `null` when that is not
111
+ * provably safe and the caller should fall back to AST injection.
112
+ *
113
+ * Applies only to dialects whose cap is a suffix (`LIMIT N`). SQL Server caps with a `TOP N`
114
+ * prefix that has to go between `SELECT` and the select list — a position no append can
115
+ * reach — so it is left to the AST path, where the round-trip is harmless anyway because
116
+ * T-SQL is not case-sensitive about the identifiers involved.
117
+ */
118
+ private static appendTrailingCap;
100
119
  /**
101
120
  * Determines whether the given params indicate paging should be applied.
102
121
  */
@@ -1 +1 @@
1
- {"version":3,"file":"queryPagingEngine.d.ts","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE5F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,iBAAiB;IAE1B;;;;;;;;OAQG;IACH,MAAM,CAAC,cAAc,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB,GAC3B,gBAAgB;IAUnB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,MAAM,CAAC,eAAe,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB,GAC3B,MAAM;IAsCT;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAyBxB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAwCjC;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAQrF,OAAO,CAAC,MAAM,CAAC,YAAY;IAyB3B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAoBrC;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAe5B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAkB7B;;;;;;OAMG;IACH,MAAM,CAAC,cAAc,CACjB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,UAAU,GAAG,MAA+B,GACtD;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IAW5D;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE;IAOxE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAe3B,OAAO,CAAC,MAAM,CAAC,UAAU;CAG5B"}
1
+ {"version":3,"file":"queryPagingEngine.d.ts","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE5F;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,iBAAiB;IAE1B;;;;;;;;OAQG;IACH,MAAM,CAAC,cAAc,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB,GAC3B,gBAAgB;IAUnB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,MAAM,CAAC,eAAe,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB,GAC3B,MAAM;IAsCT;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAyBxB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA2DjC;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CACgC;IAEjF;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAOhC;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAQrF,OAAO,CAAC,MAAM,CAAC,YAAY;IAyB3B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAoBrC;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAe5B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAkB7B;;;;;;OAMG;IACH,MAAM,CAAC,cAAc,CACjB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,UAAU,GAAG,MAA+B,GACtD;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IAW5D;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE;IAOxE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAe3B,OAAO,CAAC,MAAM,CAAC,UAAU;CAG5B"}
@@ -167,6 +167,25 @@ export class QueryPagingEngine {
167
167
  // Existing numeric cap — only modify when the requested cap is tighter.
168
168
  if (existing && existing.value <= cap)
169
169
  return { outcome: 'capped', sql };
170
+ // No cap at all, on a dialect that caps with a trailing clause — append it as TEXT.
171
+ //
172
+ // `SetOuterCap` + `ToSQL()` below re-emits the WHOLE statement from the AST, and
173
+ // node-sql-parser normalizes as it generates: keywords come back upper-cased and
174
+ // identifiers re-quoted. Appending one clause should not rewrite the caller's SQL, and
175
+ // on PostgreSQL that rewrite is not cosmetic — it is a correctness bug, because the
176
+ // provider's identifier auto-quoter runs afterwards over an upper-cased statement and
177
+ // quotes any keyword its allowlist is missing. A query written `ORDER BY x ASC nulls
178
+ // last` came back `ASC NULLS LAST`, was quoted to `ASC "NULLS" "LAST"`, and failed with
179
+ // `syntax error at or near ""NULLS""` — SQL the caller never wrote.
180
+ //
181
+ // The append is only taken where it is provably equivalent to the AST injection; every
182
+ // other shape falls through to the existing path, so this can narrow the blast radius
183
+ // but never change a result.
184
+ if (!existing) {
185
+ const appended = QueryPagingEngine.appendTrailingCap(sql, cap, dialect);
186
+ if (appended)
187
+ return { outcome: 'capped', sql: appended };
188
+ }
170
189
  // No cap (or a looser one) — inject/replace.
171
190
  parsed.SetOuterCap(cap);
172
191
  try {
@@ -176,6 +195,32 @@ export class QueryPagingEngine {
176
195
  return { outcome: 'unparseable' };
177
196
  }
178
197
  }
198
+ /**
199
+ * Clauses that must come AFTER `LIMIT` in PostgreSQL, so a bare append would be illegal.
200
+ *
201
+ * Matched loosely and deliberately: a false positive (the word inside a string literal, a
202
+ * column alias, or a nested subquery) costs only a fall-through to the AST path, which is
203
+ * the behaviour that shipped before. A false negative would emit invalid SQL, so the test
204
+ * errs heavily toward abstaining.
205
+ */
206
+ static { this.CLAUSES_THAT_FOLLOW_LIMIT = /\b(?:OFFSET|FETCH|FOR\s+(?:UPDATE|SHARE|NO\s+KEY\s+UPDATE|KEY\s+SHARE))\b/i; }
207
+ /**
208
+ * Returns `sql` with the row cap appended as a trailing clause, or `null` when that is not
209
+ * provably safe and the caller should fall back to AST injection.
210
+ *
211
+ * Applies only to dialects whose cap is a suffix (`LIMIT N`). SQL Server caps with a `TOP N`
212
+ * prefix that has to go between `SELECT` and the select list — a position no append can
213
+ * reach — so it is left to the AST path, where the round-trip is harmless anyway because
214
+ * T-SQL is not case-sensitive about the identifiers involved.
215
+ */
216
+ static appendTrailingCap(sql, cap, dialect) {
217
+ const limit = dialect.LimitClause(cap);
218
+ if (!limit.suffix || limit.prefix)
219
+ return null;
220
+ if (QueryPagingEngine.CLAUSES_THAT_FOLLOW_LIMIT.test(sql))
221
+ return null;
222
+ return `${sql}\n${limit.suffix}`;
223
+ }
179
224
  /**
180
225
  * Determines whether the given params indicate paging should be applied.
181
226
  */
@@ -1 +1 @@
1
- {"version":3,"file":"queryPagingEngine.js","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queryPagingEngine.js","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { UserInfo } from '@memberjunction/core';
2
+ /**
3
+ * ID of the MJ **system user** — the account the server runs its own work as.
4
+ *
5
+ * Canonical definition. Seeded by the baseline on both platforms; do not change it without a
6
+ * migration.
7
+ *
8
+ * It lives in a server-side package because it is a server concept — a browser has no system
9
+ * account and no use for its ID. Both concrete providers (SQL Server and PostgreSQL) depend on
10
+ * this package and neither depends on the other, so one definition serves both.
11
+ *
12
+ * Code that needs to ASK whether a user is the system user should call
13
+ * `WellKnownUserSource.Instance.IsSystemUser(user)` instead; this constant is for the
14
+ * implementations that have to know the actual value.
15
+ */
16
+ export declare const SystemUserID: string;
17
+ /**
18
+ * True when this user is the MJ system user. Null/undefined-safe, and case-insensitive because
19
+ * the same UUID arrives with different casing depending on its source (a client-minted
20
+ * lowercase value vs. an uppercase one loaded from SQL Server).
21
+ *
22
+ * Not exported from the package: callers ask
23
+ * `WellKnownUserSource.Instance.IsSystemUser(user)`, which works in shared code and answers
24
+ * false where no server-side source is registered. This backs the implementation of that seam.
25
+ */
26
+ export declare function IsSystemUser(user: UserInfo | null | undefined): boolean;
27
+ //# sourceMappingURL=systemUser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemUser.d.ts","sourceRoot":"","sources":["../src/systemUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGhD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,EAAE,MAA+C,CAAC;AAE3E;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEvE"}
@@ -0,0 +1,29 @@
1
+ import { UUIDsEqual } from '@memberjunction/global';
2
+ /**
3
+ * ID of the MJ **system user** — the account the server runs its own work as.
4
+ *
5
+ * Canonical definition. Seeded by the baseline on both platforms; do not change it without a
6
+ * migration.
7
+ *
8
+ * It lives in a server-side package because it is a server concept — a browser has no system
9
+ * account and no use for its ID. Both concrete providers (SQL Server and PostgreSQL) depend on
10
+ * this package and neither depends on the other, so one definition serves both.
11
+ *
12
+ * Code that needs to ASK whether a user is the system user should call
13
+ * `WellKnownUserSource.Instance.IsSystemUser(user)` instead; this constant is for the
14
+ * implementations that have to know the actual value.
15
+ */
16
+ export const SystemUserID = 'ecafccec-6a37-ef11-86d4-000d3a4e707e';
17
+ /**
18
+ * True when this user is the MJ system user. Null/undefined-safe, and case-insensitive because
19
+ * the same UUID arrives with different casing depending on its source (a client-minted
20
+ * lowercase value vs. an uppercase one loaded from SQL Server).
21
+ *
22
+ * Not exported from the package: callers ask
23
+ * `WellKnownUserSource.Instance.IsSystemUser(user)`, which works in shared code and answers
24
+ * false where no server-side source is registered. This backs the implementation of that seam.
25
+ */
26
+ export function IsSystemUser(user) {
27
+ return !!user?.ID && UUIDsEqual(user.ID, SystemUserID);
28
+ }
29
+ //# sourceMappingURL=systemUser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemUser.js","sourceRoot":"","sources":["../src/systemUser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAW,sCAAsC,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAiC;IAC1D,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @fileoverview Keeping the MJ system user's own field access intact, now that field-level
3
+ * security has no runtime exemption for anybody.
4
+ *
5
+ * ## Why this file exists
6
+ *
7
+ * The system user is the account the server runs its own work as. It pre-warms the shared engine
8
+ * caches at startup, and in task mode (job and agent runners) engines instead load on first touch,
9
+ * so whichever caller gets there first configures the engine for the whole process. Those caches
10
+ * are process-wide. A system user that cannot read a column therefore does not just fail its own
11
+ * query — it leaves a partially loaded record in a cache every later user reads, with nothing at
12
+ * the point of failure pointing back at the permission row that caused it.
13
+ *
14
+ * Field security deliberately has **no exempt user** at runtime: `GetUserFieldPermissions` has no
15
+ * identity branch at all, and the system user's access comes from ordinary `Allow` rows that
16
+ * snapshot initialization writes for the standard roles it holds. That is a better design — an
17
+ * administrator can see the rows and reason about them, where a code bypass is invisible exactly
18
+ * where access is decided. But it moves the burden here: something has to stop those rows being
19
+ * taken away.
20
+ *
21
+ * ## Why "does this rule contain a Deny?" is not enough
22
+ *
23
+ * Whether a change restricts a user is a property of the **aggregate across every role they
24
+ * hold**, never of one rule in isolation. Three ways to lock the system user out without writing
25
+ * a single `Deny`:
26
+ *
27
+ * 1. set `ReadAccess = 'No Access'` on each of its roles in turn — every save individually
28
+ * harmless, the last one leaves no `Allow` standing;
29
+ * 2. delete its roles' `Allow` rows;
30
+ * 3. reach either state through direct SQL, which no entity-layer guard sees at all.
31
+ *
32
+ * So the save-time guard evaluates the **projected aggregate** — the rules as they would stand
33
+ * after the proposed change — and {@link FindSystemUserFieldAccessViolations} sweeps for state
34
+ * that got there by some other route.
35
+ *
36
+ * @module @memberjunction/generic-database-provider
37
+ */
38
+ import { EntityFieldInfo, EntityInfo, FieldPermissionRuleForRole, IMetadataProvider, UserInfo } from '@memberjunction/core';
39
+ /**
40
+ * One field the MJ system user cannot fully use on an entity where field security is enabled.
41
+ */
42
+ export type SystemUserFieldAccessViolation = {
43
+ EntityName: string;
44
+ FieldName: string;
45
+ /** The verb the system user has lost, relative to its entity-level access. */
46
+ Verb: 'read' | 'update' | 'create';
47
+ };
48
+ /**
49
+ * Why a proposed field-permission state would leave the MJ system user short of its entity-level
50
+ * access, or null when it would not.
51
+ *
52
+ * Callers pass the rules **as they would be after** their change — with the edited row's new
53
+ * values substituted, or the deleted row removed. Classifying the changed row on its own cannot
54
+ * answer this question; see the module comment.
55
+ *
56
+ * Answers null (permits the change) in three cases, each deliberate:
57
+ *
58
+ * - **No system user resolves.** A cold `UserCache` is the normal state during a process's own
59
+ * bootstrap. Blocking an administrator on missing state would be worse than the risk, and
60
+ * {@link FindSystemUserFieldAccessViolations} runs at startup precisely to catch whatever slips
61
+ * through here.
62
+ * - **The field is unrestrictable.** Primary keys, `__mj_` columns and the security-configuration
63
+ * entities are forced open by the aggregation regardless of any row, so no rule about them can
64
+ * restrict anyone.
65
+ * - **The system user has no entity-level read.** It is already denied one level up, where the
66
+ * entity permission check has no exemption either, so field rules change nothing for it here.
67
+ *
68
+ * Note this does NOT gate on `EnableFieldLevelSecurity`. Rules on a disabled entity are dormant
69
+ * rather than gone — disabling deliberately preserves them — so gating would leave a three-step
70
+ * hole: disable, strip the system user's rows, re-enable.
71
+ *
72
+ * @param entity the entity the field belongs to
73
+ * @param field the field whose rules are changing
74
+ * @param projectedRules every rule that would bind to this field after the change
75
+ */
76
+ export declare function SystemUserFieldAccessLossReason(entity: EntityInfo | null | undefined, field: EntityFieldInfo | null | undefined, projectedRules: readonly FieldPermissionRuleForRole[]): string | null;
77
+ /** Narrowing for {@link FindSystemUserFieldAccessViolations}. */
78
+ export type SystemUserFieldAccessSweepOptions = {
79
+ /**
80
+ * Evaluate as though the system user did NOT hold this role.
81
+ *
82
+ * For the guard on **removing** a role from the account: taking a role away removes its rules
83
+ * from the aggregate, which can strip the last `Allow` just as surely as editing one. Both the
84
+ * field rules and the entity-level ceiling are re-evaluated without it, so a removal that also
85
+ * costs the account its entity-level read is correctly permitted — it is then denied one level
86
+ * up, and field rules decide nothing.
87
+ */
88
+ WithoutRoleID?: string;
89
+ };
90
+ /**
91
+ * Every field on an FLS-enabled entity that the system user cannot fully use.
92
+ *
93
+ * The backstop for state the save-time guard never saw: direct SQL, a migration, or a save made
94
+ * while the user cache was cold. Walks loaded metadata only — no queries — and skips entities with
95
+ * field security switched off, which is nearly all of them.
96
+ *
97
+ * @param provider the provider whose metadata to walk
98
+ * @param systemUser the account to check; defaults to the user cache's system user
99
+ * @param options optional projection — see {@link SystemUserFieldAccessSweepOptions}
100
+ */
101
+ export declare function FindSystemUserFieldAccessViolations(provider: IMetadataProvider | null | undefined, systemUser?: UserInfo | null, options?: SystemUserFieldAccessSweepOptions): SystemUserFieldAccessViolation[];
102
+ /**
103
+ * Whether the MJ system user holds the given role.
104
+ *
105
+ * The cheap pre-check for the save-time guard. Field aggregation only ever consults rules bound to
106
+ * a role the user holds, so a change to any other role's rule provably cannot move the system
107
+ * user's access — which lets callers skip the work of projecting and re-aggregating for the
108
+ * overwhelming majority of permission edits.
109
+ *
110
+ * False on a cold cache, matching {@link SystemUserFieldAccessLossReason}'s posture: with no system
111
+ * user to reason about there is nothing to protect, and the startup sweep is the backstop.
112
+ */
113
+ export declare function SystemUserHoldsRole(roleID: string | null | undefined): boolean;
114
+ //# sourceMappingURL=systemUserFieldAccess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemUserFieldAccess.d.ts","sourceRoot":"","sources":["../src/systemUserFieldAccess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EACH,eAAe,EACf,UAAU,EACV,0BAA0B,EAC1B,iBAAiB,EACjB,QAAQ,EACX,MAAM,sBAAsB,CAAC;AAI9B;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACtC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,+BAA+B,CAC3C,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACrC,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EACzC,cAAc,EAAE,SAAS,0BAA0B,EAAE,GACtD,MAAM,GAAG,IAAI,CAwBf;AAED,iEAAiE;AACjE,MAAM,MAAM,iCAAiC,GAAG;IAC5C;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,mCAAmC,CAC/C,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,EAC9C,UAAU,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC5B,OAAO,GAAE,iCAAsC,GAChD,8BAA8B,EAAE,CAuBlC;AA2CD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAM9E"}