@memberjunction/generic-database-provider 6.1.0-edge.6 → 6.1.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.
- package/dist/DatabaseWellKnownUserSource.d.ts +48 -0
- package/dist/DatabaseWellKnownUserSource.d.ts.map +1 -0
- package/dist/DatabaseWellKnownUserSource.js +101 -0
- package/dist/DatabaseWellKnownUserSource.js.map +1 -0
- package/dist/GenericDatabaseProvider.d.ts +45 -3
- package/dist/GenericDatabaseProvider.d.ts.map +1 -1
- package/dist/GenericDatabaseProvider.js +251 -21
- package/dist/GenericDatabaseProvider.js.map +1 -1
- package/dist/SystemUserFieldAccessCheck.d.ts +64 -0
- package/dist/SystemUserFieldAccessCheck.d.ts.map +1 -0
- package/dist/SystemUserFieldAccessCheck.js +137 -0
- package/dist/SystemUserFieldAccessCheck.js.map +1 -0
- package/dist/UserCache.d.ts.map +1 -1
- package/dist/UserCache.js +2 -2
- package/dist/UserCache.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/queryPagingEngine.d.ts +19 -0
- package/dist/queryPagingEngine.d.ts.map +1 -1
- package/dist/queryPagingEngine.js +45 -0
- package/dist/queryPagingEngine.js.map +1 -1
- package/dist/systemUser.d.ts +27 -0
- package/dist/systemUser.d.ts.map +1 -0
- package/dist/systemUser.js +29 -0
- package/dist/systemUser.js.map +1 -0
- package/dist/systemUserFieldAccess.d.ts +114 -0
- package/dist/systemUserFieldAccess.d.ts.map +1 -0
- package/dist/systemUserFieldAccess.js +198 -0
- package/dist/systemUserFieldAccess.js.map +1 -0
- package/package.json +14 -14
|
@@ -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":"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"}
|
package/dist/UserCache.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
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
|
|
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
|
package/dist/UserCache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserCache.js","sourceRoot":"","sources":["../src/UserCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAA6B,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
|
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;
|
|
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"}
|