prostgles-server 2.0.265 → 2.0.268
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/DboBuilder/runSQL.d.ts +6 -0
- package/dist/DboBuilder/runSQL.d.ts.map +1 -0
- package/dist/DboBuilder/runSQL.js +104 -0
- package/dist/DboBuilder/runSQL.js.map +1 -0
- package/dist/DboBuilder.d.ts +5 -5
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +13 -176
- package/dist/DboBuilder.js.map +1 -1
- package/dist/Prostgles.js +1 -1
- package/dist/Prostgles.js.map +1 -1
- package/dist/PublishParser.js +2 -2
- package/dist/PublishParser.js.map +1 -1
- package/dist/QueryBuilder.d.ts +3 -1
- package/dist/QueryBuilder.d.ts.map +1 -1
- package/lib/DboBuilder/runSQL.d.ts +6 -0
- package/lib/DboBuilder/runSQL.d.ts.map +1 -0
- package/lib/DboBuilder/runSQL.js +103 -0
- package/lib/DboBuilder/runSQL.ts +109 -0
- package/lib/DboBuilder.d.ts +5 -5
- package/lib/DboBuilder.d.ts.map +1 -1
- package/lib/DboBuilder.js +13 -176
- package/lib/DboBuilder.ts +16 -205
- package/lib/Prostgles.js +1 -1
- package/lib/Prostgles.ts +1 -1
- package/lib/PublishParser.js +2 -2
- package/lib/PublishParser.ts +2 -2
- package/package.json +2 -2
- package/tests/client/PID.txt +1 -1
- package/tests/server/package-lock.json +3 -3
package/lib/DboBuilder.js
CHANGED
|
@@ -32,7 +32,7 @@ exports.postgresToTsType = exports.isPlainObject = exports.DboBuilder = exports.
|
|
|
32
32
|
const Bluebird = __importStar(require("bluebird"));
|
|
33
33
|
// declare global { export interface Promise<T> extends Bluebird<T> {} }
|
|
34
34
|
const pgPromise = __importStar(require("pg-promise"));
|
|
35
|
-
const
|
|
35
|
+
const runSQL_1 = require("./DboBuilder/runSQL");
|
|
36
36
|
const prostgles_types_1 = require("prostgles-types");
|
|
37
37
|
// export const getFilterFields = (f: Filter | any, $and_key: string, $or_key: string, prevFields: string[] = []): string[] => {
|
|
38
38
|
// if(Array.isArray(f)){
|
|
@@ -666,7 +666,7 @@ class ViewHandler {
|
|
|
666
666
|
async find(filter, selectParams, param3_unused, tableRules, localParams) {
|
|
667
667
|
try {
|
|
668
668
|
filter = filter || {};
|
|
669
|
-
const allowedReturnTypes = ["row", "value", "values"];
|
|
669
|
+
const allowedReturnTypes = ["row", "value", "values", "statement"];
|
|
670
670
|
const { returnType } = selectParams || {};
|
|
671
671
|
if (returnType && !allowedReturnTypes.includes(returnType)) {
|
|
672
672
|
throw `returnType (${returnType}) can only be ${allowedReturnTypes.join(" OR ")}`;
|
|
@@ -710,6 +710,12 @@ class ViewHandler {
|
|
|
710
710
|
}
|
|
711
711
|
if (returnQuery)
|
|
712
712
|
return _query;
|
|
713
|
+
if (returnType === "statement") {
|
|
714
|
+
if (!(await (0, runSQL_1.canRunSQL)(this.dboBuilder.prostgles, localParams))) {
|
|
715
|
+
throw `Not allowed: {returnType: "statement"} requires sql privileges `;
|
|
716
|
+
}
|
|
717
|
+
return _query;
|
|
718
|
+
}
|
|
713
719
|
if (["row", "value"].includes(returnType)) {
|
|
714
720
|
return (this.t || this.db).oneOrNone(_query).then(data => {
|
|
715
721
|
return (data && returnType === "value") ? Object.values(data)[0] : data;
|
|
@@ -749,7 +755,7 @@ class ViewHandler {
|
|
|
749
755
|
throw parseError(e, `Issue with dbo.${this.name}.findOne()`);
|
|
750
756
|
}
|
|
751
757
|
}
|
|
752
|
-
async count(filter, param2_unused, param3_unused, table_rules, localParams
|
|
758
|
+
async count(filter, param2_unused, param3_unused, table_rules, localParams) {
|
|
753
759
|
filter = filter || {};
|
|
754
760
|
try {
|
|
755
761
|
return await this.find(filter, { select: "", limit: 0 }, undefined, table_rules, localParams)
|
|
@@ -766,7 +772,7 @@ class ViewHandler {
|
|
|
766
772
|
throw parseError(e, `dbo.${this.name}.count()`);
|
|
767
773
|
}
|
|
768
774
|
}
|
|
769
|
-
async size(filter, selectParams, param3_unused, table_rules, localParams
|
|
775
|
+
async size(filter, selectParams, param3_unused, table_rules, localParams) {
|
|
770
776
|
filter = filter || {};
|
|
771
777
|
try {
|
|
772
778
|
return await this.find(filter, { ...selectParams, limit: 2 }, undefined, table_rules, localParams)
|
|
@@ -948,8 +954,8 @@ class ViewHandler {
|
|
|
948
954
|
let finalWhere = "";
|
|
949
955
|
let t2Rules = undefined, forcedFilter, filterFields, tableAlias;
|
|
950
956
|
/* Check if allowed to view data - forcedFilters will bypass this check through isForcedFilterBypass */
|
|
951
|
-
if (localParams && (!localParams?.socket && !localParams?.httpReq))
|
|
952
|
-
throw "Unexpected: localParams missing socket/httpReq";
|
|
957
|
+
if (localParams?.isRemoteRequest && (!localParams?.socket && !localParams?.httpReq))
|
|
958
|
+
throw "Unexpected: localParams isRemoteRequest and missing socket/httpReq: ";
|
|
953
959
|
if (localParams && (localParams.socket || localParams.httpReq) && this.dboBuilder.publishParser) {
|
|
954
960
|
t2Rules = await this.dboBuilder.publishParser.getValidatedRequestRuleWusr({ tableName: t2, command: "find", localParams });
|
|
955
961
|
if (!t2Rules || !t2Rules.select)
|
|
@@ -1842,8 +1848,6 @@ class TableHandler extends ViewHandler {
|
|
|
1842
1848
|
}
|
|
1843
1849
|
}
|
|
1844
1850
|
exports.TableHandler = TableHandler;
|
|
1845
|
-
let DATA_TYPES;
|
|
1846
|
-
let USER_TABLES;
|
|
1847
1851
|
const Prostgles_1 = require("./Prostgles");
|
|
1848
1852
|
const DBSchemaBuilder_1 = require("./DBSchemaBuilder");
|
|
1849
1853
|
class DboBuilder {
|
|
@@ -1888,97 +1892,7 @@ class DboBuilder {
|
|
|
1888
1892
|
return this;
|
|
1889
1893
|
};
|
|
1890
1894
|
this.runSQL = async (query, params, options, localParams) => {
|
|
1891
|
-
|
|
1892
|
-
DATA_TYPES ?? (DATA_TYPES = await this.db.any("SELECT oid, typname FROM pg_type") ?? []);
|
|
1893
|
-
USER_TABLES ?? (USER_TABLES = await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables") ?? []);
|
|
1894
|
-
const canRunSQL = async (localParams) => {
|
|
1895
|
-
if (!localParams?.socket || !localParams?.httpReq)
|
|
1896
|
-
return true;
|
|
1897
|
-
const { socket } = localParams;
|
|
1898
|
-
const publishParams = await this.prostgles.publishParser.getPublishParams({ socket });
|
|
1899
|
-
let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
1900
|
-
return Boolean(res && typeof res === "boolean" || res === "*");
|
|
1901
|
-
};
|
|
1902
|
-
if (!(await canRunSQL(localParams)))
|
|
1903
|
-
throw "Not allowed to run SQL";
|
|
1904
|
-
const { returnType, allowListen } = options || {};
|
|
1905
|
-
const { socket } = localParams || {};
|
|
1906
|
-
const db = localParams?.tx?.t || this.db;
|
|
1907
|
-
if (returnType === "noticeSubscription") {
|
|
1908
|
-
if (!socket)
|
|
1909
|
-
throw "Only allowed with client socket";
|
|
1910
|
-
return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
1911
|
-
}
|
|
1912
|
-
else if (returnType === "statement") {
|
|
1913
|
-
try {
|
|
1914
|
-
return exports.pgp.as.format(query, params);
|
|
1915
|
-
}
|
|
1916
|
-
catch (err) {
|
|
1917
|
-
throw err.toString();
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
|
-
else if (db) {
|
|
1921
|
-
let finalQuery = query + "";
|
|
1922
|
-
if (returnType === "arrayMode" && !["listen ", "notify "].find(c => query.toLowerCase().trim().startsWith(c))) {
|
|
1923
|
-
finalQuery = new PQ({ text: exports.pgp.as.format(query, params), rowMode: "array" });
|
|
1924
|
-
}
|
|
1925
|
-
let _qres = await db.result(finalQuery, params);
|
|
1926
|
-
const { fields, rows, command } = _qres;
|
|
1927
|
-
/**
|
|
1928
|
-
* Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
1929
|
-
*/
|
|
1930
|
-
const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
1931
|
-
if (watchSchema &&
|
|
1932
|
-
(!this.prostgles.isSuperUser || watchSchemaType === "prostgles_queries")) {
|
|
1933
|
-
if (["CREATE", "ALTER", "DROP"].includes(command)) {
|
|
1934
|
-
this.prostgles.onSchemaChange({ command, query });
|
|
1935
|
-
}
|
|
1936
|
-
else if (query) {
|
|
1937
|
-
const cleanedQuery = query.toLowerCase().replace(/\s\s+/g, ' ');
|
|
1938
|
-
if (PubSubManager_1.PubSubManager.SCHEMA_ALTERING_QUERIES.some(q => cleanedQuery.includes(q.toLowerCase()))) {
|
|
1939
|
-
this.prostgles.onSchemaChange({ command, query });
|
|
1940
|
-
}
|
|
1941
|
-
}
|
|
1942
|
-
}
|
|
1943
|
-
if (command === "LISTEN") {
|
|
1944
|
-
if (!allowListen)
|
|
1945
|
-
throw new Error(`Your query contains a LISTEN command. Set { allowListen: true } to get subscription hooks. Or ignore this message`);
|
|
1946
|
-
if (!socket)
|
|
1947
|
-
throw "Only allowed with client socket";
|
|
1948
|
-
return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
1949
|
-
}
|
|
1950
|
-
else if (returnType === "rows") {
|
|
1951
|
-
return rows;
|
|
1952
|
-
}
|
|
1953
|
-
else if (returnType === "row") {
|
|
1954
|
-
return rows[0];
|
|
1955
|
-
}
|
|
1956
|
-
else if (returnType === "value") {
|
|
1957
|
-
return Object.values(rows?.[0] || {})?.[0];
|
|
1958
|
-
}
|
|
1959
|
-
else if (returnType === "values") {
|
|
1960
|
-
return rows.map(r => Object.values(r[0]));
|
|
1961
|
-
}
|
|
1962
|
-
else {
|
|
1963
|
-
let qres = {
|
|
1964
|
-
duration: 0,
|
|
1965
|
-
..._qres,
|
|
1966
|
-
fields: fields?.map(f => {
|
|
1967
|
-
const dataType = DATA_TYPES.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text", tableName = USER_TABLES.find(t => +t.relid === +f.tableID), tsDataType = postgresToTsType(dataType);
|
|
1968
|
-
return {
|
|
1969
|
-
...f,
|
|
1970
|
-
tsDataType,
|
|
1971
|
-
dataType,
|
|
1972
|
-
udt_name: dataType,
|
|
1973
|
-
tableName: tableName?.relname
|
|
1974
|
-
};
|
|
1975
|
-
}) ?? []
|
|
1976
|
-
};
|
|
1977
|
-
return qres;
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
else
|
|
1981
|
-
console.error("db missing");
|
|
1895
|
+
return runSQL_1.runSQL.bind(this)(query, params, options, localParams);
|
|
1982
1896
|
};
|
|
1983
1897
|
this.getTX = (cb) => {
|
|
1984
1898
|
return this.db.tx((t) => {
|
|
@@ -2156,83 +2070,6 @@ class DboBuilder {
|
|
|
2156
2070
|
}
|
|
2157
2071
|
if (!this.dbo.sql) {
|
|
2158
2072
|
this.dbo.sql = this.runSQL;
|
|
2159
|
-
// this.dbo.sql = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
2160
|
-
// const canRunSQL = async (localParams?: LocalParams) => {
|
|
2161
|
-
// if(!localParams?.socket || !localParams?.httpReq) return true;
|
|
2162
|
-
// const { socket } = localParams;
|
|
2163
|
-
// const publishParams = await this.prostgles.publishParser!.getPublishParams({ socket });
|
|
2164
|
-
// let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
2165
|
-
// return Boolean(res && typeof res === "boolean" || res === "*");
|
|
2166
|
-
// }
|
|
2167
|
-
// if(!(await canRunSQL(localParams))) throw "Not allowed to run SQL";
|
|
2168
|
-
// const { returnType, allowListen }: SQLOptions = options || ({} as any);
|
|
2169
|
-
// const { socket } = localParams || {};
|
|
2170
|
-
// if(returnType === "noticeSubscription"){
|
|
2171
|
-
// if(!socket) throw "Only allowed with client socket"
|
|
2172
|
-
// return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
2173
|
-
// } else if(returnType === "statement"){
|
|
2174
|
-
// try {
|
|
2175
|
-
// return pgp.as.format(query, params);
|
|
2176
|
-
// } catch (err){
|
|
2177
|
-
// throw (err as any).toString();
|
|
2178
|
-
// }
|
|
2179
|
-
// } else if(this.db) {
|
|
2180
|
-
// let finalQuery = query + "";
|
|
2181
|
-
// if(returnType === "arrayMode" && !["listen ", "notify "].find(c => query.toLowerCase().trim().startsWith(c))){
|
|
2182
|
-
// finalQuery = new PQ({ text: pgp.as.format(query, params), rowMode: "array" });
|
|
2183
|
-
// }
|
|
2184
|
-
// let _qres = await this.db.result(finalQuery, params)
|
|
2185
|
-
// const { fields, rows, command } = _qres;
|
|
2186
|
-
// /**
|
|
2187
|
-
// * Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
2188
|
-
// */
|
|
2189
|
-
// const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
2190
|
-
// if(
|
|
2191
|
-
// watchSchema &&
|
|
2192
|
-
// (!this.prostgles.isSuperUser || watchSchemaType === "prostgles_queries")
|
|
2193
|
-
// ){
|
|
2194
|
-
// if(["CREATE", "ALTER", "DROP"].includes(command)){
|
|
2195
|
-
// this.prostgles.onSchemaChange({ command, query })
|
|
2196
|
-
// } else if(query) {
|
|
2197
|
-
// const cleanedQuery = query.toLowerCase().replace(/\s\s+/g, ' ');
|
|
2198
|
-
// if(PubSubManager.SCHEMA_ALTERING_QUERIES.some(q => cleanedQuery.includes(q.toLowerCase()))){
|
|
2199
|
-
// this.prostgles.onSchemaChange({ command, query })
|
|
2200
|
-
// }
|
|
2201
|
-
// }
|
|
2202
|
-
// }
|
|
2203
|
-
// if(command === "LISTEN"){
|
|
2204
|
-
// if(!allowListen) throw new Error(`Your query contains a LISTEN command. Set { allowListen: true } to get subscription hooks. Or ignore this message`)
|
|
2205
|
-
// if(!socket) throw "Only allowed with client socket"
|
|
2206
|
-
// return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
2207
|
-
// } else if(returnType === "rows") {
|
|
2208
|
-
// return rows;
|
|
2209
|
-
// } else if(returnType === "row") {
|
|
2210
|
-
// return rows[0];
|
|
2211
|
-
// } else if(returnType === "value") {
|
|
2212
|
-
// return Object.values(rows?.[0] || {})?.[0];
|
|
2213
|
-
// } else if(returnType === "values") {
|
|
2214
|
-
// return rows.map(r => Object.values(r[0]));
|
|
2215
|
-
// } else {
|
|
2216
|
-
// let qres: SQLResult<typeof returnType> = {
|
|
2217
|
-
// duration: 0,
|
|
2218
|
-
// ..._qres,
|
|
2219
|
-
// fields: fields?.map(f => {
|
|
2220
|
-
// const dataType = DATA_TYPES.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text",
|
|
2221
|
-
// tableName = USER_TABLES.find(t => +t.relid === +f.tableID),
|
|
2222
|
-
// tsDataType = postgresToTsType(dataType);
|
|
2223
|
-
// return {
|
|
2224
|
-
// ...f,
|
|
2225
|
-
// tsDataType,
|
|
2226
|
-
// dataType,
|
|
2227
|
-
// udt_name: dataType,
|
|
2228
|
-
// tableName: tableName?.relname
|
|
2229
|
-
// }
|
|
2230
|
-
// }) ?? []
|
|
2231
|
-
// };
|
|
2232
|
-
// return qres;
|
|
2233
|
-
// }
|
|
2234
|
-
// } else console.error("db missing");
|
|
2235
|
-
// }
|
|
2236
2073
|
}
|
|
2237
2074
|
else {
|
|
2238
2075
|
console.warn(`Could not create dbo.sql handler because there is already a table named "sql"`);
|
package/lib/DboBuilder.ts
CHANGED
|
@@ -8,7 +8,7 @@ import * as Bluebird from "bluebird";
|
|
|
8
8
|
// declare global { export interface Promise<T> extends Bluebird<T> {} }
|
|
9
9
|
|
|
10
10
|
import * as pgPromise from 'pg-promise';
|
|
11
|
-
|
|
11
|
+
import { canRunSQL, runSQL } from "./DboBuilder/runSQL";
|
|
12
12
|
import pg = require('pg-promise/typescript/pg-subset');
|
|
13
13
|
import {
|
|
14
14
|
ColumnInfo, ValidatedColumnInfo, FieldFilter, SelectParams, SubscribeParams,
|
|
@@ -152,7 +152,7 @@ export type LocalParams = {
|
|
|
152
152
|
httpReq?: any;
|
|
153
153
|
socket?: PRGLIOSocket;
|
|
154
154
|
func?: () => any;
|
|
155
|
-
|
|
155
|
+
isRemoteRequest?: boolean;
|
|
156
156
|
testRule?: boolean;
|
|
157
157
|
tableAlias?: string;
|
|
158
158
|
// subOne?: boolean;
|
|
@@ -1043,7 +1043,7 @@ export class ViewHandler {
|
|
|
1043
1043
|
async find(filter?: Filter, selectParams?: SelectParams , param3_unused?: undefined, tableRules?: TableRule, localParams?: LocalParams): Promise<any[]>{
|
|
1044
1044
|
try {
|
|
1045
1045
|
filter = filter || {};
|
|
1046
|
-
const allowedReturnTypes: Array<SelectParams["returnType"]> = ["row", "value", "values"]
|
|
1046
|
+
const allowedReturnTypes: Array<SelectParams["returnType"]> = ["row", "value", "values", "statement"]
|
|
1047
1047
|
const { returnType } = selectParams || {};
|
|
1048
1048
|
if(returnType && !allowedReturnTypes.includes(returnType)){
|
|
1049
1049
|
throw `returnType (${returnType}) can only be ${allowedReturnTypes.join(" OR ")}`
|
|
@@ -1091,6 +1091,14 @@ export class ViewHandler {
|
|
|
1091
1091
|
}
|
|
1092
1092
|
|
|
1093
1093
|
if(returnQuery) return (_query as unknown as any[]);
|
|
1094
|
+
|
|
1095
|
+
if(returnType === "statement"){
|
|
1096
|
+
if(!(await canRunSQL(this.dboBuilder.prostgles, localParams))){
|
|
1097
|
+
throw `Not allowed: {returnType: "statement"} requires sql privileges `
|
|
1098
|
+
}
|
|
1099
|
+
return _query as unknown as any[];
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1094
1102
|
if(["row", "value"].includes(returnType!)) {
|
|
1095
1103
|
return (this.t || this.db).oneOrNone(_query).then(data => {
|
|
1096
1104
|
return (data && returnType === "value")? Object.values(data)[0] : data;
|
|
@@ -1128,7 +1136,7 @@ export class ViewHandler {
|
|
|
1128
1136
|
}
|
|
1129
1137
|
}
|
|
1130
1138
|
|
|
1131
|
-
async count(filter?: Filter, param2_unused?: undefined, param3_unused?: undefined, table_rules?: TableRule, localParams
|
|
1139
|
+
async count(filter?: Filter, param2_unused?: undefined, param3_unused?: undefined, table_rules?: TableRule, localParams?: LocalParams): Promise<number>{
|
|
1132
1140
|
filter = filter || {};
|
|
1133
1141
|
try {
|
|
1134
1142
|
return await this.find(filter, { select: "", limit: 0 }, undefined, table_rules, localParams)
|
|
@@ -1144,7 +1152,7 @@ export class ViewHandler {
|
|
|
1144
1152
|
}
|
|
1145
1153
|
}
|
|
1146
1154
|
|
|
1147
|
-
async size(filter?: Filter, selectParams?: SelectParams, param3_unused?: undefined, table_rules?: TableRule, localParams
|
|
1155
|
+
async size(filter?: Filter, selectParams?: SelectParams, param3_unused?: undefined, table_rules?: TableRule, localParams?: LocalParams): Promise<string>{
|
|
1148
1156
|
filter = filter || {};
|
|
1149
1157
|
try {
|
|
1150
1158
|
return await this.find(filter, { ...selectParams, limit: 2 }, undefined, table_rules, localParams)
|
|
@@ -1383,7 +1391,7 @@ export class ViewHandler {
|
|
|
1383
1391
|
tableAlias;
|
|
1384
1392
|
|
|
1385
1393
|
/* Check if allowed to view data - forcedFilters will bypass this check through isForcedFilterBypass */
|
|
1386
|
-
if(localParams && (!localParams?.socket && !localParams?.httpReq)) throw "Unexpected: localParams missing socket/httpReq"
|
|
1394
|
+
if(localParams?.isRemoteRequest && (!localParams?.socket && !localParams?.httpReq)) throw "Unexpected: localParams isRemoteRequest and missing socket/httpReq: ";
|
|
1387
1395
|
if(localParams && (localParams.socket || localParams.httpReq) && this.dboBuilder.publishParser){
|
|
1388
1396
|
|
|
1389
1397
|
t2Rules = await this.dboBuilder.publishParser.getValidatedRequestRuleWusr({ tableName: t2, command: "find", localParams }) as TableRule;
|
|
@@ -2439,13 +2447,9 @@ export class TableHandler extends ViewHandler {
|
|
|
2439
2447
|
|
|
2440
2448
|
}
|
|
2441
2449
|
|
|
2442
|
-
let DATA_TYPES: {oid: string, typname: PG_COLUMN_UDT_DATA_TYPE }[] | undefined;
|
|
2443
|
-
let USER_TABLES: { relid: string; relname: string; }[] | undefined;
|
|
2444
|
-
|
|
2445
2450
|
import { JOIN_TYPES } from "./Prostgles";
|
|
2446
2451
|
import { BasicSession } from "./AuthHandler";
|
|
2447
2452
|
import { DBOFullyTyped, getDBSchema } from "./DBSchemaBuilder";
|
|
2448
|
-
import { bool } from "aws-sdk/clients/signer";
|
|
2449
2453
|
|
|
2450
2454
|
export class DboBuilder {
|
|
2451
2455
|
tablesOrViews?: TableSchema[]; //TableSchema TableOrViewInfo
|
|
@@ -2651,107 +2655,9 @@ export class DboBuilder {
|
|
|
2651
2655
|
return this.joinPaths;
|
|
2652
2656
|
}
|
|
2653
2657
|
|
|
2654
|
-
runSQL = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
2655
|
-
|
|
2656
|
-
/** Cache types */
|
|
2657
|
-
DATA_TYPES ??= await this.db.any("SELECT oid, typname FROM pg_type") ?? [];
|
|
2658
|
-
USER_TABLES ??= await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables") ?? [];
|
|
2659
|
-
|
|
2660
|
-
const canRunSQL = async (localParams?: LocalParams) => {
|
|
2661
|
-
if(!localParams?.socket || !localParams?.httpReq) return true;
|
|
2662
|
-
|
|
2663
|
-
const { socket } = localParams;
|
|
2664
|
-
const publishParams = await this.prostgles.publishParser!.getPublishParams({ socket });
|
|
2665
|
-
let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
2666
|
-
return Boolean(res && typeof res === "boolean" || res === "*");
|
|
2667
|
-
}
|
|
2668
|
-
|
|
2669
|
-
if(!(await canRunSQL(localParams))) throw "Not allowed to run SQL";
|
|
2670
|
-
|
|
2671
|
-
const { returnType, allowListen }: SQLOptions = options || ({} as any);
|
|
2672
|
-
const { socket } = localParams || {};
|
|
2673
|
-
|
|
2674
|
-
const db = localParams?.tx?.t || this.db;
|
|
2675
|
-
if(returnType === "noticeSubscription"){
|
|
2676
|
-
if(!socket) throw "Only allowed with client socket"
|
|
2677
|
-
return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
2678
|
-
} else if(returnType === "statement"){
|
|
2679
|
-
try {
|
|
2680
|
-
return pgp.as.format(query, params);
|
|
2681
|
-
} catch (err){
|
|
2682
|
-
throw (err as any).toString();
|
|
2683
|
-
}
|
|
2684
|
-
} else if(db) {
|
|
2685
|
-
|
|
2686
|
-
let finalQuery = query + "";
|
|
2687
|
-
if(returnType === "arrayMode" && !["listen ", "notify "].find(c => query.toLowerCase().trim().startsWith(c))){
|
|
2688
|
-
finalQuery = new PQ({ text: pgp.as.format(query, params), rowMode: "array" });
|
|
2689
|
-
}
|
|
2690
|
-
|
|
2691
|
-
let _qres = await db.result(finalQuery, params)
|
|
2692
|
-
const { fields, rows, command } = _qres;
|
|
2693
|
-
|
|
2694
|
-
/**
|
|
2695
|
-
* Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
2696
|
-
*/
|
|
2697
|
-
const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
2698
|
-
|
|
2699
|
-
if(
|
|
2700
|
-
watchSchema &&
|
|
2701
|
-
(!this.prostgles.isSuperUser || watchSchemaType === "prostgles_queries")
|
|
2702
|
-
){
|
|
2703
|
-
if(["CREATE", "ALTER", "DROP"].includes(command)){
|
|
2704
|
-
this.prostgles.onSchemaChange({ command, query })
|
|
2705
|
-
} else if(query) {
|
|
2706
|
-
const cleanedQuery = query.toLowerCase().replace(/\s\s+/g, ' ');
|
|
2707
|
-
if(PubSubManager.SCHEMA_ALTERING_QUERIES.some(q => cleanedQuery.includes(q.toLowerCase()))){
|
|
2708
|
-
this.prostgles.onSchemaChange({ command, query })
|
|
2709
|
-
}
|
|
2710
|
-
}
|
|
2711
|
-
}
|
|
2712
|
-
|
|
2713
|
-
if(command === "LISTEN"){
|
|
2714
|
-
if(!allowListen) throw new Error(`Your query contains a LISTEN command. Set { allowListen: true } to get subscription hooks. Or ignore this message`)
|
|
2715
|
-
if(!socket) throw "Only allowed with client socket"
|
|
2716
|
-
return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
2717
|
-
|
|
2718
|
-
} else if(returnType === "rows") {
|
|
2719
|
-
return rows;
|
|
2720
|
-
|
|
2721
|
-
} else if(returnType === "row") {
|
|
2722
|
-
return rows[0];
|
|
2723
|
-
|
|
2724
|
-
} else if(returnType === "value") {
|
|
2725
|
-
return Object.values(rows?.[0] || {})?.[0];
|
|
2726
|
-
|
|
2727
|
-
} else if(returnType === "values") {
|
|
2728
|
-
return rows.map(r => Object.values(r[0]));
|
|
2729
|
-
|
|
2730
|
-
} else {
|
|
2731
|
-
|
|
2732
|
-
let qres: SQLResult<typeof returnType> = {
|
|
2733
|
-
duration: 0,
|
|
2734
|
-
..._qres,
|
|
2735
|
-
fields: fields?.map(f => {
|
|
2736
|
-
const dataType = DATA_TYPES!.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text",
|
|
2737
|
-
tableName = USER_TABLES!.find(t => +t.relid === +f.tableID),
|
|
2738
|
-
tsDataType = postgresToTsType(dataType);
|
|
2739
|
-
|
|
2740
|
-
return {
|
|
2741
|
-
...f,
|
|
2742
|
-
tsDataType,
|
|
2743
|
-
dataType,
|
|
2744
|
-
udt_name: dataType,
|
|
2745
|
-
tableName: tableName?.relname
|
|
2746
|
-
}
|
|
2747
|
-
}) ?? []
|
|
2748
|
-
};
|
|
2749
|
-
return qres;
|
|
2750
|
-
}
|
|
2751
|
-
|
|
2752
|
-
} else console.error("db missing");
|
|
2658
|
+
private runSQL = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
2659
|
+
return runSQL.bind(this)(query, params, options, localParams);
|
|
2753
2660
|
}
|
|
2754
|
-
|
|
2755
2661
|
async build(): Promise<DBHandlerServer>{
|
|
2756
2662
|
|
|
2757
2663
|
this.tablesOrViews = await getTablesForSchemaPostgresSQL(this.db);
|
|
@@ -2820,101 +2726,6 @@ export class DboBuilder {
|
|
|
2820
2726
|
if(!this.dbo.sql){
|
|
2821
2727
|
|
|
2822
2728
|
this.dbo.sql = this.runSQL;
|
|
2823
|
-
// this.dbo.sql = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
2824
|
-
|
|
2825
|
-
// const canRunSQL = async (localParams?: LocalParams) => {
|
|
2826
|
-
// if(!localParams?.socket || !localParams?.httpReq) return true;
|
|
2827
|
-
|
|
2828
|
-
// const { socket } = localParams;
|
|
2829
|
-
// const publishParams = await this.prostgles.publishParser!.getPublishParams({ socket });
|
|
2830
|
-
// let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
2831
|
-
// return Boolean(res && typeof res === "boolean" || res === "*");
|
|
2832
|
-
// }
|
|
2833
|
-
|
|
2834
|
-
// if(!(await canRunSQL(localParams))) throw "Not allowed to run SQL";
|
|
2835
|
-
|
|
2836
|
-
// const { returnType, allowListen }: SQLOptions = options || ({} as any);
|
|
2837
|
-
// const { socket } = localParams || {};
|
|
2838
|
-
|
|
2839
|
-
// if(returnType === "noticeSubscription"){
|
|
2840
|
-
// if(!socket) throw "Only allowed with client socket"
|
|
2841
|
-
// return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
2842
|
-
// } else if(returnType === "statement"){
|
|
2843
|
-
// try {
|
|
2844
|
-
// return pgp.as.format(query, params);
|
|
2845
|
-
// } catch (err){
|
|
2846
|
-
// throw (err as any).toString();
|
|
2847
|
-
// }
|
|
2848
|
-
// } else if(this.db) {
|
|
2849
|
-
|
|
2850
|
-
// let finalQuery = query + "";
|
|
2851
|
-
// if(returnType === "arrayMode" && !["listen ", "notify "].find(c => query.toLowerCase().trim().startsWith(c))){
|
|
2852
|
-
// finalQuery = new PQ({ text: pgp.as.format(query, params), rowMode: "array" });
|
|
2853
|
-
// }
|
|
2854
|
-
|
|
2855
|
-
// let _qres = await this.db.result(finalQuery, params)
|
|
2856
|
-
// const { fields, rows, command } = _qres;
|
|
2857
|
-
|
|
2858
|
-
// /**
|
|
2859
|
-
// * Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
2860
|
-
// */
|
|
2861
|
-
// const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
2862
|
-
|
|
2863
|
-
// if(
|
|
2864
|
-
// watchSchema &&
|
|
2865
|
-
// (!this.prostgles.isSuperUser || watchSchemaType === "prostgles_queries")
|
|
2866
|
-
// ){
|
|
2867
|
-
// if(["CREATE", "ALTER", "DROP"].includes(command)){
|
|
2868
|
-
// this.prostgles.onSchemaChange({ command, query })
|
|
2869
|
-
// } else if(query) {
|
|
2870
|
-
// const cleanedQuery = query.toLowerCase().replace(/\s\s+/g, ' ');
|
|
2871
|
-
// if(PubSubManager.SCHEMA_ALTERING_QUERIES.some(q => cleanedQuery.includes(q.toLowerCase()))){
|
|
2872
|
-
// this.prostgles.onSchemaChange({ command, query })
|
|
2873
|
-
// }
|
|
2874
|
-
// }
|
|
2875
|
-
// }
|
|
2876
|
-
|
|
2877
|
-
// if(command === "LISTEN"){
|
|
2878
|
-
// if(!allowListen) throw new Error(`Your query contains a LISTEN command. Set { allowListen: true } to get subscription hooks. Or ignore this message`)
|
|
2879
|
-
// if(!socket) throw "Only allowed with client socket"
|
|
2880
|
-
// return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
2881
|
-
|
|
2882
|
-
// } else if(returnType === "rows") {
|
|
2883
|
-
// return rows;
|
|
2884
|
-
|
|
2885
|
-
// } else if(returnType === "row") {
|
|
2886
|
-
// return rows[0];
|
|
2887
|
-
|
|
2888
|
-
// } else if(returnType === "value") {
|
|
2889
|
-
// return Object.values(rows?.[0] || {})?.[0];
|
|
2890
|
-
|
|
2891
|
-
// } else if(returnType === "values") {
|
|
2892
|
-
// return rows.map(r => Object.values(r[0]));
|
|
2893
|
-
|
|
2894
|
-
// } else {
|
|
2895
|
-
|
|
2896
|
-
// let qres: SQLResult<typeof returnType> = {
|
|
2897
|
-
// duration: 0,
|
|
2898
|
-
// ..._qres,
|
|
2899
|
-
// fields: fields?.map(f => {
|
|
2900
|
-
// const dataType = DATA_TYPES.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text",
|
|
2901
|
-
// tableName = USER_TABLES.find(t => +t.relid === +f.tableID),
|
|
2902
|
-
// tsDataType = postgresToTsType(dataType);
|
|
2903
|
-
|
|
2904
|
-
// return {
|
|
2905
|
-
// ...f,
|
|
2906
|
-
// tsDataType,
|
|
2907
|
-
// dataType,
|
|
2908
|
-
// udt_name: dataType,
|
|
2909
|
-
// tableName: tableName?.relname
|
|
2910
|
-
// }
|
|
2911
|
-
// }) ?? []
|
|
2912
|
-
// };
|
|
2913
|
-
// return qres;
|
|
2914
|
-
// }
|
|
2915
|
-
|
|
2916
|
-
// } else console.error("db missing");
|
|
2917
|
-
// }
|
|
2918
2729
|
} else {
|
|
2919
2730
|
console.warn(`Could not create dbo.sql handler because there is already a table named "sql"`)
|
|
2920
2731
|
}
|
package/lib/Prostgles.js
CHANGED
|
@@ -522,7 +522,7 @@ class Prostgles {
|
|
|
522
522
|
let valid_table_command_rules = await this.publishParser.getValidatedRequestRule({ tableName, command, localParams: { socket } }, clientInfo);
|
|
523
523
|
if (valid_table_command_rules) {
|
|
524
524
|
//@ts-ignore
|
|
525
|
-
let res = await this.dbo[tableName][command](param1, param2, param3, valid_table_command_rules, { socket,
|
|
525
|
+
let res = await this.dbo[tableName][command](param1, param2, param3, valid_table_command_rules, { socket, isRemoteRequest: true });
|
|
526
526
|
cb(null, res);
|
|
527
527
|
}
|
|
528
528
|
else
|
package/lib/Prostgles.ts
CHANGED
|
@@ -704,7 +704,7 @@ export class Prostgles {
|
|
|
704
704
|
let valid_table_command_rules = await this.publishParser.getValidatedRequestRule({ tableName, command, localParams: { socket } }, clientInfo);
|
|
705
705
|
if (valid_table_command_rules) {
|
|
706
706
|
//@ts-ignore
|
|
707
|
-
let res = await this.dbo[tableName][command]!(param1, param2, param3, valid_table_command_rules, { socket,
|
|
707
|
+
let res = await this.dbo[tableName][command]!(param1, param2, param3, valid_table_command_rules, { socket, isRemoteRequest: true });
|
|
708
708
|
cb(null, res);
|
|
709
709
|
} else throw `Invalid OR disallowed request: ${tableName}.${command} `;
|
|
710
710
|
|
package/lib/PublishParser.js
CHANGED
|
@@ -347,7 +347,7 @@ class PublishParser {
|
|
|
347
347
|
let err = null;
|
|
348
348
|
try {
|
|
349
349
|
let valid_table_command_rules = await this.getValidatedRequestRule({ tableName, command: method, localParams: { socket } }, clientInfo);
|
|
350
|
-
await this.dbo[tableName][method]({}, {}, {}, valid_table_command_rules, { socket,
|
|
350
|
+
await this.dbo[tableName][method]({}, {}, {}, valid_table_command_rules, { socket, isRemoteRequest: true, testRule: true });
|
|
351
351
|
}
|
|
352
352
|
catch (e) {
|
|
353
353
|
err = "INTERNAL PUBLISH ERROR";
|
|
@@ -357,7 +357,7 @@ class PublishParser {
|
|
|
357
357
|
}
|
|
358
358
|
if (method === "getInfo" || method === "getColumns") {
|
|
359
359
|
let tableRules = await this.getValidatedRequestRule({ tableName, command: method, localParams: { socket } }, clientInfo);
|
|
360
|
-
const res = await this.dbo[tableName][method](undefined, undefined, undefined, tableRules, { socket,
|
|
360
|
+
const res = await this.dbo[tableName][method](undefined, undefined, undefined, tableRules, { socket, isRemoteRequest: true });
|
|
361
361
|
if (method === "getInfo") {
|
|
362
362
|
tableInfo = res;
|
|
363
363
|
}
|
package/lib/PublishParser.ts
CHANGED
|
@@ -682,7 +682,7 @@ export class PublishParser {
|
|
|
682
682
|
let err = null;
|
|
683
683
|
try {
|
|
684
684
|
let valid_table_command_rules = await this.getValidatedRequestRule({ tableName, command: method, localParams: {socket} }, clientInfo);
|
|
685
|
-
await (this.dbo[tableName] as any)[method]({}, {}, {}, valid_table_command_rules, { socket,
|
|
685
|
+
await (this.dbo[tableName] as any)[method]({}, {}, {}, valid_table_command_rules, { socket, isRemoteRequest: true, testRule: true });
|
|
686
686
|
|
|
687
687
|
} catch(e) {
|
|
688
688
|
err = "INTERNAL PUBLISH ERROR";
|
|
@@ -695,7 +695,7 @@ export class PublishParser {
|
|
|
695
695
|
|
|
696
696
|
if(method === "getInfo" || method === "getColumns"){
|
|
697
697
|
let tableRules = await this.getValidatedRequestRule({ tableName, command: method, localParams: {socket} }, clientInfo);
|
|
698
|
-
const res = await (this.dbo[tableName] as any)[method](undefined, undefined, undefined , tableRules, { socket,
|
|
698
|
+
const res = await (this.dbo[tableName] as any)[method](undefined, undefined, undefined , tableRules, { socket, isRemoteRequest: true });
|
|
699
699
|
if(method === "getInfo"){
|
|
700
700
|
tableInfo = res;
|
|
701
701
|
} else if(method === "getColumns"){
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prostgles-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.268",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"check-disk-space": "^3.3.1",
|
|
32
32
|
"file-type": "^17.1.4",
|
|
33
33
|
"pg-promise": "^10.11.1",
|
|
34
|
-
"prostgles-types": "^1.5.
|
|
34
|
+
"prostgles-types": "^1.5.174",
|
|
35
35
|
"sharp": "^0.30.7"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
package/tests/client/PID.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
17034
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"../..": {
|
|
23
23
|
"name": "prostgles-server",
|
|
24
|
-
"version": "2.0.
|
|
24
|
+
"version": "2.0.267",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@aws-sdk/client-s3": "^3.121.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"check-disk-space": "^3.3.1",
|
|
32
32
|
"file-type": "^17.1.4",
|
|
33
33
|
"pg-promise": "^10.11.1",
|
|
34
|
-
"prostgles-types": "^1.5.
|
|
34
|
+
"prostgles-types": "^1.5.174",
|
|
35
35
|
"sharp": "^0.30.7"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
@@ -1375,7 +1375,7 @@
|
|
|
1375
1375
|
"check-disk-space": "^3.3.1",
|
|
1376
1376
|
"file-type": "^17.1.4",
|
|
1377
1377
|
"pg-promise": "^10.11.1",
|
|
1378
|
-
"prostgles-types": "^1.5.
|
|
1378
|
+
"prostgles-types": "^1.5.174",
|
|
1379
1379
|
"sharp": "^0.30.7",
|
|
1380
1380
|
"typescript": "^4.7.4"
|
|
1381
1381
|
}
|