prostgles-server 2.0.114 → 2.0.118

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/lib/Prostgles.ts CHANGED
@@ -1093,20 +1093,25 @@ type DboTableCommand = Request & DboTable & {
1093
1093
  const RULE_TO_METHODS = [
1094
1094
  {
1095
1095
  rule: "getColumns",
1096
+ sqlRule: "select",
1096
1097
  methods: ["getColumns"],
1097
1098
  no_limits: true,
1098
1099
  allowed_params: [],
1100
+ table_only: false,
1099
1101
  hint: ` expecting false | true | undefined`
1100
1102
  },
1101
1103
  {
1102
1104
  rule: "getInfo",
1105
+ sqlRule: "select",
1103
1106
  methods: ["getInfo"],
1104
1107
  no_limits: true,
1105
1108
  allowed_params: [],
1109
+ table_only: false,
1106
1110
  hint: ` expecting false | true | undefined`
1107
1111
  },
1108
1112
  {
1109
1113
  rule: "insert",
1114
+ sqlRule: "insert",
1110
1115
  methods: ["insert", "upsert"],
1111
1116
  no_limits: <SelectRule>{ fields: "*" },
1112
1117
  table_only: true,
@@ -1115,6 +1120,7 @@ const RULE_TO_METHODS = [
1115
1120
  },
1116
1121
  {
1117
1122
  rule: "update",
1123
+ sqlRule: "update",
1118
1124
  methods: ["update", "upsert", "updateBatch"],
1119
1125
  no_limits: <UpdateRule>{ fields: "*", filterFields: "*", returningFields: "*" },
1120
1126
  table_only: true,
@@ -1123,13 +1129,16 @@ const RULE_TO_METHODS = [
1123
1129
  },
1124
1130
  {
1125
1131
  rule: "select",
1132
+ sqlRule: "select",
1126
1133
  methods: ["findOne", "find", "count"],
1127
1134
  no_limits: <SelectRule>{ fields: "*", filterFields: "*" },
1135
+ table_only: false,
1128
1136
  allowed_params: <Array<keyof SelectRule>>["fields", "filterFields", "forcedFilter", "validate", "maxLimit"] ,
1129
1137
  hint: ` expecting "*" | true | { fields: ( string | string[] | {} ) }`
1130
1138
  },
1131
1139
  {
1132
1140
  rule: "delete",
1141
+ sqlRule: "delete",
1133
1142
  methods: ["delete", "remove"],
1134
1143
  no_limits: <DeleteRule>{ filterFields: "*" } ,
1135
1144
  table_only: true,
@@ -1137,20 +1146,24 @@ const RULE_TO_METHODS = [
1137
1146
  hint: ` expecting "*" | true | { filterFields: ( string | string[] | {} ) } \n Will use "select", "update", "delete" and "insert" rules`
1138
1147
  },
1139
1148
  {
1140
- rule: "sync", methods: ["sync", "unsync"],
1149
+ rule: "sync",
1150
+ sqlRule: "select",
1151
+ methods: ["sync", "unsync"],
1141
1152
  no_limits: null,
1142
1153
  table_only: true,
1143
1154
  allowed_params: <Array<keyof SyncRule>>["id_fields", "synced_field", "sync_type", "allow_delete", "throttle", "batch_size"],
1144
1155
  hint: ` expecting "*" | true | { id_fields: string[], synced_field: string }`
1145
1156
  },
1146
1157
  {
1147
- rule: "subscribe", methods: ["unsubscribe", "subscribe", "subscribeOne"],
1158
+ rule: "subscribe",
1159
+ sqlRule: "select",
1160
+ methods: ["unsubscribe", "subscribe", "subscribeOne"],
1148
1161
  no_limits: <SubscribeRule>{ throttle: 0 },
1149
1162
  table_only: true,
1150
1163
  allowed_params: <Array<keyof SubscribeRule>>["throttle"],
1151
1164
  hint: ` expecting "*" | true | { throttle: number } \n Will use "select" rules`
1152
1165
  }
1153
- ];
1166
+ ] as const;
1154
1167
  // const ALL_PUBLISH_METHODS = ["update", "upsert", "delete", "insert", "find", "findOne", "subscribe", "unsubscribe", "sync", "unsync", "remove"];
1155
1168
  // const ALL_PUBLISH_METHODS = RULE_TO_METHODS.map(r => r.methods).flat();
1156
1169
 
@@ -1239,7 +1252,7 @@ export class PublishParser {
1239
1252
 
1240
1253
  if(!command || !tableName) throw "command OR tableName are missing";
1241
1254
 
1242
- let rtm = RULE_TO_METHODS.find(rtms => rtms.methods.includes(command));
1255
+ let rtm = RULE_TO_METHODS.find(rtms => (rtms.methods as any).includes(command));
1243
1256
  if(!rtm){
1244
1257
  throw "Invalid command: " + command;
1245
1258
  }
@@ -1285,7 +1298,9 @@ export class PublishParser {
1285
1298
  let table_rules = _publish[tableName];// applyParamsIfFunc(_publish[tableName], localParams, this.dbo, this.db, user);
1286
1299
 
1287
1300
  /* Get view or table specific rules */
1288
- const is_view = (this.dbo[tableName] as TableHandler | ViewHandler).is_view,
1301
+ const tHandler = (this.dbo[tableName] as TableHandler | ViewHandler);
1302
+
1303
+ const is_view = tHandler.is_view,
1289
1304
  MY_RULES = RULE_TO_METHODS.filter(r => !is_view || !r.table_only);
1290
1305
 
1291
1306
  // if(tableName === "various") console.warn(1033, MY_RULES)
@@ -1295,7 +1310,14 @@ export class PublishParser {
1295
1310
  if([true, "*"].includes(table_rules as any)){
1296
1311
  table_rules = {};
1297
1312
  MY_RULES.map(r => {
1298
- table_rules[r.rule] = { ...r.no_limits };
1313
+ /** Check PG User privileges */
1314
+ if(
1315
+ tHandler.tableOrViewInfo.privileges[r.sqlRule]
1316
+ ){
1317
+ table_rules[r.rule] = { ...r.no_limits };
1318
+ }
1319
+
1320
+
1299
1321
  });
1300
1322
  // if(tableName === "various") console.warn(1042, table_rules)
1301
1323
  }
@@ -1315,7 +1337,7 @@ export class PublishParser {
1315
1337
 
1316
1338
  if(table_rules[r.rule]){
1317
1339
  /* Add implied methods if not falsy */
1318
- r.methods.map(method => {
1340
+ (r.methods as any).map(method => {
1319
1341
  if(table_rules[method] === undefined){
1320
1342
  const publishedTable = (table_rules as PublishTable);
1321
1343
  if(method === "updateBatch" && !publishedTable.update){
@@ -1340,11 +1362,17 @@ export class PublishParser {
1340
1362
 
1341
1363
  ruleKeys.filter(m => table_rules[m])
1342
1364
  .find(method => {
1343
- let rm = MY_RULES.find(r => r.rule === method || r.methods.includes(method));
1365
+ let rm = MY_RULES.find(r => r.rule === method || (r.methods as any).includes(method));
1344
1366
  if(!rm){
1345
1367
  throw `Invalid rule in publish.${tableName} -> ${method} \nExpecting any of: ${flat(MY_RULES.map(r => [r.rule, ...r.methods])).join(", ")}`;
1346
1368
  }
1347
1369
 
1370
+ /** Check user privileges */
1371
+ if(!tHandler.tableOrViewInfo.privileges[rm.sqlRule]){
1372
+ delete table_rules[method];
1373
+ return;
1374
+ }
1375
+
1348
1376
  /* Check RULES for invalid params */
1349
1377
  /* Methods do not have params -> They use them from rules */
1350
1378
  if(method === rm.rule){
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License. See LICENSE in the project root for license information.
5
5
  *--------------------------------------------------------------------------------------------*/
6
6
 
7
- import { pgp, Filter, LocalParams, isPlainObject, TableHandler, ViewHandler } from "./DboBuilder";
7
+ import { pgp, Filter, LocalParams, isPlainObject, TableHandler, ViewHandler, postgresToTsType } from "./DboBuilder";
8
8
  import { TableRule, flat } from "./Prostgles";
9
9
  import { SelectParamsBasic as SelectParams, isEmpty, FieldFilter, asName, TextFilter_FullTextSearchFilterKeys, TS_PG_Types, ColumnInfo } from "prostgles-types";
10
10
  import { get } from "./utils";
@@ -698,19 +698,38 @@ export const FUNCTIONS: FunctionSpec[] = [
698
698
  // res = `CASE WHEN position(${term} IN ${col}) > 0 THEN TRUE ELSE FALSE END`;
699
699
 
700
700
  } else if(returnType === "object" || returnType === "boolean"){
701
+ const hasChars = Boolean(term && /[a-z]/i.test(term));
702
+ const _cols = cols.map(c => {
703
+ const colInfo = allColumns.find(ac => ac.name === c);
704
+ return {
705
+ key: c,
706
+ colInfo
707
+ }
708
+ })
709
+ .filter(c => !c.colInfo || c.colInfo.udt_name !== "bytea")
710
+ .filter(c =>
711
+ /** Exclude numeric columns when the search tern contains a character */
712
+ !hasChars ||
713
+ c.colInfo?.udt_name &&
714
+ postgresToTsType(c.colInfo.udt_name) !== "number"
715
+ );
716
+ if(!_cols.length){
717
+ return (returnType === "boolean")? "FALSE" : "NULL"
718
+ }
701
719
  res = `CASE
702
- ${cols.map(c => {
703
- const colInfo = allColumns.find(ac => ac.name === c);
704
- const colNameEscaped = asNameAlias(c, tableAlias)
720
+ ${_cols
721
+ .map(c => {
722
+ const colNameEscaped = asNameAlias(c.key, tableAlias)
705
723
  let colSelect = `${colNameEscaped}::TEXT`;
706
- const isTstamp = colInfo?.udt_name.startsWith("timestamp");
707
- if(isTstamp || colInfo?.udt_name === "date"){
708
- colSelect = `( CASE WHEN ${colNameEscaped} IS NULL THEN '' ELSE concat_ws(' ',
724
+ const isTstamp = c.colInfo?.udt_name.startsWith("timestamp");
725
+ if(isTstamp || c.colInfo?.udt_name === "date"){
726
+ colSelect = `( CASE WHEN ${colNameEscaped} IS NULL THEN ''
727
+ ELSE concat_ws(' ',
709
728
  ${colNameEscaped}::TEXT,
710
- ${isTstamp? `'TZ' || to_char(${colNameEscaped}, 'OF'), `: ''}
711
- to_char(${colNameEscaped}, ' Day Month '),
712
- 'Q' || to_char(${colNameEscaped}, 'Q'),
713
- 'WK' || to_char(${colNameEscaped}, 'WW')
729
+ ${isTstamp? `'TZ' || trim(to_char(${colNameEscaped}, 'OF')), `: ''}
730
+ trim(to_char(${colNameEscaped}, 'Day Month')),
731
+ 'Q' || trim(to_char(${colNameEscaped}, 'Q')),
732
+ 'WK' || trim(to_char(${colNameEscaped}, 'WW'))
714
733
  ) END)`
715
734
  }
716
735
  let colTxt = `COALESCE(${colSelect}, '')`; // position(${term} IN ${colTxt}) > 0
@@ -723,7 +742,7 @@ export const FUNCTIONS: FunctionSpec[] = [
723
742
  return `
724
743
  WHEN ${colTxt} ${matchCase? "LIKE" : "ILIKE"} ${asValue('%' + rawTerm + '%')}
725
744
  THEN json_build_object(
726
- ${asValue(c)},
745
+ ${asValue(c.key)},
727
746
  ${makeTextMatcherArray(
728
747
  colTxt,
729
748
  term
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "2.0.114",
3
+ "version": "2.0.118",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1 +1 @@
1
- 14839
1
+ 14900
@@ -11,7 +11,7 @@
11
11
  "dependencies": {
12
12
  "@types/node": "^14.14.16",
13
13
  "@types/socket.io-client": "^1.4.35",
14
- "prostgles-client": "^1.5.127",
14
+ "prostgles-client": "^1.5.130",
15
15
  "prostgles-types": "^1.5.68",
16
16
  "socket.io-client": "^4.2.0"
17
17
  }
@@ -114,22 +114,17 @@
114
114
  "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
115
115
  },
116
116
  "node_modules/prostgles-client": {
117
- "version": "1.5.127",
118
- "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.127.tgz",
119
- "integrity": "sha512-2iA5CD6hH9UGh1q7FEtmSUjmzUHHUHtskf60ik2d0i9oML+6yN8dxZSn7AZuWA+DRIm85wYDS2hfFzumJgUeCQ==",
117
+ "version": "1.5.130",
118
+ "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.130.tgz",
119
+ "integrity": "sha512-Dd3b1JY7avcZ2oS5avCQ5KyzLaQTaYDzDE/q9bIiY7R5JJsesGKoRsqJISuNWyGYeVCY93n+r/EN88v0Jsj48A==",
120
120
  "dependencies": {
121
- "prostgles-types": "^1.5.120"
121
+ "prostgles-types": "^1.5.121"
122
122
  }
123
123
  },
124
- "node_modules/prostgles-client/node_modules/prostgles-types": {
125
- "version": "1.5.120",
126
- "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.120.tgz",
127
- "integrity": "sha512-dWrXMJFhYmTKsiIBzYHTsCKXN6GoJGJe/lTohnkg9+drAhXbJvUrJ5nZ8LwYgkzG+wbWBwW82KIBGK6Zg4OqLw=="
128
- },
129
124
  "node_modules/prostgles-types": {
130
- "version": "1.5.105",
131
- "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.105.tgz",
132
- "integrity": "sha512-k87FnawwTuyPpnoOPDWMeu7QDevuNhOr9x7xoQ2GxF84Y7W66FPrdE/jh6kD7oqzIZtsV/WEVd0WtX+BC2uwEg=="
125
+ "version": "1.5.121",
126
+ "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.121.tgz",
127
+ "integrity": "sha512-9fzF/3tISjv1P6B0uV2ubZRKqblUvDG8K7+9INdcR8di2UOVD2vONgCgvFe7ZH12FyUC5q1OM1PUm41dgo9cqQ=="
133
128
  },
134
129
  "node_modules/socket.io-client": {
135
130
  "version": "4.2.0",
@@ -280,24 +275,17 @@
280
275
  "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
281
276
  },
282
277
  "prostgles-client": {
283
- "version": "1.5.127",
284
- "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.127.tgz",
285
- "integrity": "sha512-2iA5CD6hH9UGh1q7FEtmSUjmzUHHUHtskf60ik2d0i9oML+6yN8dxZSn7AZuWA+DRIm85wYDS2hfFzumJgUeCQ==",
278
+ "version": "1.5.130",
279
+ "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-1.5.130.tgz",
280
+ "integrity": "sha512-Dd3b1JY7avcZ2oS5avCQ5KyzLaQTaYDzDE/q9bIiY7R5JJsesGKoRsqJISuNWyGYeVCY93n+r/EN88v0Jsj48A==",
286
281
  "requires": {
287
- "prostgles-types": "^1.5.120"
288
- },
289
- "dependencies": {
290
- "prostgles-types": {
291
- "version": "1.5.120",
292
- "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.120.tgz",
293
- "integrity": "sha512-dWrXMJFhYmTKsiIBzYHTsCKXN6GoJGJe/lTohnkg9+drAhXbJvUrJ5nZ8LwYgkzG+wbWBwW82KIBGK6Zg4OqLw=="
294
- }
282
+ "prostgles-types": "^1.5.121"
295
283
  }
296
284
  },
297
285
  "prostgles-types": {
298
- "version": "1.5.105",
299
- "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.105.tgz",
300
- "integrity": "sha512-k87FnawwTuyPpnoOPDWMeu7QDevuNhOr9x7xoQ2GxF84Y7W66FPrdE/jh6kD7oqzIZtsV/WEVd0WtX+BC2uwEg=="
286
+ "version": "1.5.121",
287
+ "resolved": "https://registry.npmjs.org/prostgles-types/-/prostgles-types-1.5.121.tgz",
288
+ "integrity": "sha512-9fzF/3tISjv1P6B0uV2ubZRKqblUvDG8K7+9INdcR8di2UOVD2vONgCgvFe7ZH12FyUC5q1OM1PUm41dgo9cqQ=="
301
289
  },
302
290
  "socket.io-client": {
303
291
  "version": "4.2.0",
@@ -14,7 +14,7 @@
14
14
  "dependencies": {
15
15
  "@types/node": "^14.14.16",
16
16
  "@types/socket.io-client": "^1.4.35",
17
- "prostgles-client": "^1.5.127",
17
+ "prostgles-client": "^1.5.130",
18
18
  "prostgles-types": "^1.5.68",
19
19
  "socket.io-client": "^4.2.0"
20
20
  }
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "../..": {
25
25
  "name": "prostgles-server",
26
- "version": "2.0.113",
26
+ "version": "2.0.117",
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@aws-sdk/client-s3": "^3.32.0",