@mikro-orm/core 7.2.0-dev.14 → 7.2.0-dev.15
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/EntityManager.d.ts +30 -2
- package/EntityManager.js +192 -40
- package/MikroORM.js +3 -0
- package/connections/Connection.d.ts +3 -1
- package/entity/Collection.js +4 -2
- package/entity/EntityLoader.js +1 -1
- package/entity/defineEntity.d.ts +3 -0
- package/enums.d.ts +3 -1
- package/errors.d.ts +31 -0
- package/errors.js +72 -0
- package/exceptions.d.ts +5 -0
- package/exceptions.js +5 -0
- package/index.d.ts +1 -1
- package/metadata/MetadataDiscovery.d.ts +1 -0
- package/metadata/MetadataDiscovery.js +31 -0
- package/metadata/types.d.ts +5 -1
- package/package.json +1 -1
- package/platforms/Platform.d.ts +9 -0
- package/platforms/Platform.js +40 -0
- package/typings.d.ts +36 -0
- package/typings.js +1 -0
- package/unit-of-work/UnitOfWork.js +1 -0
- package/utils/Configuration.d.ts +15 -1
- package/utils/Configuration.js +11 -1
- package/utils/QueryHelper.d.ts +12 -0
- package/utils/QueryHelper.js +63 -0
- package/utils/TransactionManager.js +1 -1
- package/utils/Utils.d.ts +2 -0
- package/utils/Utils.js +5 -1
- package/utils/env-vars.js +1 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/rls-utils.d.ts +35 -0
- package/utils/rls-utils.js +97 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { MetadataStorage } from '../metadata/MetadataStorage.js';
|
|
2
|
+
import type { Dictionary, FilterDef } from '../typings.js';
|
|
3
|
+
/** An `rls`-flagged filter definition together with the entity it is declared on. @internal */
|
|
4
|
+
export interface RlsFilterEntry {
|
|
5
|
+
filter: FilterDef;
|
|
6
|
+
entityName: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Collects all `rls`-flagged filter definitions with the given name (only entity-scoped filters can be `rls`).
|
|
10
|
+
* The full name -> defs lookup is built once and cached on the shared (immutable) MetadataStorage, so repeated
|
|
11
|
+
* `setFilterParams` calls and forks reuse it instead of walking every entity each time.
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export declare function findRlsFilterDefs(metadata: MetadataStorage, name: string): RlsFilterEntry[];
|
|
15
|
+
/**
|
|
16
|
+
* Drops the cached `rls` filter lookup — `MikroORM.discoverEntity()` mutates the shared MetadataStorage,
|
|
17
|
+
* so a lookup built before the call would miss the newly discovered filters.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export declare function clearRlsFilterDefsCache(metadata: MetadataStorage): void;
|
|
22
|
+
/**
|
|
23
|
+
* Computes the `rls` session variables a set of same-named filter defs stages for the given args, mirroring the
|
|
24
|
+
* policy compilation (`current_setting` names and custom `setting` binding). Shared by staging and `fork({ session })`.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function computeRlsFilterVariables(filters: RlsFilterEntry[], args: Dictionary): Dictionary<string | number | boolean | Date>;
|
|
28
|
+
/**
|
|
29
|
+
* Computes which staged session variables a `setFilterParams` call may prune: the variables the OLD args staged for
|
|
30
|
+
* this filter that the new args no longer set, minus any variable another filter's current params still stage
|
|
31
|
+
* (a custom `setting` name can be shared by differently named filters). Recomputing from the old args rather than
|
|
32
|
+
* matching by prefix keeps a filter named `tenant` from also pruning a `tenant.x` filter's `mikro.tenant.x.*` variables.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
export declare function computeRemovedRlsVariables(metadata: MetadataStorage, name: string, filters: RlsFilterEntry[], previousArgs: Dictionary, nextVariables: Dictionary, allFilterParams: Dictionary<Dictionary>): string[];
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { MetadataError, ValidationError } from '../errors.js';
|
|
2
|
+
import { QueryHelper } from './QueryHelper.js';
|
|
3
|
+
import { Utils } from './Utils.js';
|
|
4
|
+
/** Lazily-built `rls` filter lookup keyed by the shared (immutable) MetadataStorage, so all forks reuse it. */
|
|
5
|
+
const rlsFilterDefs = new WeakMap();
|
|
6
|
+
/**
|
|
7
|
+
* Collects all `rls`-flagged filter definitions with the given name (only entity-scoped filters can be `rls`).
|
|
8
|
+
* The full name -> defs lookup is built once and cached on the shared (immutable) MetadataStorage, so repeated
|
|
9
|
+
* `setFilterParams` calls and forks reuse it instead of walking every entity each time.
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export function findRlsFilterDefs(metadata, name) {
|
|
13
|
+
let cache = rlsFilterDefs.get(metadata);
|
|
14
|
+
if (!cache) {
|
|
15
|
+
cache = new Map();
|
|
16
|
+
for (const meta of metadata) {
|
|
17
|
+
for (const filterName of Object.keys(meta.filters)) {
|
|
18
|
+
const filter = meta.filters[filterName];
|
|
19
|
+
if (!filter.rls) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const defs = cache.get(filterName) ?? [];
|
|
23
|
+
// inheritance shares the same filter object across base and child metadata — keep a single entry
|
|
24
|
+
if (!defs.some(d => d.filter === filter)) {
|
|
25
|
+
defs.push({ filter, entityName: meta.className });
|
|
26
|
+
}
|
|
27
|
+
cache.set(filterName, defs);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
rlsFilterDefs.set(metadata, cache);
|
|
31
|
+
}
|
|
32
|
+
return cache.get(name) ?? [];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Drops the cached `rls` filter lookup — `MikroORM.discoverEntity()` mutates the shared MetadataStorage,
|
|
36
|
+
* so a lookup built before the call would miss the newly discovered filters.
|
|
37
|
+
*
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export function clearRlsFilterDefsCache(metadata) {
|
|
41
|
+
rlsFilterDefs.delete(metadata);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Computes the `rls` session variables a set of same-named filter defs stages for the given args, mirroring the
|
|
45
|
+
* policy compilation (`current_setting` names and custom `setting` binding). Shared by staging and `fork({ session })`.
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
export function computeRlsFilterVariables(filters, args) {
|
|
49
|
+
const variables = {};
|
|
50
|
+
for (const { filter, entityName } of filters) {
|
|
51
|
+
const setting = typeof filter.rls === 'object' ? filter.rls.setting : undefined;
|
|
52
|
+
let settingArg;
|
|
53
|
+
if (setting) {
|
|
54
|
+
// mirror the policy compilation — a custom `setting` binds the single argument the condition accesses
|
|
55
|
+
const accessed = new Set();
|
|
56
|
+
QueryHelper.resolveRlsFilterCond(filter, accessed, entityName);
|
|
57
|
+
if (accessed.size > 1) {
|
|
58
|
+
throw MetadataError.rlsFilterMultiArgSetting(filter.name, [...accessed]);
|
|
59
|
+
}
|
|
60
|
+
settingArg = [...accessed][0];
|
|
61
|
+
}
|
|
62
|
+
for (const key of Object.keys(args)) {
|
|
63
|
+
const value = args[key];
|
|
64
|
+
// treat `undefined` like an omitted arg — staging it would serialize as the literal string 'undefined'
|
|
65
|
+
if (value === undefined) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// a non-scalar arg has no equivalent in the compiled `= current_setting(...)` comparison — the app-level
|
|
69
|
+
// filter would apply `$in`/`is null` semantics while the policy compares against `String(value)`
|
|
70
|
+
if (value === null || (typeof value === 'object' && !(value instanceof Date))) {
|
|
71
|
+
throw ValidationError.cannotStageNonScalarSessionVariable(filter.name, key);
|
|
72
|
+
}
|
|
73
|
+
const settingName = key === settingArg ? setting : Utils.getRlsSettingName(filter.name, key);
|
|
74
|
+
variables[settingName] = value;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return variables;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Computes which staged session variables a `setFilterParams` call may prune: the variables the OLD args staged for
|
|
81
|
+
* this filter that the new args no longer set, minus any variable another filter's current params still stage
|
|
82
|
+
* (a custom `setting` name can be shared by differently named filters). Recomputing from the old args rather than
|
|
83
|
+
* matching by prefix keeps a filter named `tenant` from also pruning a `tenant.x` filter's `mikro.tenant.x.*` variables.
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
export function computeRemovedRlsVariables(metadata, name, filters, previousArgs, nextVariables, allFilterParams) {
|
|
87
|
+
const removed = Object.keys(computeRlsFilterVariables(filters, previousArgs)).filter(key => !(key in nextVariables));
|
|
88
|
+
const keptByOthers = new Set();
|
|
89
|
+
for (const otherName of removed.length > 0 ? Object.keys(allFilterParams) : []) {
|
|
90
|
+
if (otherName !== name) {
|
|
91
|
+
for (const key of Object.keys(computeRlsFilterVariables(findRlsFilterDefs(metadata, otherName), allFilterParams[otherName]))) {
|
|
92
|
+
keptByOthers.add(key);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return removed.filter(key => !keptByOthers.has(key));
|
|
97
|
+
}
|