prostgles-server 4.2.624 → 4.2.625
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/Audit/AuditTable.d.ts +2 -1
- package/dist/Audit/AuditTable.d.ts.map +1 -1
- package/dist/Audit/AuditTable.js +3 -2
- package/dist/Audit/AuditTable.js.map +1 -1
- package/dist/Audit/getAuditTableRules.d.ts +7 -0
- package/dist/Audit/getAuditTableRules.d.ts.map +1 -0
- package/dist/Audit/getAuditTableRules.js +191 -0
- package/dist/Audit/getAuditTableRules.js.map +1 -0
- package/dist/Audit/getAuditTriggerConfig.d.ts.map +1 -1
- package/dist/Audit/getAuditTriggerConfig.js +14 -1
- package/dist/Audit/getAuditTriggerConfig.js.map +1 -1
- package/dist/DBSchemaBuilder/getDBGeneratedSchema.d.ts.map +1 -1
- package/dist/DBSchemaBuilder/getDBGeneratedSchema.js +1 -2
- package/dist/DBSchemaBuilder/getDBGeneratedSchema.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts +10 -5
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js +90 -71
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getJoinQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getJoinQuery.js +3 -2
- package/dist/DboBuilder/QueryBuilder/getJoinQuery.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts +2 -2
- package/dist/DboBuilder/QueryBuilder/getNewQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getNewQuery.js +53 -116
- package/dist/DboBuilder/QueryBuilder/getNewQuery.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getQuerySource.d.ts +18 -0
- package/dist/DboBuilder/QueryBuilder/getQuerySource.d.ts.map +1 -0
- package/dist/DboBuilder/QueryBuilder/getQuerySource.js +29 -0
- package/dist/DboBuilder/QueryBuilder/getQuerySource.js.map +1 -0
- package/dist/DboBuilder/QueryBuilder/getSelectQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/getSelectQuery.js +6 -2
- package/dist/DboBuilder/QueryBuilder/getSelectQuery.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.d.ts +13 -0
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.d.ts.map +1 -0
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.js +57 -0
- package/dist/DboBuilder/QueryBuilder/parseJoinSelect.js.map +1 -0
- package/dist/DboBuilder/TableHandler/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/TableHandler.js +2 -1
- package/dist/DboBuilder/TableHandler/TableHandler.js.map +1 -1
- package/dist/DboBuilder/TableHandler/delete.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/delete.js +2 -1
- package/dist/DboBuilder/TableHandler/delete.js.map +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js +2 -1
- package/dist/DboBuilder/TableHandler/runInsertUpdateQuery.js.map +1 -1
- package/dist/DboBuilder/TableHandler/update.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/update.js +2 -1
- package/dist/DboBuilder/TableHandler/update.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts +6 -16
- package/dist/DboBuilder/ViewHandler/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/ViewHandler.js +2 -7
- package/dist/DboBuilder/ViewHandler/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/find.js +1 -1
- package/dist/DboBuilder/ViewHandler/find.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getExistsCondition.d.ts +1 -1
- package/dist/DboBuilder/ViewHandler/getExistsCondition.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/getExistsCondition.js +24 -13
- package/dist/DboBuilder/ViewHandler/getExistsCondition.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.d.ts +4 -1
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.js +20 -14
- package/dist/DboBuilder/ViewHandler/getTableJoinQuery.js.map +1 -1
- package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts +7 -3
- package/dist/DboBuilder/ViewHandler/prepareWhere.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler/prepareWhere.js +30 -23
- package/dist/DboBuilder/ViewHandler/prepareWhere.js.map +1 -1
- package/dist/DboBuilder/getCondition.d.ts +2 -1
- package/dist/DboBuilder/getCondition.d.ts.map +1 -1
- package/dist/DboBuilder/getCondition.js +9 -8
- package/dist/DboBuilder/getCondition.js.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.d.ts.map +1 -1
- package/dist/DboBuilder/getSubscribeRelatedTables.js +3 -2
- package/dist/DboBuilder/getSubscribeRelatedTables.js.map +1 -1
- package/dist/DboBuilder/parseUpdateRules.d.ts.map +1 -1
- package/dist/DboBuilder/parseUpdateRules.js +3 -2
- package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
- package/dist/DboBuilder/schema/getTablesForSchemaPostgresSQL.d.ts +2 -2
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +2 -0
- package/dist/Prostgles.js.map +1 -1
- package/dist/ProstglesContext.spec.js +25 -0
- package/dist/ProstglesContext.spec.js.map +1 -1
- package/dist/PubSubManager/PubSubManager.d.ts +1 -1
- package/dist/PublishParser/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser/PublishParser.js +15 -4
- package/dist/PublishParser/PublishParser.js.map +1 -1
- package/dist/PublishParser/applyScopeToTableRules.d.ts +0 -1
- package/dist/PublishParser/applyScopeToTableRules.d.ts.map +1 -1
- package/dist/PublishParser/applyScopeToTableRules.js +3 -7
- package/dist/PublishParser/applyScopeToTableRules.js.map +1 -1
- package/dist/PublishParser/getPublishedTableNames.d.ts.map +1 -1
- package/dist/PublishParser/getPublishedTableNames.js +16 -0
- package/dist/PublishParser/getPublishedTableNames.js.map +1 -1
- package/dist/PublishParser/publishTypesAndUtils.d.ts +0 -4
- package/dist/PublishParser/publishTypesAndUtils.d.ts.map +1 -1
- package/dist/PublishParser/publishTypesAndUtils.js.map +1 -1
- package/dist/TableConfig/getColumnSQLDefinitionQuery.d.ts.map +1 -1
- package/dist/TableConfig/getColumnSQLDefinitionQuery.js +1 -2
- package/dist/TableConfig/getColumnSQLDefinitionQuery.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/lib/Audit/AuditTable.ts +4 -3
- package/lib/Audit/getAuditTableRules.ts +288 -0
- package/lib/Audit/getAuditTriggerConfig.ts +14 -1
- package/lib/DBSchemaBuilder/getDBGeneratedSchema.ts +1 -2
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +118 -90
- package/lib/DboBuilder/QueryBuilder/getJoinQuery.ts +3 -2
- package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +111 -194
- package/lib/DboBuilder/QueryBuilder/getQuerySource.ts +55 -0
- package/lib/DboBuilder/QueryBuilder/getSelectQuery.ts +8 -2
- package/lib/DboBuilder/QueryBuilder/parseJoinSelect.ts +73 -0
- package/lib/DboBuilder/TableHandler/TableHandler.ts +3 -6
- package/lib/DboBuilder/TableHandler/delete.ts +2 -1
- package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +2 -1
- package/lib/DboBuilder/TableHandler/update.ts +2 -1
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +6 -12
- package/lib/DboBuilder/ViewHandler/find.ts +0 -1
- package/lib/DboBuilder/ViewHandler/getExistsCondition.ts +35 -28
- package/lib/DboBuilder/ViewHandler/getTableJoinQuery.ts +22 -14
- package/lib/DboBuilder/ViewHandler/prepareWhere.ts +48 -27
- package/lib/DboBuilder/getCondition.ts +11 -10
- package/lib/DboBuilder/getSubscribeRelatedTables.ts +3 -2
- package/lib/DboBuilder/parseUpdateRules.ts +3 -2
- package/lib/Prostgles.ts +1 -0
- package/lib/ProstglesContext.spec.ts +30 -0
- package/lib/PublishParser/PublishParser.ts +33 -8
- package/lib/PublishParser/applyScopeToTableRules.ts +1 -7
- package/lib/PublishParser/getPublishedTableNames.ts +22 -0
- package/lib/PublishParser/publishTypesAndUtils.ts +0 -5
- package/lib/TableConfig/getColumnSQLDefinitionQuery.ts +8 -2
- package/lib/index.ts +1 -0
- package/package.json +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { EXISTS_KEYS
|
|
3
|
-
import type { LocalParams, ExistsFilterConfig } from "../DboBuilder";
|
|
4
|
-
import type { ViewHandler } from "./ViewHandler";
|
|
1
|
+
import type { EXISTS_KEY } from "prostgles-types";
|
|
2
|
+
import { EXISTS_KEYS } from "prostgles-types";
|
|
5
3
|
import type { ParsedTableRule } from "../../PublishParser/PublishParser";
|
|
6
|
-
import type {
|
|
7
|
-
import {
|
|
4
|
+
import type { ExistsFilterConfig, LocalParams } from "../DboBuilder";
|
|
5
|
+
import { getQuerySourceSQL } from "../QueryBuilder/getQuerySource";
|
|
6
|
+
import { getTableJoinAlias, getTableJoinQuery } from "./getTableJoinQuery";
|
|
7
|
+
import type { ViewHandler } from "./ViewHandler";
|
|
8
|
+
import { prepareWhere } from "./prepareWhere";
|
|
8
9
|
|
|
9
10
|
export async function getExistsCondition(
|
|
10
11
|
this: ViewHandler,
|
|
@@ -25,17 +26,22 @@ export async function getExistsCondition(
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
let t2Rules: ParsedTableRule | undefined = undefined,
|
|
29
|
-
forcedFilter: AnyObject | undefined,
|
|
30
|
-
filterFields: FieldFilter | undefined;
|
|
31
|
-
|
|
32
29
|
/* Check if allowed to view data - forcedFilters will bypass this check through isForcedFilterBypass */
|
|
33
30
|
if (localParams?.isRemoteRequest && !localParams.clientReq) {
|
|
34
31
|
throw "Unexpected: localParams isRemoteRequest and missing clientReq";
|
|
35
32
|
}
|
|
33
|
+
|
|
34
|
+
let targetTableRules: ParsedTableRule | undefined = undefined;
|
|
36
35
|
const targetTable = eConfig.isJoined ? eConfig.parsedPath.at(-1)!.table : eConfig.targetTable;
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const tableHandler = this.dboBuilder.dboMap.get(targetTable);
|
|
37
|
+
if (!tableHandler) {
|
|
38
|
+
throw `Table handler for ${targetTable} not found`;
|
|
39
|
+
}
|
|
40
|
+
if (localParams?.clientReq) {
|
|
41
|
+
if (!this.dboBuilder.publishParser) {
|
|
42
|
+
throw "Unexpected: missing publishParser";
|
|
43
|
+
}
|
|
44
|
+
targetTableRules = await this.dboBuilder.publishParser.getValidatedRequestRuleWusr(
|
|
39
45
|
{
|
|
40
46
|
tableName: targetTable,
|
|
41
47
|
command: "find",
|
|
@@ -44,27 +50,27 @@ export async function getExistsCondition(
|
|
|
44
50
|
localParams.scope,
|
|
45
51
|
);
|
|
46
52
|
|
|
47
|
-
if (!
|
|
48
|
-
({ forcedFilter, filterFields } = t2Rules.select);
|
|
53
|
+
if (!targetTableRules.select) throw "Disallowed";
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
56
|
+
const targetAlias =
|
|
57
|
+
eConfig.isJoined ? getTableJoinAlias(targetTable, eConfig.parsedPath.length - 1) : undefined;
|
|
58
|
+
const whereOpts = await prepareWhere(tableHandler, {
|
|
59
|
+
select: undefined,
|
|
60
|
+
selectParams: {},
|
|
61
|
+
filter: targetTableFilter,
|
|
62
|
+
forcedFilter: targetTableRules?.select?.forcedFilter,
|
|
63
|
+
filterFields: targetTableRules?.select?.filterFields,
|
|
64
|
+
tableRule: targetTableRules,
|
|
65
|
+
addWhere: false,
|
|
66
|
+
tableAlias: targetAlias,
|
|
67
|
+
localParams,
|
|
68
|
+
});
|
|
69
|
+
const { source: targetSource, where: finalWhere } = whereOpts;
|
|
64
70
|
|
|
65
71
|
let innerQuery = [
|
|
66
72
|
`SELECT 1`,
|
|
67
|
-
`FROM ${
|
|
73
|
+
`FROM ${getQuerySourceSQL(targetSource)}`,
|
|
68
74
|
`${finalWhere ? `WHERE ${finalWhere}` : ""}`,
|
|
69
75
|
].join("\n");
|
|
70
76
|
|
|
@@ -74,6 +80,7 @@ export async function getExistsCondition(
|
|
|
74
80
|
rootTableAlias: rootTableAlias ?? rootTable,
|
|
75
81
|
type: "EXISTS",
|
|
76
82
|
finalWhere,
|
|
83
|
+
finalTableExpression: targetSource.expression,
|
|
77
84
|
});
|
|
78
85
|
innerQuery = query;
|
|
79
86
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { asName } from "prostgles-types";
|
|
2
|
+
import type { PGIdentifier } from "../DboBuilder";
|
|
2
3
|
import type { ParsedJoinPath } from "./parseJoinPath";
|
|
3
4
|
|
|
4
5
|
type getTableJoinsArgs = {
|
|
5
6
|
rootTableAlias: string;
|
|
6
7
|
type: "INNER" | "LEFT" | "EXISTS";
|
|
7
8
|
finalWhere?: string;
|
|
9
|
+
finalTableExpression?: string;
|
|
8
10
|
path: ParsedJoinPath[];
|
|
9
11
|
};
|
|
10
12
|
export const getTableJoinQuery = ({
|
|
@@ -12,14 +14,14 @@ export const getTableJoinQuery = ({
|
|
|
12
14
|
type,
|
|
13
15
|
rootTableAlias,
|
|
14
16
|
finalWhere,
|
|
17
|
+
finalTableExpression,
|
|
15
18
|
}: getTableJoinsArgs): { targetAlias: string; query: string } => {
|
|
16
19
|
const [firstPath] = path;
|
|
17
20
|
if (!firstPath) {
|
|
18
21
|
throw `Cannot create join query for empty path`;
|
|
19
22
|
}
|
|
20
|
-
const aliasSufix = "jd";
|
|
21
23
|
const getTableAlias = (table: string, pathIndex: number) =>
|
|
22
|
-
|
|
24
|
+
getTableJoinAlias(table, pathIndex).escaped;
|
|
23
25
|
|
|
24
26
|
const query = path
|
|
25
27
|
.map(({ table, on }, i) => {
|
|
@@ -45,19 +47,19 @@ export const getTableJoinQuery = ({
|
|
|
45
47
|
*/
|
|
46
48
|
const whereJoinCondition =
|
|
47
49
|
isLast && isExists ?
|
|
48
|
-
`WHERE (${
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
`WHERE (${[
|
|
51
|
+
getJoinOnCondition({
|
|
52
|
+
on: firstPath.on,
|
|
53
|
+
leftAlias: rootTableAlias,
|
|
54
|
+
rightAlias: getTableAlias(firstPath.table, 0),
|
|
55
|
+
}),
|
|
56
|
+
finalWhere,
|
|
57
|
+
]
|
|
58
|
+
.filter(Boolean)
|
|
59
|
+
.join(") AND (")})`
|
|
53
60
|
: "";
|
|
54
61
|
|
|
55
|
-
const tableSelect =
|
|
56
|
-
isExists && isLast ?
|
|
57
|
-
[`(`, ` SELECT *`, ` FROM ${tableName}`, finalWhere ? ` WHERE ${finalWhere}` : "", `)`]
|
|
58
|
-
.filter((v) => v)
|
|
59
|
-
.join("\n")
|
|
60
|
-
: tableName;
|
|
62
|
+
const tableSelect = isLast ? (finalTableExpression ?? tableName) : tableName;
|
|
61
63
|
if (isExists && isFirst) {
|
|
62
64
|
return [`SELECT 1`, `FROM ${tableSelect} ${tableAlias}`, whereJoinCondition]
|
|
63
65
|
.filter((v) => v)
|
|
@@ -76,6 +78,12 @@ export const getTableJoinQuery = ({
|
|
|
76
78
|
};
|
|
77
79
|
};
|
|
78
80
|
|
|
81
|
+
export const getTableJoinAlias = (table: string, pathIndex: number): PGIdentifier => {
|
|
82
|
+
const prefix = "jd";
|
|
83
|
+
const raw = `${prefix}_${pathIndex}_${table}`;
|
|
84
|
+
return { raw, escaped: asName(raw) };
|
|
85
|
+
};
|
|
86
|
+
|
|
79
87
|
type GetJoinOnConditionArgs = {
|
|
80
88
|
on: Record<string, string>[];
|
|
81
89
|
leftAlias: string;
|
|
@@ -95,7 +103,7 @@ export const getJoinOnConditions = ({
|
|
|
95
103
|
.map(([leftCol, rightCol]) => {
|
|
96
104
|
return `${leftAlias}.${getLeftColName(leftCol)} = ${rightAlias}.${getRightColName(rightCol)}`;
|
|
97
105
|
})
|
|
98
|
-
.join(" AND ")
|
|
106
|
+
.join(" AND "),
|
|
99
107
|
);
|
|
100
108
|
};
|
|
101
109
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { AnyObject, FieldFilter } from "prostgles-types/dist";
|
|
1
|
+
import type { AnyObject, FieldFilter, SelectParams } from "prostgles-types/dist";
|
|
2
2
|
import { getKeys, isDefined, isObject } from "prostgles-types/dist";
|
|
3
3
|
import type { ParsedTableRule } from "../../PublishParser/PublishParser";
|
|
4
4
|
import type { ExistsFilterConfig, Filter, LocalParams, PGIdentifier } from "../DboBuilder";
|
|
5
5
|
import { getCondition } from "../getCondition";
|
|
6
6
|
import { type SelectItemValidated } from "../QueryBuilder/QueryBuilder";
|
|
7
|
+
import { getQuerySource, type QuerySource } from "../QueryBuilder/getQuerySource";
|
|
7
8
|
import type { ViewHandler } from "./ViewHandler";
|
|
8
9
|
|
|
9
10
|
export type PrepareWhereParams = {
|
|
@@ -16,46 +17,61 @@ export type PrepareWhereParams = {
|
|
|
16
17
|
localParams: LocalParams | undefined;
|
|
17
18
|
tableRule: ParsedTableRule | undefined;
|
|
18
19
|
isHaving?: boolean;
|
|
20
|
+
selectParams?: SelectParams;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
|
-
export
|
|
22
|
-
this: ViewHandler,
|
|
23
|
-
params: PrepareWhereParams,
|
|
24
|
-
): Promise<{
|
|
23
|
+
export type WhereOptions = {
|
|
25
24
|
columnsUsed: string[];
|
|
26
25
|
condition: string;
|
|
27
26
|
where: string;
|
|
28
27
|
filter: AnyObject;
|
|
29
28
|
exists: ExistsFilterConfig[];
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
source: QuerySource;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const prepareWhere = async (
|
|
33
|
+
viewHandler: ViewHandler,
|
|
34
|
+
{
|
|
32
35
|
filter,
|
|
33
36
|
select,
|
|
34
37
|
forcedFilter,
|
|
35
|
-
filterFields: ff,
|
|
36
38
|
addWhere: addKeywords = true,
|
|
37
39
|
tableAlias,
|
|
38
40
|
localParams,
|
|
39
41
|
tableRule,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
/* Local update allow all. TODO: tidy all calls */
|
|
43
|
+
filterFields = !tableRule ? "*" : undefined,
|
|
44
|
+
isHaving,
|
|
45
|
+
selectParams,
|
|
46
|
+
}: PrepareWhereParams,
|
|
47
|
+
): Promise<WhereOptions> => {
|
|
48
|
+
const { $and: $and_key, $or: $or_key } = viewHandler.dboBuilder.prostgles.keywords;
|
|
49
|
+
|
|
50
|
+
if (localParams?.isRemoteRequest && !tableRule) {
|
|
51
|
+
throw "Unexpected: localParams isRemoteRequest and missing tableRule";
|
|
52
|
+
}
|
|
42
53
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
const source = await getQuerySource(
|
|
55
|
+
viewHandler,
|
|
56
|
+
selectParams ? tableRule : undefined,
|
|
57
|
+
filter ?? {},
|
|
58
|
+
selectParams ?? {},
|
|
59
|
+
tableAlias,
|
|
60
|
+
);
|
|
46
61
|
|
|
47
62
|
const exists: ExistsFilterConfig[] = [];
|
|
48
63
|
|
|
49
64
|
type FilterItemResult = { condition: string; columnsUsed: string[] };
|
|
50
65
|
const parseFullFilter = async (
|
|
51
|
-
|
|
66
|
+
fullFilter: any,
|
|
52
67
|
parentFilter: AnyObject | null = null,
|
|
53
68
|
isForcedFilterBypass: boolean,
|
|
54
69
|
): Promise<FilterItemResult | undefined> => {
|
|
55
|
-
if (!
|
|
56
|
-
if (!isObject(
|
|
70
|
+
if (!fullFilter) throw "Invalid/missing group filter provided";
|
|
71
|
+
if (!isObject(fullFilter))
|
|
72
|
+
throw "\nInvalid filter\nExpecting an object but got -> " + JSON.stringify(fullFilter);
|
|
57
73
|
|
|
58
|
-
const keys = getKeys(
|
|
74
|
+
const keys = getKeys(fullFilter);
|
|
59
75
|
if (!keys.length) {
|
|
60
76
|
return;
|
|
61
77
|
}
|
|
@@ -66,8 +82,8 @@ export async function prepareWhere(
|
|
|
66
82
|
throw "group filter ($and/$or) can only be placed at the root or within another group filter";
|
|
67
83
|
}
|
|
68
84
|
|
|
69
|
-
const { [$and_key]: $and, [$or_key]: $or } =
|
|
70
|
-
|
|
85
|
+
const { [$and_key]: $and, [$or_key]: $or } = fullFilter;
|
|
86
|
+
const group = ($and || $or) as AnyObject[] | undefined;
|
|
71
87
|
|
|
72
88
|
if (group && group.length) {
|
|
73
89
|
const operand = $and ? " AND " : " OR ";
|
|
@@ -82,20 +98,24 @@ export async function prepareWhere(
|
|
|
82
98
|
if (conditionItems.length) {
|
|
83
99
|
const conditions = conditionItems.map((c) => c.condition);
|
|
84
100
|
const columnsUsed = conditionItems.map((c) => c.columnsUsed).flat();
|
|
85
|
-
if (conditions.length === 1)
|
|
86
|
-
|
|
101
|
+
if (conditions.length === 1) {
|
|
102
|
+
return { columnsUsed, condition: conditions.join(operand) };
|
|
103
|
+
}
|
|
104
|
+
return { columnsUsed, condition: ` ( ${conditions.sort().join(operand)} ) ` };
|
|
87
105
|
}
|
|
88
106
|
} else if (!group) {
|
|
89
107
|
/** forcedFilters do not get checked against publish and are treated as server-side requests */
|
|
90
|
-
const itemInfo = await getCondition.bind(
|
|
91
|
-
filter: { ...
|
|
108
|
+
const itemInfo = await getCondition.bind(viewHandler)({
|
|
109
|
+
filter: { ...fullFilter },
|
|
92
110
|
select,
|
|
93
111
|
allowed_colnames:
|
|
94
|
-
isForcedFilterBypass ?
|
|
95
|
-
|
|
112
|
+
isForcedFilterBypass ?
|
|
113
|
+
viewHandler.column_names.slice(0)
|
|
114
|
+
: viewHandler.parseFieldFilter(filterFields),
|
|
115
|
+
tableAlias: source.alias,
|
|
96
116
|
localParams: isForcedFilterBypass ? undefined : localParams,
|
|
97
117
|
tableRules: isForcedFilterBypass ? undefined : tableRule,
|
|
98
|
-
isHaving
|
|
118
|
+
isHaving,
|
|
99
119
|
});
|
|
100
120
|
exists.push(...itemInfo.exists);
|
|
101
121
|
return {
|
|
@@ -135,5 +155,6 @@ export async function prepareWhere(
|
|
|
135
155
|
where: combinedConditions || "",
|
|
136
156
|
filter: finalFilter,
|
|
137
157
|
exists,
|
|
158
|
+
source,
|
|
138
159
|
};
|
|
139
|
-
}
|
|
160
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { pickKeys } from "prostgles-types";
|
|
1
|
+
import { pickKeys, type AnyObject } from "prostgles-types";
|
|
2
2
|
import { parseFilterItem } from "../Filtering/Filtering";
|
|
3
3
|
import type { ParsedTableRule } from "../PublishParser/PublishParser";
|
|
4
4
|
import type { ExistsFilterConfig, LocalParams, PGIdentifier } from "./DboBuilder";
|
|
@@ -9,6 +9,7 @@ import type { ViewHandler } from "./ViewHandler/ViewHandler";
|
|
|
9
9
|
import { getExistsCondition } from "./ViewHandler/getExistsCondition";
|
|
10
10
|
import { getExistsFilters } from "./ViewHandler/getExistsFilters";
|
|
11
11
|
import { parseComplexFilter } from "./ViewHandler/parseComplexFilter";
|
|
12
|
+
import { isArray } from "../utils/utils";
|
|
12
13
|
|
|
13
14
|
const FILTER_FUNCS = FUNCTIONS.filter((f) => f.canBeUsedForFilter);
|
|
14
15
|
|
|
@@ -21,7 +22,7 @@ const FILTER_FUNCS = FUNCTIONS.filter((f) => f.canBeUsedForFilter);
|
|
|
21
22
|
export async function getCondition(
|
|
22
23
|
this: ViewHandler,
|
|
23
24
|
params: {
|
|
24
|
-
filter:
|
|
25
|
+
filter: AnyObject;
|
|
25
26
|
select: SelectItemValidated[] | undefined;
|
|
26
27
|
allowed_colnames: string[];
|
|
27
28
|
tableAlias?: PGIdentifier;
|
|
@@ -44,21 +45,21 @@ export async function getCondition(
|
|
|
44
45
|
|
|
45
46
|
const existsConfigs = getExistsFilters(filter, this);
|
|
46
47
|
|
|
47
|
-
const
|
|
48
|
+
const functionConditions: string[] = [];
|
|
48
49
|
const funcFilter = FILTER_FUNCS.filter((f) => f.name in filter);
|
|
49
50
|
|
|
50
51
|
funcFilter.map((f) => {
|
|
51
52
|
const funcArgs = filter[f.name];
|
|
52
|
-
if (!
|
|
53
|
+
if (!isArray(funcArgs)) {
|
|
53
54
|
throw `A function filter must contain an array. E.g: { $funcFilterName: ["col1"] } \n but got: ${JSON.stringify(pickKeys(filter, [f.name]))} `;
|
|
54
55
|
}
|
|
55
56
|
const fields = this.parseFieldFilter(f.getFields(funcArgs), true, allowed_colnames);
|
|
56
57
|
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
throw `Invalid/disallowed columns found in function filter: ${
|
|
58
|
+
const disallowedCols = fields.filter((fname) => !allowed_colnames.includes(fname));
|
|
59
|
+
if (disallowedCols.length) {
|
|
60
|
+
throw `Invalid/disallowed columns found in function filter: ${disallowedCols}`;
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
+
functionConditions.push(
|
|
62
63
|
f.getQuery({
|
|
63
64
|
args: funcArgs,
|
|
64
65
|
allColumns: this.columns,
|
|
@@ -84,7 +85,7 @@ export async function getCondition(
|
|
|
84
85
|
const p = this.getValidatedRules(tableRules, localParams);
|
|
85
86
|
const computedFields = p.allColumns.filter((c) => c.type === "computed");
|
|
86
87
|
const computedColConditions: string[] = [];
|
|
87
|
-
Object.keys(filter
|
|
88
|
+
Object.keys(filter).map((key) => {
|
|
88
89
|
const compCol = computedFields.find((cf) => cf.name === key);
|
|
89
90
|
if (compCol) {
|
|
90
91
|
if (!p.select) throw new Error("Computed column filter requires p.select.fields");
|
|
@@ -231,7 +232,7 @@ export async function getCondition(
|
|
|
231
232
|
let templates: string[] = q?.condition ? [q.condition] : [];
|
|
232
233
|
|
|
233
234
|
if (existsCond) templates.push(existsCond);
|
|
234
|
-
templates = templates.concat(
|
|
235
|
+
templates = templates.concat(functionConditions);
|
|
235
236
|
templates = templates.concat(computedColConditions);
|
|
236
237
|
templates = templates.concat(complexFilters);
|
|
237
238
|
|
|
@@ -8,6 +8,7 @@ import type { TableHandler } from "./TableHandler/TableHandler";
|
|
|
8
8
|
import type { ViewHandler } from "./ViewHandler/ViewHandler";
|
|
9
9
|
import { getViewRelatedTables } from "./ViewRelatedTables/getViewRelatedTables";
|
|
10
10
|
import type { AddTriggerParams } from "../PubSubManager/addTrigger";
|
|
11
|
+
import { prepareWhere } from "./ViewHandler/prepareWhere";
|
|
11
12
|
|
|
12
13
|
type Args = {
|
|
13
14
|
selectParams: Omit<SubscribeParams, "throttle">;
|
|
@@ -66,9 +67,9 @@ export async function getSubscribeRelatedTables(
|
|
|
66
67
|
isEmpty(targetTableFilter) ? reversedJoinFilter : (
|
|
67
68
|
{ $and: [targetTableFilter, reversedJoinFilter] }
|
|
68
69
|
);
|
|
69
|
-
const joinConditionInfo = await
|
|
70
|
-
select: undefined,
|
|
70
|
+
const joinConditionInfo = await prepareWhere(relatedTableOrViewHandler, {
|
|
71
71
|
filter,
|
|
72
|
+
select: undefined,
|
|
72
73
|
addWhere: false,
|
|
73
74
|
localParams: undefined,
|
|
74
75
|
tableRule: undefined,
|
|
@@ -9,6 +9,7 @@ import { type ParsedTableRule } from "../PublishParser/PublishParser";
|
|
|
9
9
|
import type { Filter, LocalParams } from "./DboBuilder";
|
|
10
10
|
import { prepareNewData } from "./TableHandler/DataValidator";
|
|
11
11
|
import type { TableHandler } from "./TableHandler/TableHandler";
|
|
12
|
+
import { prepareWhere } from "./ViewHandler/prepareWhere";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* 1) Check if publish is valid
|
|
@@ -57,7 +58,7 @@ export async function parseUpdateRules(
|
|
|
57
58
|
throw ` Invalid update rule fo r ${this.name}. fields missing `;
|
|
58
59
|
}
|
|
59
60
|
finalUpdateFilter = (
|
|
60
|
-
await
|
|
61
|
+
await prepareWhere(this, {
|
|
61
62
|
select: undefined,
|
|
62
63
|
filter,
|
|
63
64
|
forcedFilter,
|
|
@@ -77,7 +78,7 @@ export async function parseUpdateRules(
|
|
|
77
78
|
/**
|
|
78
79
|
* Validated filter and fields
|
|
79
80
|
*/
|
|
80
|
-
const condition = await
|
|
81
|
+
const condition = await prepareWhere(this, {
|
|
81
82
|
select: undefined,
|
|
82
83
|
filterFields: this.column_names,
|
|
83
84
|
filter: dfRule.filter,
|
package/lib/Prostgles.ts
CHANGED
|
@@ -2,6 +2,7 @@ import assert from "node:assert";
|
|
|
2
2
|
import { describe, test } from "node:test";
|
|
3
3
|
import type { DboBuilder } from "./DboBuilder/DboBuilder";
|
|
4
4
|
import { Prostgles } from "./Prostgles";
|
|
5
|
+
import type { PublishParser } from "./PublishParser/PublishParser";
|
|
5
6
|
|
|
6
7
|
void describe("Prostgles context", async () => {
|
|
7
8
|
await test("recreates context and runs cleanups in reverse order", async () => {
|
|
@@ -47,6 +48,35 @@ void describe("Prostgles context", async () => {
|
|
|
47
48
|
assert.equal(prostgles.context, undefined);
|
|
48
49
|
});
|
|
49
50
|
|
|
51
|
+
await test("recreates the publish parser with the rebuilt DBO", async () => {
|
|
52
|
+
const prostgles = new Prostgles({
|
|
53
|
+
dbConnection: "postgres://unused",
|
|
54
|
+
onReady: () => {},
|
|
55
|
+
});
|
|
56
|
+
prostgles.db = {} as typeof prostgles.db;
|
|
57
|
+
const rebuiltDbo = {};
|
|
58
|
+
const dboBuilder = {
|
|
59
|
+
build: () => {
|
|
60
|
+
dboBuilder.dbo = rebuiltDbo;
|
|
61
|
+
return Promise.resolve();
|
|
62
|
+
},
|
|
63
|
+
dbo: {},
|
|
64
|
+
sql: {},
|
|
65
|
+
tables: [],
|
|
66
|
+
};
|
|
67
|
+
prostgles.dboBuilder = dboBuilder as unknown as DboBuilder;
|
|
68
|
+
|
|
69
|
+
// PublishParser captures the DBO on construction, so it must be recreated after a rebuild.
|
|
70
|
+
const initialPublishParser = {} as PublishParser;
|
|
71
|
+
prostgles.publishParser = initialPublishParser;
|
|
72
|
+
|
|
73
|
+
await prostgles.rebuildDBO();
|
|
74
|
+
|
|
75
|
+
assert.equal(prostgles.dbo, rebuiltDbo);
|
|
76
|
+
assert.notEqual(prostgles.publishParser, initialPublishParser);
|
|
77
|
+
assert.equal(prostgles.publishParser.dbo, prostgles.dbo);
|
|
78
|
+
});
|
|
79
|
+
|
|
50
80
|
await test("cleans partially-created context after an error", async () => {
|
|
51
81
|
const events: string[] = [];
|
|
52
82
|
const prostgles = new Prostgles({
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "prostgles-types";
|
|
7
7
|
import { getClientRequestIPsInfo } from "../Auth/AuthHandler";
|
|
8
8
|
import type { AuthClientRequest, AuthResultWithSID, SessionUser } from "../Auth/AuthTypes";
|
|
9
|
+
import { getAuditTableRules } from "../Audit/getAuditTableRules";
|
|
9
10
|
import type { DBOFullyTyped } from "../DBSchemaBuilder/DBSchemaBuilder";
|
|
10
11
|
import type { DB, DBHandlerServer, Prostgles } from "../Prostgles";
|
|
11
12
|
import { getClientHandlers } from "../WebsocketAPI/getClientHandlers";
|
|
@@ -305,16 +306,40 @@ export class PublishParser {
|
|
|
305
306
|
if (!tableHandler) {
|
|
306
307
|
throw "INTERNAL ERROR: table handler not found for " + tableName;
|
|
307
308
|
}
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
309
|
+
const audit = this.prostgles.resolvedAuditConfig;
|
|
310
|
+
const isAuditTable = audit?.tableName === tableName;
|
|
311
|
+
const resolvedPublishObject =
|
|
312
|
+
overriddenPublish ??
|
|
313
|
+
(isAuditTable && clientReq ?
|
|
314
|
+
await this.getPublishObjectForUser(clientReq, clientInfo)
|
|
315
|
+
: undefined);
|
|
316
|
+
const publishRulesExcludingInferredTables =
|
|
317
|
+
await this.getParsedPublishTable({
|
|
318
|
+
clientReq,
|
|
319
|
+
tableName,
|
|
320
|
+
clientInfo,
|
|
321
|
+
resolvedPublishObject,
|
|
322
|
+
});
|
|
323
|
+
if (audit && isAuditTable) {
|
|
324
|
+
const auditTableRules = await getAuditTableRules.bind(this)(
|
|
325
|
+
audit,
|
|
326
|
+
publishRulesExcludingInferredTables,
|
|
327
|
+
clientReq,
|
|
328
|
+
clientInfo,
|
|
329
|
+
scope,
|
|
330
|
+
resolvedPublishObject,
|
|
331
|
+
);
|
|
332
|
+
return applyScopeToTableRules(
|
|
333
|
+
tableName,
|
|
334
|
+
tableHandler,
|
|
335
|
+
parsePublishTableRule(auditTableRules),
|
|
336
|
+
scope,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
314
339
|
if (this.dbo[tableName]?.is_media) {
|
|
315
340
|
const { rules: fileTableRules } = await getFileTableRules.bind(this)(
|
|
316
341
|
tableName,
|
|
317
|
-
|
|
342
|
+
publishRulesExcludingInferredTables,
|
|
318
343
|
clientReq,
|
|
319
344
|
clientInfo,
|
|
320
345
|
scope,
|
|
@@ -331,7 +356,7 @@ export class PublishParser {
|
|
|
331
356
|
return applyScopeToTableRules(
|
|
332
357
|
tableName,
|
|
333
358
|
tableHandler,
|
|
334
|
-
parsePublishTableRule(
|
|
359
|
+
parsePublishTableRule(publishRulesExcludingInferredTables),
|
|
335
360
|
scope,
|
|
336
361
|
);
|
|
337
362
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getObjectEntries, isDefined, isEmpty } from "prostgles-types";
|
|
1
|
+
import { fromEntries, getObjectEntries, isDefined, isEmpty } from "prostgles-types";
|
|
2
2
|
import type { TableHandler } from "../DboBuilder/TableHandler/TableHandler";
|
|
3
3
|
import { type ParsedTableRule, type PermissionScope } from "./PublishParser";
|
|
4
4
|
export const applyScopeToTableRules = (
|
|
@@ -68,9 +68,3 @@ export const applyScopeToTableRules = (
|
|
|
68
68
|
) as ParsedTableRule;
|
|
69
69
|
return result;
|
|
70
70
|
};
|
|
71
|
-
|
|
72
|
-
export const fromEntries = <K extends string | number | symbol, V>(
|
|
73
|
-
entries: readonly (readonly [K, V])[],
|
|
74
|
-
): Record<K, V> => {
|
|
75
|
-
return Object.fromEntries(entries) as Record<K, V>;
|
|
76
|
-
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isObject } from "prostgles-types";
|
|
1
2
|
import type { PublishParser } from "./PublishParser";
|
|
2
3
|
import { type PublishObject } from "./PublishParser";
|
|
3
4
|
|
|
@@ -30,5 +31,26 @@ export const getPublishedTableNames = (
|
|
|
30
31
|
tableNames.unshift(fileTableName);
|
|
31
32
|
}
|
|
32
33
|
}
|
|
34
|
+
|
|
35
|
+
const audit = publishParserInstance.prostgles.resolvedAuditConfig;
|
|
36
|
+
const publishedFileTableName =
|
|
37
|
+
fileTableName && tableNames.includes(fileTableName) ?
|
|
38
|
+
fileTableName
|
|
39
|
+
: undefined;
|
|
40
|
+
if (
|
|
41
|
+
audit &&
|
|
42
|
+
!tableNames.includes(audit.tableName) &&
|
|
43
|
+
Object.keys(audit.tables).some((tableName) => {
|
|
44
|
+
const rule = publishObject[tableName];
|
|
45
|
+
return (
|
|
46
|
+
tableName === publishedFileTableName ||
|
|
47
|
+
rule === "*" ||
|
|
48
|
+
rule === true ||
|
|
49
|
+
(isObject(rule) && Boolean(rule.select))
|
|
50
|
+
);
|
|
51
|
+
})
|
|
52
|
+
) {
|
|
53
|
+
tableNames.unshift(audit.tableName);
|
|
54
|
+
}
|
|
33
55
|
return tableNames;
|
|
34
56
|
};
|
|
@@ -228,11 +228,6 @@ export type SelectRule<Cols extends AnyObject = AnyObject, S extends DBSchema |
|
|
|
228
228
|
* */
|
|
229
229
|
filterFields?: FieldFilter<Cols>;
|
|
230
230
|
|
|
231
|
-
/**
|
|
232
|
-
* Validation logic to check/update data for each request
|
|
233
|
-
*/
|
|
234
|
-
validate?(args: SelectRequestData): SelectRequestData | Promise<SelectRequestData>;
|
|
235
|
-
|
|
236
231
|
subscribeThrottle?: number;
|
|
237
232
|
|
|
238
233
|
disableMethods?: Partial<Record<"sync" | "subscribe", 1>>;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import type pgPromise from "pg-promise";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
asName,
|
|
4
|
+
fromEntries,
|
|
5
|
+
getObjectEntries,
|
|
6
|
+
isObject,
|
|
7
|
+
pickKeys,
|
|
8
|
+
type JSONB,
|
|
9
|
+
} from "prostgles-types";
|
|
3
10
|
import { VALIDATE_SCHEMA_FUNCNAME } from "../JSONBSchemaValidation/validateJSONBSchemaSQL";
|
|
4
11
|
import type { DB } from "../Prostgles";
|
|
5
|
-
import { fromEntries } from "../PublishParser/applyScopeToTableRules";
|
|
6
12
|
import { asValue } from "../PubSubManager/PubSubManagerUtils";
|
|
7
13
|
import type { BaseColumnTypes, ColumnConfig } from "./TableConfigTypes";
|
|
8
14
|
|
package/lib/index.ts
CHANGED