@memberjunction/core 6.2.0-edge.5 → 6.2.0-edge.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/dist/generic/BaseEntitySaveQueue.d.ts +15 -0
  2. package/dist/generic/BaseEntitySaveQueue.d.ts.map +1 -1
  3. package/dist/generic/BaseEntitySaveQueue.js +21 -0
  4. package/dist/generic/BaseEntitySaveQueue.js.map +1 -1
  5. package/dist/generic/EntityFieldRules.d.ts.map +1 -1
  6. package/dist/generic/EntityFieldRules.js +1 -0
  7. package/dist/generic/EntityFieldRules.js.map +1 -1
  8. package/dist/generic/alternateBaseViews.d.ts +119 -0
  9. package/dist/generic/alternateBaseViews.d.ts.map +1 -0
  10. package/dist/generic/alternateBaseViews.js +223 -0
  11. package/dist/generic/alternateBaseViews.js.map +1 -0
  12. package/dist/generic/baseEngine.d.ts +171 -17
  13. package/dist/generic/baseEngine.d.ts.map +1 -1
  14. package/dist/generic/baseEngine.js +722 -117
  15. package/dist/generic/baseEngine.js.map +1 -1
  16. package/dist/generic/baseEngineRegistry.d.ts.map +1 -1
  17. package/dist/generic/baseEngineRegistry.js +2 -1
  18. package/dist/generic/baseEngineRegistry.js.map +1 -1
  19. package/dist/generic/baseEntity.d.ts +216 -21
  20. package/dist/generic/baseEntity.d.ts.map +1 -1
  21. package/dist/generic/baseEntity.js +969 -100
  22. package/dist/generic/baseEntity.js.map +1 -1
  23. package/dist/generic/baseRemotableOperation.d.ts +95 -6
  24. package/dist/generic/baseRemotableOperation.d.ts.map +1 -1
  25. package/dist/generic/baseRemotableOperation.js +112 -8
  26. package/dist/generic/baseRemotableOperation.js.map +1 -1
  27. package/dist/generic/contextTokens.d.ts +136 -0
  28. package/dist/generic/contextTokens.d.ts.map +1 -0
  29. package/dist/generic/contextTokens.js +319 -0
  30. package/dist/generic/contextTokens.js.map +1 -0
  31. package/dist/generic/databaseProviderBase.d.ts +103 -5
  32. package/dist/generic/databaseProviderBase.d.ts.map +1 -1
  33. package/dist/generic/databaseProviderBase.js +381 -52
  34. package/dist/generic/databaseProviderBase.js.map +1 -1
  35. package/dist/generic/embeddedRecord.d.ts +6 -0
  36. package/dist/generic/embeddedRecord.d.ts.map +1 -1
  37. package/dist/generic/embeddedRecord.js +15 -1
  38. package/dist/generic/embeddedRecord.js.map +1 -1
  39. package/dist/generic/entityCompanion.d.ts +7 -0
  40. package/dist/generic/entityCompanion.d.ts.map +1 -1
  41. package/dist/generic/entityCompanion.js +8 -0
  42. package/dist/generic/entityCompanion.js.map +1 -1
  43. package/dist/generic/entityInfo.d.ts +234 -9
  44. package/dist/generic/entityInfo.d.ts.map +1 -1
  45. package/dist/generic/entityInfo.js +592 -77
  46. package/dist/generic/entityInfo.js.map +1 -1
  47. package/dist/generic/entityValueFieldSecurity.d.ts +139 -0
  48. package/dist/generic/entityValueFieldSecurity.d.ts.map +1 -0
  49. package/dist/generic/entityValueFieldSecurity.js +250 -0
  50. package/dist/generic/entityValueFieldSecurity.js.map +1 -0
  51. package/dist/generic/externalDataSourceReadRouter.d.ts +10 -0
  52. package/dist/generic/externalDataSourceReadRouter.d.ts.map +1 -1
  53. package/dist/generic/externalDataSourceReadRouter.js +12 -0
  54. package/dist/generic/externalDataSourceReadRouter.js.map +1 -1
  55. package/dist/generic/fieldSecuritySQLGate.d.ts +359 -0
  56. package/dist/generic/fieldSecuritySQLGate.d.ts.map +1 -0
  57. package/dist/generic/fieldSecuritySQLGate.js +902 -0
  58. package/dist/generic/fieldSecuritySQLGate.js.map +1 -0
  59. package/dist/generic/indexRestrictedFields.d.ts +47 -0
  60. package/dist/generic/indexRestrictedFields.d.ts.map +1 -0
  61. package/dist/generic/indexRestrictedFields.js +129 -0
  62. package/dist/generic/indexRestrictedFields.js.map +1 -0
  63. package/dist/generic/interfaces.d.ts +64 -2
  64. package/dist/generic/interfaces.d.ts.map +1 -1
  65. package/dist/generic/interfaces.js.map +1 -1
  66. package/dist/generic/listMembershipFilter.d.ts +5 -0
  67. package/dist/generic/listMembershipFilter.d.ts.map +1 -0
  68. package/dist/generic/listMembershipFilter.js +23 -0
  69. package/dist/generic/listMembershipFilter.js.map +1 -0
  70. package/dist/generic/localCacheManager.d.ts +126 -14
  71. package/dist/generic/localCacheManager.d.ts.map +1 -1
  72. package/dist/generic/localCacheManager.js +348 -48
  73. package/dist/generic/localCacheManager.js.map +1 -1
  74. package/dist/generic/logging.d.ts.map +1 -1
  75. package/dist/generic/logging.js +7 -1
  76. package/dist/generic/logging.js.map +1 -1
  77. package/dist/generic/metadata.d.ts +3 -2
  78. package/dist/generic/metadata.d.ts.map +1 -1
  79. package/dist/generic/metadata.js +5 -2
  80. package/dist/generic/metadata.js.map +1 -1
  81. package/dist/generic/platformSQL.d.ts +54 -0
  82. package/dist/generic/platformSQL.d.ts.map +1 -1
  83. package/dist/generic/platformSQL.js +55 -0
  84. package/dist/generic/platformSQL.js.map +1 -1
  85. package/dist/generic/providerBase.d.ts +408 -57
  86. package/dist/generic/providerBase.d.ts.map +1 -1
  87. package/dist/generic/providerBase.js +1051 -310
  88. package/dist/generic/providerBase.js.map +1 -1
  89. package/dist/generic/queryInfo.d.ts +13 -0
  90. package/dist/generic/queryInfo.d.ts.map +1 -1
  91. package/dist/generic/queryInfo.js +13 -0
  92. package/dist/generic/queryInfo.js.map +1 -1
  93. package/dist/generic/queryInfoInterfaces.d.ts +8 -0
  94. package/dist/generic/queryInfoInterfaces.d.ts.map +1 -1
  95. package/dist/generic/queryTemplateContext.d.ts +49 -0
  96. package/dist/generic/queryTemplateContext.d.ts.map +1 -0
  97. package/dist/generic/queryTemplateContext.js +113 -0
  98. package/dist/generic/queryTemplateContext.js.map +1 -0
  99. package/dist/generic/recordChangeFieldSecurity.d.ts.map +1 -1
  100. package/dist/generic/recordChangeFieldSecurity.js +13 -2
  101. package/dist/generic/recordChangeFieldSecurity.js.map +1 -1
  102. package/dist/generic/relatedRecordCollection.d.ts +18 -0
  103. package/dist/generic/relatedRecordCollection.d.ts.map +1 -1
  104. package/dist/generic/relatedRecordCollection.js +55 -7
  105. package/dist/generic/relatedRecordCollection.js.map +1 -1
  106. package/dist/generic/remoteOperationDispatch.d.ts.map +1 -1
  107. package/dist/generic/remoteOperationDispatch.js +14 -2
  108. package/dist/generic/remoteOperationDispatch.js.map +1 -1
  109. package/dist/generic/runQuery.d.ts +42 -0
  110. package/dist/generic/runQuery.d.ts.map +1 -1
  111. package/dist/generic/runQuery.js +14 -0
  112. package/dist/generic/runQuery.js.map +1 -1
  113. package/dist/generic/runQuerySQLFilterImplementations.d.ts +33 -6
  114. package/dist/generic/runQuerySQLFilterImplementations.d.ts.map +1 -1
  115. package/dist/generic/runQuerySQLFilterImplementations.js +119 -29
  116. package/dist/generic/runQuerySQLFilterImplementations.js.map +1 -1
  117. package/dist/generic/saveEntityGraphOperation.d.ts.map +1 -1
  118. package/dist/generic/saveEntityGraphOperation.js +3 -0
  119. package/dist/generic/saveEntityGraphOperation.js.map +1 -1
  120. package/dist/generic/securityInfo.d.ts +11 -0
  121. package/dist/generic/securityInfo.d.ts.map +1 -1
  122. package/dist/generic/securityInfo.js +15 -0
  123. package/dist/generic/securityInfo.js.map +1 -1
  124. package/dist/generic/telemetryManager.d.ts +9 -0
  125. package/dist/generic/telemetryManager.d.ts.map +1 -1
  126. package/dist/generic/telemetryManager.js +5 -1
  127. package/dist/generic/telemetryManager.js.map +1 -1
  128. package/dist/generic/transportError.d.ts +41 -0
  129. package/dist/generic/transportError.d.ts.map +1 -0
  130. package/dist/generic/transportError.js +167 -0
  131. package/dist/generic/transportError.js.map +1 -0
  132. package/dist/generic/util.d.ts +12 -0
  133. package/dist/generic/util.d.ts.map +1 -1
  134. package/dist/generic/util.js +52 -3
  135. package/dist/generic/util.js.map +1 -1
  136. package/dist/index.d.ts +9 -0
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +9 -0
  139. package/dist/index.js.map +1 -1
  140. package/dist/views/runView.d.ts +102 -0
  141. package/dist/views/runView.d.ts.map +1 -1
  142. package/dist/views/runView.js +40 -0
  143. package/dist/views/runView.js.map +1 -1
  144. package/dist/views/viewProperties.d.ts +55 -0
  145. package/dist/views/viewProperties.d.ts.map +1 -0
  146. package/dist/views/viewProperties.js +258 -0
  147. package/dist/views/viewProperties.js.map +1 -0
  148. package/package.json +3 -3
@@ -0,0 +1,359 @@
1
+ import { SQLScreeningDialect } from '@memberjunction/global';
2
+ import { EntityInfo, FieldSecurityError } from './entityInfo.js';
3
+ import { UserInfo } from './securityInfo.js';
4
+ /** Why {@link FieldSecuritySQLGate} refuses a piece of SQL. */
5
+ export type FieldSecurityViolationKind = 'DeniedField' | 'WholeRow' | 'Unresolvable' | 'UnknownRelation';
6
+ /** One reason {@link FieldSecuritySQLGate.FindViolation} refuses a piece of SQL. */
7
+ export interface FieldSecurityViolation {
8
+ Kind: FieldSecurityViolationKind;
9
+ /**
10
+ * `DeniedField`: the reference as the database reads it (a quoted identifier's bare name; on
11
+ * PostgreSQL an unquoted name in lower case). `WholeRow`: the construct, such as `FOR JSON`.
12
+ * `Unresolvable`: why the text could not be read. `UnknownRelation`: the relation the catalog
13
+ * does not know.
14
+ */
15
+ Reference: string;
16
+ /** The entity whose denial the reference reaches; null when the text could not be read. */
17
+ Entity: EntityInfo | null;
18
+ }
19
+ /** What {@link FieldSecuritySQLGate} needs to judge one piece of SQL for one user. */
20
+ export interface FieldSecuritySQLContext {
21
+ /** The acting user. */
22
+ User: UserInfo;
23
+ /** The dialect whose lexical rules the database applies to the text. */
24
+ Dialect: SQLScreeningDialect;
25
+ /** Every entity the provider knows, so base views and tables named in the text are recognized. */
26
+ Catalog: readonly EntityInfo[];
27
+ /**
28
+ * For a filter, sort or aggregate fragment: the entity whose view the fragment runs against.
29
+ * Its columns can be named without a qualifier, so its denied fields are always checked.
30
+ */
31
+ TargetEntity?: EntityInfo | null;
32
+ /** Entities the SQL is known to read beyond those its text names, such as a query's declared entities. */
33
+ ReadEntities?: readonly EntityInfo[];
34
+ /**
35
+ * For a whole statement, such as a saved query's SQL: refuse, for a user carrying any field
36
+ * denial, a relation that is not a CTE and not the base view or base table of a catalog entity
37
+ * (a custom view, synonym, table-valued function, temp table, or a name in another schema or
38
+ * database), and `EXEC`/`CALL`. What such a relation reads cannot be checked.
39
+ */
40
+ RefuseUnknownRelations?: boolean;
41
+ /**
42
+ * For a saved query's rendered SQL: the character offsets of `*` tokens that a structural
43
+ * reading of the whole statement has shown reach the caller only as output columns (a plain
44
+ * `*` or `alias.*` select item of a block whose rows become the result unchanged in shape).
45
+ * Such a star is not refused as a whole-row read; the caller must instead drop the denied
46
+ * columns it brings from the result. Every other star is judged as usual.
47
+ */
48
+ ProjectionStarOffsets?: ReadonlySet<number>;
49
+ }
50
+ /**
51
+ * SECURITY — the field-level security gate for SQL text a caller authors: RunView filters, sorts and
52
+ * aggregate expressions, a saved view's stored clauses, dataset item filters, and the rendered SQL
53
+ * of a saved query.
54
+ *
55
+ * Output projection alone is not enough. A user denied `Salary` who can write
56
+ * `ExtraFilter: "Salary > 200000"`, sort by it, or aggregate `MIN(Salary)` reconstructs its values
57
+ * from which rows come back. This gate refuses such text before it reaches the cache or the
58
+ * database, for every caller: client requests, agents and actions alike.
59
+ *
60
+ * ## How it reads the text
61
+ *
62
+ * The text is split into tokens with the database's own lexical rules
63
+ * (`ScanSQLForScreening`), so a name inside a string literal or a comment is not a reference, and a
64
+ * `[bracketed]` or `"quoted"` name is read as the bare name it is. Every unquoted word and quoted
65
+ * identifier is then compared with every denied field of every entity the SQL reads:
66
+ * - the entity the fragment filters (its columns can be named unqualified);
67
+ * - the entities whose base view or base table the text names, such as a subquery's FROM;
68
+ * - any entities the caller says the SQL reads.
69
+ *
70
+ * A name matches a denied field by the rule `IdentifierMatches` states, or when the two are equal
71
+ * after Unicode compatibility folding, accent stripping and case folding, the comparisons a
72
+ * database collation can make. So a look-alike spelling that the database would still resolve to
73
+ * the denied column is refused too. Each name is compared on its own, so one denied name inside
74
+ * another can never hide it.
75
+ *
76
+ * A reference qualified by an alias or view name that binds only to entities whose denied set
77
+ * does not hold that name is not a reference to a denied field. An unknown qualifier is checked
78
+ * against every restricted entity.
79
+ *
80
+ * ## Whole-row constructs
81
+ *
82
+ * For a user denied something on an entity the SQL reads, constructs that read a whole row without
83
+ * naming its columns are refused: `SELECT *` and `alias.*` (except directly inside `EXISTS (…)`
84
+ * whose body has no set operation or row-picking ORDER BY), `FOR JSON`, `FOR XML`, any function of
85
+ * `*` other than `COUNT(*)`/`COUNT_BIG(*)` (for example `CHECKSUM(*)`), `NATURAL JOIN`, a column
86
+ * alias list on such a relation, and a relation or its alias used as a value (PostgreSQL's
87
+ * whole-row reference, as in `row_to_json(e)` or `TABLE vw`). A user with no denials on the
88
+ * entities read is not affected; ordinary subqueries keep working.
89
+ *
90
+ * ## Failing closed
91
+ *
92
+ * Text the scanner cannot read the way the database does is refused for any user who carries a
93
+ * denial on an entity the SQL could read. So is a name holding a control, format or
94
+ * default-ignorable character (a zero-width joiner, a direction mark), which a collation may give
95
+ * no weight to.
96
+ *
97
+ * ## Unknown columns
98
+ *
99
+ * A reference to a column that does not exist reaches the database, which rejects it. For a user
100
+ * carrying denials, {@link FieldSecuritySQLGate.ErrorForInvalidColumn} turns that rejection into the
101
+ * same {@link FieldSecurityError} a denied column gets, so the two cannot be told apart.
102
+ */
103
+ export declare class FieldSecuritySQLGate {
104
+ /**
105
+ * The first reason `sql` must be refused for `context.User`, or null when it may run.
106
+ *
107
+ * @param sql A filter, sort or aggregate fragment, or a whole statement
108
+ * @param context The user, dialect, catalog and the entities the SQL is known to read
109
+ */
110
+ static FindViolation(sql: string | null | undefined, context: FieldSecuritySQLContext): FieldSecurityViolation | null;
111
+ /**
112
+ * The first reason the sort fragment `orderBy` must be refused for `context.User`, or null.
113
+ * Everything {@link FindViolation} refuses, and, for a user denied a field on
114
+ * `context.TargetEntity`, a sort item that is a column position (`3 DESC`). A position names a
115
+ * column of the select list without spelling it, and an entity-object read selects every
116
+ * column, so `ORDER BY 3` can sort by a denied field. It is refused as a whole-row construct.
117
+ */
118
+ static FindSortViolation(orderBy: string | null | undefined, context: FieldSecuritySQLContext): FieldSecurityViolation | null;
119
+ /**
120
+ * Throws a {@link FieldSecurityError} when {@link FindViolation} refuses `sql`. The error names
121
+ * `entityName`, the entity the caller is reading, never the entity a subquery reaches, so a
122
+ * refusal says nothing a "no such column" error would not.
123
+ */
124
+ static AssertAllowed(sql: string | null | undefined, context: FieldSecuritySQLContext, entityName: string): void;
125
+ /**
126
+ * Checks a whole statement, such as a saved query's rendered SQL, against the denied fields of
127
+ * every entity it reads. The entities come from the base views and tables the text names, plus
128
+ * `readEntities`. References are checked wherever they appear: the select list, WHERE, JOIN,
129
+ * GROUP BY, ORDER BY and HAVING. For a user carrying any field denial, a relation the catalog
130
+ * does not know is refused too ({@link FieldSecuritySQLContext.RefuseUnknownRelations}).
131
+ * Throws a {@link FieldSecurityError} on the first violation, naming the entity whose denial
132
+ * it reached (or `fallbackEntityName` when none).
133
+ */
134
+ static AssertStatementAllowed(sql: string, user: UserInfo, catalog: readonly EntityInfo[], dialect: SQLScreeningDialect, readEntities?: readonly EntityInfo[], fallbackEntityName?: string): void;
135
+ /** The error a violation raises, naming `entityName`. */
136
+ static ErrorForViolation(violation: FieldSecurityViolation, entityName: string): FieldSecurityError;
137
+ /**
138
+ * For a user carrying field denials on `entity`, the {@link FieldSecurityError} a database's
139
+ * "no such column" rejection becomes, so a column that does not exist and a column that is
140
+ * denied produce the same error. Null when the user carries no denials there, or the error is
141
+ * not a "no such column" rejection.
142
+ *
143
+ * Reads SQL Server's `Invalid column name 'x'` and `The multi-part identifier "a.x" could not be
144
+ * bound`, and PostgreSQL's `column "x" does not exist` and `column a.x does not exist`.
145
+ */
146
+ static ErrorForInvalidColumn(error: unknown, entity: EntityInfo | null | undefined, user: UserInfo | null | undefined): FieldSecurityError | null;
147
+ /**
148
+ * The entities whose base view or base table `sql` reads as a relation: a name after FROM, JOIN
149
+ * or APPLY, or in a FROM list, wherever it appears (subqueries and CTE bodies included), with
150
+ * schema qualifiers skipped. A name in a literal or a comment is not a relation. A bare name
151
+ * shared by entities in several schemas yields each of them, so the set never misses a read.
152
+ * A relation inside a parenthesized join and PostgreSQL's `FROM ONLY x` count too. Null when
153
+ * the text cannot be read the way the database reads it.
154
+ */
155
+ static RelationEntities(sql: string | null | undefined, catalog: readonly EntityInfo[], dialect: SQLScreeningDialect): EntityInfo[] | null;
156
+ /** True when `user` is denied at least one field on at least one of `entities`. */
157
+ static UserCarriesDenials(entities: Iterable<EntityInfo | null | undefined>, user: UserInfo): boolean;
158
+ /**
159
+ * True when `user` is denied at least one field on any entity of `catalog`.
160
+ *
161
+ * Memoized per (catalog, user): after the first call it costs a few comparisons. The memo is
162
+ * discarded when the catalog array changes length, when the field-security generation moves
163
+ * (an entity rebuilt, a flag assigned, a cache invalidated; see
164
+ * `CurrentFieldSecurityGeneration`) or when the user's roles change, which are everything the
165
+ * answer depends on. A catalog swapped for a new array starts a new memo.
166
+ */
167
+ static CatalogHasDenialsForUser(catalog: readonly EntityInfo[] | null | undefined, user: UserInfo): boolean;
168
+ /**
169
+ * Every field `user` may not read across `catalog`: one `entityID:field,field` entry per
170
+ * entity on which the user is denied something, sorted. '' for a user denied nothing.
171
+ * Memoized exactly as {@link CatalogHasDenialsForUser}.
172
+ */
173
+ static CatalogDenialProfileKey(catalog: readonly EntityInfo[] | null | undefined, user: UserInfo): string;
174
+ /** The current summary for (`catalog`, `user`), rebuilt when any part of its key moved. */
175
+ private static catalogDenialSummary;
176
+ /** The uncached walk behind {@link CatalogDenialProfileKey}. */
177
+ private static buildDenialProfileKey;
178
+ /**
179
+ * The column a database "no such column" message names, or null. A qualified name gives its
180
+ * last part, which is what the gate reports for the same reference.
181
+ */
182
+ private static invalidColumnName;
183
+ /** Longest prefix of a database error message scanned for a column name. */
184
+ private static readonly maxErrorMessageScanLength;
185
+ /** The last dot-separated part of an identifier path, unquoted and unescaped. */
186
+ private static lastIdentifierPart;
187
+ /**
188
+ * The identifier path in a PostgreSQL `column <path> does not exist` message (for example
189
+ * `e.salry` or `"E"."Salry"`), or null. Scanned by hand rather than with a regular expression:
190
+ * the path's parts may themselves contain dots, and a pattern that allows that backtracks
191
+ * exponentially on crafted input.
192
+ */
193
+ private static postgresColumnPath;
194
+ /**
195
+ * Index just past an identifier path starting at `start`: a run of non-space characters in
196
+ * which double-quoted segments (with `""` escapes) may contain spaces. Returns `start` when no
197
+ * path starts there, and -1 for an unterminated quote.
198
+ */
199
+ private static identifierPathEnd;
200
+ /**
201
+ * The first call of a function the dialect forbids in caller SQL (one that runs SQL given as a
202
+ * string, reads files or other databases), or null. What such a call reads cannot be checked.
203
+ */
204
+ private static findDynamicSQLCall;
205
+ /**
206
+ * True when the user carries a denial on any entity the SQL could read: the target, the
207
+ * declared read entities (checked directly, as they need not be catalog members), or any
208
+ * catalog entity, since the text can name any of them. The catalog answer is memoized
209
+ * ({@link CatalogHasDenialsForUser}).
210
+ *
211
+ * Deliberately catalog-wide rather than "the target and read entities only". Which other
212
+ * entities a fragment reads is only known once its text has been read the way the database
213
+ * reads it: a subquery, a parenthesized join, a schema-qualified or bracketed name, or a name
214
+ * spelled with look-alike characters all reach another entity's view. And text that cannot be
215
+ * read at all, a dynamic-SQL call or an invisible character must be refused for such a user
216
+ * whatever it appears to name. Every one of those checks needs the tokens, so a user with a
217
+ * denial anywhere has every fragment tokenized; {@link analyze} then derives the read set, and
218
+ * a fragment whose read set carries none of the user's denials passes without the
219
+ * denied-name and whole-row checks.
220
+ */
221
+ private static mayReadRestrictedEntity;
222
+ /** Builds the relation bindings, the restricted set and its denied names. */
223
+ private static analyze;
224
+ /** Adds `entity` to the restricted set when the user is denied a field on it. */
225
+ private static addIfRestricted;
226
+ /** Records each relation the text names, its alias, and which of them are restricted. */
227
+ private static bindRelations;
228
+ /** Binds a qualifier to entities. */
229
+ private static bind;
230
+ /**
231
+ * Whether the relation name at `i` declares a relation: it follows FROM, JOIN or APPLY, or a
232
+ * comma in a FROM list, with any `schema .` / `database . schema .` qualifiers, a PostgreSQL
233
+ * `ONLY`, and the parentheses of a parenthesized join skipped.
234
+ */
235
+ private static isRelationDeclaration;
236
+ /** Whether the token at `j` is a FROM, JOIN or APPLY keyword, or a comma in a FROM list. */
237
+ private static introducesRelation;
238
+ /** The index of the first part of the dotted name that ends at `i` (`db . schema . name`). */
239
+ private static qualifierStart;
240
+ /**
241
+ * The clause keyword that governs the token at `i` at its own parenthesis depth: the nearest
242
+ * preceding SELECT, FROM, JOIN, WHERE, ON, GROUP, ORDER or HAVING at that depth. Inside the
243
+ * parentheses of a parenthesized join (`FROM (a x, b y)`) with no such keyword, `from`.
244
+ */
245
+ private static clauseAt;
246
+ /** Whether the `(` at `j` opens a parenthesized join: it stands where a relation is declared. */
247
+ private static opensJoinGroup;
248
+ /**
249
+ * The first relation the statement reads that is not a CTE and not the base view or base table
250
+ * of a catalog entity, or a stored-procedure call; null when there is none. A name qualified by
251
+ * a schema no entity of that name lives in, or by a database, is unknown; so is a function in
252
+ * a relation position (`FROM f(…)`).
253
+ */
254
+ private static findUnknownRelation;
255
+ /**
256
+ * Whether the name at `i` is the last part of a relation the statement reads: after FROM (of a
257
+ * SELECT, not `EXTRACT(… FROM x)` or `IS DISTINCT FROM x`), JOIN, APPLY, a FROM-list comma or
258
+ * PostgreSQL's `TABLE`, past qualifiers, `ONLY`, `LATERAL` and join-group parentheses.
259
+ */
260
+ private static isRelationTarget;
261
+ /** Whether a token is `ONLY` or `LATERAL`. */
262
+ private static isRelationModifier;
263
+ /** Whether the FROM at `j` is a SELECT's FROM clause. */
264
+ private static isSelectFrom;
265
+ /**
266
+ * Whether the relation whose last name part is at `i` is a CTE or a catalog entity's base view
267
+ * or base table, in that entity's schema when qualified.
268
+ */
269
+ private static isKnownRelation;
270
+ /**
271
+ * The folded names of the CTEs a statement defines: a name after WITH, RECURSIVE or a comma
272
+ * that is followed by an optional column list, AS, an optional `[NOT] MATERIALIZED`, and `(`.
273
+ */
274
+ private static cteNames;
275
+ /** Whether the tokens from `j` are `[(columns)] AS [NOT] [MATERIALIZED] (`. */
276
+ private static opensCTEBody;
277
+ /** The index of the `)` that closes the `(` at `open`, or -1. */
278
+ private static closingParen;
279
+ /**
280
+ * Whether the body of the `EXISTS (` whose parenthesis is at `open` has, at its own depth, a
281
+ * word that makes a `SELECT *` there read column values ({@link EXISTS_ROW_READING_WORDS}).
282
+ * An unclosed body counts as one that does.
283
+ */
284
+ private static existsBodyReadsRows;
285
+ /** The index of the alias after the relation at `i` (`x a`, `x AS a`), or null. */
286
+ private static aliasIndexAfter;
287
+ /** The first reference to a denied field, honoring qualifiers that bind to known entities. */
288
+ private static findDeniedReference;
289
+ /**
290
+ * The denied names a reference at `i` could reach: those of the entities its qualifier binds to,
291
+ * or every restricted entity's when it is unqualified or its qualifier is unknown.
292
+ */
293
+ private static candidatesFor;
294
+ /**
295
+ * A sort item of `orderBy` that is a column position, as a whole-row violation, or null. Only
296
+ * for a user denied a field on the target entity. An item counts when its first token, inside
297
+ * any opening parentheses, is a number.
298
+ */
299
+ private static findSortByPosition;
300
+ /** The first whole-row construct, or null. */
301
+ private static findWholeRowConstruct;
302
+ /** The whole-row construct that starts at token `i`, or null. */
303
+ private static wholeRowConstructAt;
304
+ /**
305
+ * What a `*` at `i` reads: null for a multiplication, `COUNT(*)`, `EXISTS (SELECT *` whose body
306
+ * has no set operation or row-picking ORDER BY at its own depth, `alias.*` whose alias binds
307
+ * only to entities the user is denied nothing on, or a projection star
308
+ * ({@link FieldSecuritySQLContext.ProjectionStarOffsets}).
309
+ */
310
+ private static starConstruct;
311
+ /**
312
+ * A restricted relation name or alias used other than as a declaration or a qualifier (`x.`):
313
+ * a whole-row value on PostgreSQL, or a column alias list after the declaration.
314
+ */
315
+ private static relationValueConstruct;
316
+ /** Whether a token can end the left operand of a multiplication. */
317
+ private static endsOperand;
318
+ /** Whether a token can start the right operand of a multiplication. */
319
+ private static startsOperand;
320
+ /**
321
+ * The name a "no such column" error would give for `name` as `sql` writes it, so a denied
322
+ * column is reported exactly as an unknown one. On PostgreSQL, MJ quotes a capitalized or
323
+ * dot-qualified word before the database sees it (`AutoQuoteLeavesWordBare`), so the error
324
+ * names such a word as written; a word left bare is folded to lower case. A quoted name, and
325
+ * every name on SQL Server, is reported as written. The first token spelled `name` decides.
326
+ *
327
+ * @param sql The caller's SQL
328
+ * @param name The reference as the database reads it
329
+ * @param dialect The dialect the SQL runs under
330
+ */
331
+ static ReportedColumnName(sql: string, name: string, dialect: SQLScreeningDialect): string;
332
+ /** A reference's name as {@link ReportedColumnName} gives it. */
333
+ private static reportedName;
334
+ private static isName;
335
+ private static isWord;
336
+ private static isSymbol;
337
+ /** Folded base view and base table names of every entity in the catalog. */
338
+ private static relationIndex;
339
+ }
340
+ /**
341
+ * An identifier reduced to the form a database collation may compare it in: Unicode compatibility
342
+ * decomposition (a KELVIN SIGN reads as `K`, a full-width letter as its ASCII form), accents and
343
+ * other combining marks removed, control, format and default-ignorable characters (zero-width
344
+ * joiners, direction marks, a soft hyphen) removed, case folded through upper case (`ß` and `ẞ` both read `ss`, a
345
+ * final `ς` reads `σ`), and surrounding spaces trimmed.
346
+ */
347
+ export declare function FoldIdentifier(name: string): string;
348
+ /**
349
+ * Whether a reference as written may name `fieldName` on some database: by the rule
350
+ * `IdentifierMatches` states, or when both fold to the same form ({@link FoldIdentifier}). Looser
351
+ * than any collation, so a security check that refuses on it never lets through a reference the
352
+ * database would resolve to the field.
353
+ */
354
+ export declare function ReferenceMayNameField(reference: string, fieldName: string): boolean;
355
+ /** The message for a whole-row construct refused for a user carrying field denials. */
356
+ export declare function FieldSecurityWholeRowMessage(construct: string, entityName: string): string;
357
+ /** The message for SQL that could not be read well enough to check against field permissions. */
358
+ export declare function FieldSecurityUnresolvableSQLMessage(entityName: string): string;
359
+ //# sourceMappingURL=fieldSecuritySQLGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldSecuritySQLGate.d.ts","sourceRoot":"","sources":["../../src/generic/fieldSecuritySQLGate.ts"],"names":[],"mappings":"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"}