@opengis/fastify-table 2.5.0 → 2.5.2
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/index.d.ts.map +1 -1
- package/dist/index.js +27 -0
- package/dist/server/migrations/oauth.sql.sql +77 -0
- package/dist/server/migrations/users.sql +11 -1
- package/dist/server/plugins/crud/funcs/utils/logChanges.d.ts.map +1 -1
- package/dist/server/plugins/crud/funcs/utils/logChanges.js +5 -2
- package/dist/server/plugins/grpc/utils/server/plugins/grpc/utils/convertp.proto +137 -0
- package/dist/server/plugins/grpc/utils/server/plugins/grpc/utils/office2pdf.proto +14 -0
- package/dist/server/plugins/hook/funcs/addHook.js +7 -0
- package/dist/server/plugins/hook/funcs/applyHook.js +25 -0
- package/dist/server/plugins/hook/funcs/applyHookSync.js +7 -0
- package/dist/server/plugins/hook/index.js +7 -0
- package/dist/server/plugins/migration/index.d.ts +3 -0
- package/dist/server/plugins/migration/index.d.ts.map +1 -0
- package/dist/server/plugins/migration/index.js +5 -0
- package/dist/server/plugins/policy/funcs/checkPolicy.d.ts.map +1 -1
- package/dist/server/plugins/policy/funcs/checkPolicy.js +4 -1
- package/dist/server/plugins/table/funcs/getSelectMeta.d.ts.map +1 -1
- package/dist/server/plugins/table/funcs/getSelectMeta.js +10 -5
- package/dist/server/routes/access/schema.d.ts.map +1 -1
- package/dist/server/routes/auth/controllers/2factor/generate.d.ts +19 -0
- package/dist/server/routes/auth/controllers/2factor/generate.d.ts.map +1 -0
- package/dist/server/routes/auth/controllers/2factor/generate.js +38 -0
- package/dist/server/routes/auth/controllers/2factor/toggle.d.ts +18 -0
- package/dist/server/routes/auth/controllers/2factor/toggle.d.ts.map +1 -0
- package/dist/server/routes/auth/controllers/2factor/toggle.js +39 -0
- package/dist/server/routes/file/controllers/export.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/export.js +5 -3
- package/dist/server/routes/file/controllers/resizeAll.d.ts.map +1 -1
- package/dist/server/routes/file/controllers/resizeAll.js +4 -3
- package/dist/server/routes/file/index.d.ts.map +1 -1
- package/dist/server/routes/file/index.js +20 -5
- package/dist/server/routes/file/schema.d.ts +27 -4
- package/dist/server/routes/file/schema.d.ts.map +1 -1
- package/dist/server/routes/file/schema.js +23 -9
- package/dist/server/routes/logger/controllers/utils/checkUserAccess.js +22 -0
- package/dist/server/routes/logger/controllers/utils/getRootDir.js +25 -0
- package/dist/server/routes/table/controllers/search.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/search.js +19 -11
- package/dist/server/routes/table/controllers/suggest.js +1 -1
- package/dist/server/routes/table/functions/getData.d.ts +1 -1
- package/dist/server/routes/table/functions/getData.d.ts.map +1 -1
- package/dist/server/routes/table/functions/getData.js +80 -46
- package/dist/server/routes/table/index.js +2 -1
- package/dist/server/routes/table/schema.d.ts +6 -10
- package/dist/server/routes/table/schema.d.ts.map +1 -1
- package/dist/server/routes/table/schema.js +50 -50
- package/dist/server/routes/templates/index.d.ts.map +1 -1
- package/dist/server/routes/templates/index.js +7 -1
- package/dist/server/routes/templates/schema.d.ts +3 -3
- package/dist/server/routes/templates/schema.d.ts.map +1 -1
- package/dist/server/routes/templates/schema.js +4 -4
- package/dist/server/types/errors.d.ts +10 -0
- package/dist/server/types/errors.d.ts.map +1 -0
- package/dist/server/types/errors.js +3 -0
- package/package.json +98 -98
|
@@ -7,7 +7,7 @@ import download from "./controllers/download.js";
|
|
|
7
7
|
import exportTable from "./controllers/export.js";
|
|
8
8
|
import uploadImage from "./controllers/uploadImage.js";
|
|
9
9
|
import deleteFileAPI from "./controllers/delete.js";
|
|
10
|
-
import { resizeSchema } from "./schema.js";
|
|
10
|
+
import { resizeSchema, exportSchema } from "./schema.js";
|
|
11
11
|
const tags = ["core", "file"];
|
|
12
12
|
const { uploadPolicy = "L1" } = config;
|
|
13
13
|
const publicParams = { config: { tags, policy: "L0" } };
|
|
@@ -15,7 +15,9 @@ const privateParams = { config: { tags, policy: uploadPolicy } };
|
|
|
15
15
|
function plugin(app, opt = {}) {
|
|
16
16
|
app.get("/files/*", publicParams, files);
|
|
17
17
|
if (!app.hasRoute({ method: "GET", url: "/file/resize" })) {
|
|
18
|
-
app.
|
|
18
|
+
app.route({
|
|
19
|
+
method: "GET",
|
|
20
|
+
url: "/file/resize",
|
|
19
21
|
config: {
|
|
20
22
|
...publicParams,
|
|
21
23
|
rateLimit: config.rateLimit
|
|
@@ -26,13 +28,26 @@ function plugin(app, opt = {}) {
|
|
|
26
28
|
: undefined,
|
|
27
29
|
},
|
|
28
30
|
schema: resizeSchema,
|
|
29
|
-
|
|
31
|
+
handler: resize,
|
|
32
|
+
});
|
|
30
33
|
}
|
|
31
|
-
app.
|
|
34
|
+
app.route({
|
|
35
|
+
method: "GET",
|
|
36
|
+
url: "/api/resize-all",
|
|
37
|
+
config: { tags, role: "admin" },
|
|
38
|
+
schema: resizeSchema,
|
|
39
|
+
handler: resizeAll,
|
|
40
|
+
});
|
|
32
41
|
app.post("/file/upload/*", privateParams, upload);
|
|
33
42
|
app.post("/file/upload-image/*", privateParams, uploadImage);
|
|
34
43
|
app.get("/file/download/*", publicParams, download);
|
|
35
44
|
app.get("/file/delete/*", publicParams, deleteFileAPI);
|
|
36
|
-
app.
|
|
45
|
+
app.route({
|
|
46
|
+
method: "GET",
|
|
47
|
+
url: "/api/export",
|
|
48
|
+
...publicParams,
|
|
49
|
+
schema: exportSchema,
|
|
50
|
+
handler: exportTable,
|
|
51
|
+
});
|
|
37
52
|
}
|
|
38
53
|
export default plugin;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
declare const resizeSchema: {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
querystring: {
|
|
3
|
+
type: string;
|
|
4
|
+
properties: {
|
|
5
5
|
filepath: {
|
|
6
6
|
type: string;
|
|
7
7
|
};
|
|
@@ -27,7 +27,30 @@ declare const resizeSchema: {
|
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
|
+
declare const exportSchema: {
|
|
31
|
+
querystring: {
|
|
32
|
+
type: string;
|
|
33
|
+
properties: {
|
|
34
|
+
limit: {
|
|
35
|
+
type: string;
|
|
36
|
+
minimum: number;
|
|
37
|
+
};
|
|
38
|
+
batchLimit: {
|
|
39
|
+
type: string;
|
|
40
|
+
minimum: number;
|
|
41
|
+
};
|
|
42
|
+
page: {
|
|
43
|
+
type: string;
|
|
44
|
+
minimum: number;
|
|
45
|
+
};
|
|
46
|
+
key: {
|
|
47
|
+
type: string;
|
|
48
|
+
pattern: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
};
|
|
30
53
|
declare const _default: null;
|
|
31
54
|
export default _default;
|
|
32
|
-
export { resizeSchema };
|
|
55
|
+
export { resizeSchema, exportSchema };
|
|
33
56
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/file/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/file/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcjB,CAAC;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;CAUjB,CAAC;;AAEF,wBAAoB;AAEpB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
const resizeSchema = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
filepath: { type:
|
|
6
|
-
quality: { type:
|
|
7
|
-
size: {
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
querystring: {
|
|
3
|
+
type: "object",
|
|
4
|
+
properties: {
|
|
5
|
+
filepath: { type: "string" },
|
|
6
|
+
quality: { type: "number", exclusiveMinimum: 0, maximum: 100 },
|
|
7
|
+
size: {
|
|
8
|
+
type: "string",
|
|
9
|
+
pattern: "^((\\d{1,4})x(\\d{1,4})|(\\d{1,4})x|x(\\d{1,4}))$",
|
|
10
|
+
},
|
|
11
|
+
w: { type: "number", minimum: 1, maximum: 2048 },
|
|
12
|
+
h: { type: "number", minimum: 1, maximum: 2048 },
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const exportSchema = {
|
|
17
|
+
querystring: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
limit: { type: "number", minimum: 1 },
|
|
21
|
+
batchLimit: { type: "number", minimum: 1 },
|
|
22
|
+
page: { type: "number", minimum: 1 },
|
|
23
|
+
key: { type: "string", pattern: "^([\\d\\w_.-]+)$" },
|
|
10
24
|
},
|
|
11
25
|
},
|
|
12
26
|
};
|
|
13
27
|
export default null;
|
|
14
|
-
export { resizeSchema };
|
|
28
|
+
export { resizeSchema, exportSchema };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import config from "../../../../../config.js";
|
|
2
|
+
const { accessToken = "0NWcGQxKRP8AsRxD" } = config.auth || {};
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @summary check user access to logger interface - per admin user type or user group
|
|
6
|
+
* @returns {Object} message, status
|
|
7
|
+
*/
|
|
8
|
+
export default function checkUserAccess({ user = {}, token, }) {
|
|
9
|
+
if (token && token === accessToken) {
|
|
10
|
+
return { message: "access granted", status: 200 };
|
|
11
|
+
}
|
|
12
|
+
// console.log(user);
|
|
13
|
+
if (!user.user_type?.includes?.("admin") &&
|
|
14
|
+
!config?.local &&
|
|
15
|
+
!config.auth?.disable) {
|
|
16
|
+
return { message: "access restricted", status: 403 };
|
|
17
|
+
}
|
|
18
|
+
/* if (!['admin', 'superadmin']?.includes(user.user_type) && count === '0') {
|
|
19
|
+
return { message: 'access restricted', status: 403 };
|
|
20
|
+
} */
|
|
21
|
+
return { message: "access granted", status: 200 };
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import config from "../../../../../config.js";
|
|
5
|
+
// import { existsSync } from 'fs';
|
|
6
|
+
let logDir = null;
|
|
7
|
+
export default function getRootDir() {
|
|
8
|
+
// absolute / relative path
|
|
9
|
+
if (logDir)
|
|
10
|
+
return logDir;
|
|
11
|
+
const file = ["config.json", "/data/local/config.json"].find((el) => fs.existsSync(el) ? el : null);
|
|
12
|
+
const root = file === "config.json" ? process.cwd() : "/data/local";
|
|
13
|
+
logDir = config.logDir || path.join(root, config.log?.dir || "log");
|
|
14
|
+
console.log({ logDir });
|
|
15
|
+
return logDir;
|
|
16
|
+
// windows debug support
|
|
17
|
+
/* const customLogDir = process.cwd().includes(':') ? 'c:/data/local' : '/data/local';
|
|
18
|
+
// docker default path
|
|
19
|
+
if (existsSync(customLogDir)) {
|
|
20
|
+
return path.join(customLogDir, config.folder || '', 'log');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// non-docker default path
|
|
24
|
+
return path.join(config.root || '/data/local', config.folder || '', 'log'); */
|
|
25
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/search.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/search.ts"],"names":[],"mappings":"AAkJA,wBAA8B,MAAM,CAAC,EACnC,EAAqB,EACrB,KAAU,GACX,EAAE,GAAG;;;;;;GAmCL"}
|
|
@@ -11,7 +11,7 @@ async function getData({ pg = pgClients.client, tableName, query = {}, maxLimit,
|
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
13
13
|
const { table, columns, meta } = loadTable;
|
|
14
|
-
const { pk, view } = await getMeta({ pg, table });
|
|
14
|
+
const { pk, view } = (await getMeta({ pg, table }).catch((err) => null)) || {};
|
|
15
15
|
if (!pk && !view) {
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
@@ -20,14 +20,19 @@ async function getData({ pg = pgClients.client, tableName, query = {}, maxLimit,
|
|
|
20
20
|
const order = cols.includes(orderColumn) && orderColumn?.length
|
|
21
21
|
? `order by ${orderColumn} ${query.desc || orderDir === "desc" ? "desc" : ""}`
|
|
22
22
|
: "";
|
|
23
|
+
const args = [];
|
|
23
24
|
const limit = Math.max(maxLimit - res.rows.length, 0);
|
|
24
|
-
|
|
25
|
-
const offset = query.page && query.page > 0 ?
|
|
25
|
+
args.push(limit);
|
|
26
|
+
const offset = query.page && query.page > 0 ? (query.page - 1) * limit : 0;
|
|
27
|
+
args.push(offset);
|
|
28
|
+
if (meta?.search && query.key) {
|
|
29
|
+
args.push(`%${query.key}%`);
|
|
30
|
+
}
|
|
26
31
|
const search1 = meta?.search && query.key
|
|
27
32
|
? `(${meta?.search
|
|
28
33
|
.concat(meta?.title ? `,${meta?.title}` : "")
|
|
29
34
|
.split(",")
|
|
30
|
-
.map((el) => `${el}::text ilike
|
|
35
|
+
.map((el) => `${el}::text ilike $3`)
|
|
31
36
|
.join(" or ")})`
|
|
32
37
|
: "false";
|
|
33
38
|
const where = [!pk ? "false" : "true", loadTable.query, search1].filter(Boolean);
|
|
@@ -40,23 +45,26 @@ async function getData({ pg = pgClients.client, tableName, query = {}, maxLimit,
|
|
|
40
45
|
meta?.title ? `${meta.title} as title` : "",
|
|
41
46
|
]
|
|
42
47
|
.filter((el) => el)
|
|
43
|
-
.join(",")} from ${table} t ${sqlTable} where ${where.join(" and ") || "true"} ${order} $
|
|
48
|
+
.join(",")} from ${table} t ${sqlTable} where ${where.join(" and ") || "true"} ${order} limit $1 offset $2`;
|
|
44
49
|
if (query.sql) {
|
|
45
50
|
res.sql.push(q);
|
|
46
51
|
return null;
|
|
47
52
|
}
|
|
48
|
-
const rows = await pg.query(q).then((
|
|
53
|
+
const rows = await pg.query(q, args).then((r) => r.rows || []);
|
|
49
54
|
const filtered = pg.queryCache
|
|
50
55
|
? await pg
|
|
51
|
-
.queryCache(`select count(*) from ${table} t ${sqlTable} where ${where.join(" and ") || "true"}
|
|
52
|
-
|
|
56
|
+
.queryCache(`select count(*) from ${table} t ${sqlTable} where ${where.join(" and ").replace(/\$3/g, "$1") || "true"}`, {
|
|
57
|
+
args: [meta?.search && query.key ? query.key : undefined].filter(Boolean),
|
|
58
|
+
table,
|
|
59
|
+
})
|
|
60
|
+
.then((r) => +(r?.rows[0]?.count || 0))
|
|
53
61
|
: 0;
|
|
54
62
|
const total = pg.queryCache
|
|
55
63
|
? await pg
|
|
56
64
|
.queryCache(`select count(*) from ${table}`)
|
|
57
|
-
.then((
|
|
65
|
+
.then((r) => +(r?.rows[0]?.count || 0))
|
|
58
66
|
: 0;
|
|
59
|
-
await metaFormat({ rows, table: tableName });
|
|
67
|
+
await metaFormat({ rows, table: tableName }, pg);
|
|
60
68
|
res.total += +total;
|
|
61
69
|
res.filtered += +filtered;
|
|
62
70
|
rows.forEach((row) => {
|
|
@@ -83,7 +91,7 @@ export default async function search({ pg = pgClients.client, query = {}, }) {
|
|
|
83
91
|
total: 0,
|
|
84
92
|
filtered: 0,
|
|
85
93
|
};
|
|
86
|
-
const maxLimit = Math.min(100, query.limit ||
|
|
94
|
+
const maxLimit = Math.min(100, +query.limit || 16);
|
|
87
95
|
await sequence(tables, {
|
|
88
96
|
pg,
|
|
89
97
|
query,
|
|
@@ -68,7 +68,7 @@ export async function getTableColumnMeta({ table, template, column, selectName,
|
|
|
68
68
|
export default async function suggest(req) {
|
|
69
69
|
const time = Date.now();
|
|
70
70
|
const { params, user, query = {}, pg: pg1 = pgClients.client } = req;
|
|
71
|
-
const { lang = "ua", parent
|
|
71
|
+
const { lang = "ua", parent } = query;
|
|
72
72
|
const debugMode = config.local ||
|
|
73
73
|
user?.user_type?.includes?.("admin") ||
|
|
74
74
|
process.env.NODE_ENV === "test" ||
|
|
@@ -20,5 +20,5 @@ export default function dataAPI({ pg, params, table, id, headers, query, user, c
|
|
|
20
20
|
accessQuery?: string;
|
|
21
21
|
columns?: string[];
|
|
22
22
|
isExport?: boolean;
|
|
23
|
-
},
|
|
23
|
+
}, reply?: FastifyReply, called?: any): Promise<any>;
|
|
24
24
|
//# sourceMappingURL=getData.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwFzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,YAAY,EACrB,QAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,
|
|
1
|
+
{"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwFzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,YAAY,EACrB,QAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,KAAK,CAAC,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,GAAG,gBA64Bb"}
|
|
@@ -54,13 +54,11 @@ function getOrder(queryOrder, queryDesc, defaultOrder, columnList, sqlColumns, i
|
|
|
54
54
|
const checkInline = {};
|
|
55
55
|
const maxLimit = 100;
|
|
56
56
|
const defaultLimit = 20;
|
|
57
|
-
export default async function dataAPI({ pg = pgClients.client, params, table, id, headers = {}, query = {}, user = {}, contextQuery, searchColumn, sufix = true, filterList, actions: actionsParam, accessQuery: accessQueryParam, columns: columnsParam, isExport = false, },
|
|
57
|
+
export default async function dataAPI({ pg = pgClients.client, params, table, id, headers = {}, query = {}, user = {}, contextQuery, searchColumn, sufix = true, filterList, actions: actionsParam, accessQuery: accessQueryParam, columns: columnsParam, isExport = false, }, reply, called) {
|
|
58
58
|
const time = Date.now();
|
|
59
59
|
const timeArr = [Date.now()];
|
|
60
60
|
const { uid } = user;
|
|
61
|
-
const reply = reply1 || mockReply;
|
|
62
61
|
const method = "GET";
|
|
63
|
-
const checkQuery = (item) => user?.user_type === "superadmin" ? !item.includes("{{uid}}") : true;
|
|
64
62
|
const paramsTable = params?.table || table;
|
|
65
63
|
if (!paramsTable) {
|
|
66
64
|
throw BadRequestError("not enough params: table");
|
|
@@ -210,14 +208,14 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
210
208
|
!el.inline &&
|
|
211
209
|
el?.sql?.replace &&
|
|
212
210
|
!(isExport && el.export === false))
|
|
213
|
-
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", uid)}) ${el.name || `t${i}`} on 1=1 `)
|
|
211
|
+
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", `$${idx.uid}`)}) ${el.name || `t${i}`} on 1=1 `)
|
|
214
212
|
?.join("") || "";
|
|
215
213
|
const cardSqlFiltered = objectId
|
|
216
214
|
? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) || []
|
|
217
215
|
: [];
|
|
218
216
|
const cardSqlTable = cardSqlFiltered.length
|
|
219
217
|
? cardSqlFiltered
|
|
220
|
-
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", uid)}) ct${i} on 1=1 `)
|
|
218
|
+
.map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", `$${idx.uid}`)}) ct${i} on 1=1 `)
|
|
221
219
|
.join("\n") || ""
|
|
222
220
|
: "";
|
|
223
221
|
const sqlInline = loadTable?.sql
|
|
@@ -277,21 +275,40 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
277
275
|
const keyQuery = query?.key && (loadTable?.key || tokenData?.key) && !objectId
|
|
278
276
|
? `${loadTable?.key || tokenData?.key}=$1`
|
|
279
277
|
: null;
|
|
278
|
+
const idx = {};
|
|
279
|
+
const args = (objectId ? [objectId] : null) ||
|
|
280
|
+
(query?.key && loadTable.key ? [query.key] : []);
|
|
281
|
+
if (args[0]) {
|
|
282
|
+
Object.assign(idx, { id: 1 });
|
|
283
|
+
}
|
|
284
|
+
const isSingle = !!idx.id;
|
|
280
285
|
const limit = (called
|
|
281
286
|
? query?.limit || defaultLimit
|
|
282
287
|
: Math.min(maxLimit, +(query?.limit || defaultLimit))) || defaultLimit;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
288
|
+
args.push(limit);
|
|
289
|
+
Object.assign(idx, { limit: idx.id ? 2 : 1 });
|
|
290
|
+
const offset = query?.page && query?.page > 0 && !objectId ? (query?.page - 1) * limit : 0;
|
|
291
|
+
args.push(offset);
|
|
292
|
+
Object.assign(idx, { offset: idx.id ? 3 : 2 });
|
|
286
293
|
const order = getOrder(query?.order, query?.desc, loadTable?.order, columnList, loadTable?.sqlColumns, !!called);
|
|
294
|
+
const isSearchable = Array.isArray(loadTable?.meta?.search) &&
|
|
295
|
+
loadTable.meta.search.length &&
|
|
296
|
+
query?.search &&
|
|
297
|
+
!isSingle;
|
|
298
|
+
if (isSearchable) {
|
|
299
|
+
args.push(`%${query.search.replace(/%/g, "\\%")}%`);
|
|
300
|
+
Object.assign(idx, { search: Object.keys(idx).length + 1 });
|
|
301
|
+
}
|
|
302
|
+
if (meta?.bbox && query?.polyline) {
|
|
303
|
+
args.push(query.polyline);
|
|
304
|
+
Object.assign(idx, { polyline: Object.keys(idx).length + 1 });
|
|
305
|
+
}
|
|
287
306
|
if (config.trace)
|
|
288
307
|
console.log(order);
|
|
289
|
-
const search =
|
|
308
|
+
const search = isSearchable
|
|
290
309
|
? `(${loadTable?.meta?.search
|
|
291
310
|
?.split(",")
|
|
292
|
-
?.map((el) => `${el} ilike
|
|
293
|
-
.replace(/%/g, "\\%")
|
|
294
|
-
.replace(/'/g, "''")}%'`)
|
|
311
|
+
?.map((el) => `${el} ilike $${idx.search}`)
|
|
295
312
|
.join(" or ")})`
|
|
296
313
|
: null;
|
|
297
314
|
const queryBbox = query?.bbox
|
|
@@ -301,7 +318,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
301
318
|
?.map((el) => el - 0)
|
|
302
319
|
: [];
|
|
303
320
|
const queryPolyline = meta?.bbox && query?.polyline
|
|
304
|
-
? `ST_Contains(ST_MakePolygon(ST_LineFromEncodedPolyline(
|
|
321
|
+
? `ST_Contains(ST_MakePolygon(ST_LineFromEncodedPolyline($${idx.polyline})),${meta.bbox})`
|
|
305
322
|
: undefined;
|
|
306
323
|
const bbox = meta?.bbox && queryBbox.filter((el) => !Number.isNaN(el))?.length === 4
|
|
307
324
|
? `${meta.bbox} && 'box(${queryBbox[0]} ${queryBbox[1]},${queryBbox[2]} ${queryBbox[3]})'::box2d `
|
|
@@ -318,7 +335,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
318
335
|
? await handlebars.compile(params?.query)({ user, uid })
|
|
319
336
|
: undefined;
|
|
320
337
|
const where = [
|
|
321
|
-
objectId ? ` "${pk}" =
|
|
338
|
+
objectId ? ` "${pk}" = $${idx.id}` : null,
|
|
322
339
|
keyQuery,
|
|
323
340
|
loadTable?.query,
|
|
324
341
|
tokenData?.query,
|
|
@@ -330,40 +347,36 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
330
347
|
queryPolyline,
|
|
331
348
|
interfaceQuery,
|
|
332
349
|
interfaceQuery1,
|
|
333
|
-
]
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
: columnsParam || sqlColumns || cols || "*"}
|
|
340
|
-
${metaCols}
|
|
341
|
-
${dbColumns.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry").length && !columnsParam
|
|
350
|
+
].filter(Boolean);
|
|
351
|
+
const q1 = `select ${pk ? `"${pk}" as id,` : ""}
|
|
352
|
+
${objectId || query?.key ? "*" : columnsParam || sqlColumns || cols || "*"}
|
|
353
|
+
${metaCols}
|
|
354
|
+
${dbColumns.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry")
|
|
355
|
+
.length && !columnsParam
|
|
342
356
|
? `,${dbColumns
|
|
343
357
|
.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry")
|
|
344
358
|
.map((el) => `st_asgeojson("${el.name.replace(/'/g, "''")}")::json as "${el.name.replace(/'/g, "''")}"`)
|
|
345
359
|
.join(",")}`
|
|
346
360
|
: ""}
|
|
347
|
-
|
|
361
|
+
from (select * ${sql
|
|
348
362
|
?.filter((el) => el.inline && !(isExport && el.export === false))
|
|
349
363
|
.map((el) => `,(${el.sql})`)
|
|
350
364
|
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable} ) t
|
|
351
365
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
366
|
+
${objectId ? cardSqlTable : ""}
|
|
367
|
+
where ${where.join(" and ") || "true"}
|
|
368
|
+
${order} limit $${idx.limit} offset $${idx.offset}`;
|
|
369
|
+
if (q1.includes("{{uid}}")) {
|
|
370
|
+
args.push(uid || "");
|
|
371
|
+
Object.assign(idx, { uid: Object.keys(idx).length + 1 });
|
|
372
|
+
}
|
|
373
|
+
const q = q1.replace(/{{uid}}/g, `$${idx.uid}`);
|
|
355
374
|
if (config.trace)
|
|
356
375
|
console.log(q);
|
|
357
376
|
if (query?.sql === "1") {
|
|
358
377
|
return q;
|
|
359
378
|
}
|
|
360
|
-
const
|
|
361
|
-
.query(q, (objectId ? [objectId] : null) ||
|
|
362
|
-
(query?.key && loadTable.key ? [query?.key] : []))
|
|
363
|
-
.catch((err) => {
|
|
364
|
-
console.error(err.toString());
|
|
365
|
-
throw err;
|
|
366
|
-
});
|
|
379
|
+
const rows = await pg.query(q, args).then((r) => r.rows || []);
|
|
367
380
|
if (!rows.length &&
|
|
368
381
|
headers?.referer?.includes?.("/card/") &&
|
|
369
382
|
headers?.referer?.includes?.(templateName)) {
|
|
@@ -395,17 +408,38 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
395
408
|
});
|
|
396
409
|
});
|
|
397
410
|
}
|
|
411
|
+
const idx1 = {};
|
|
412
|
+
const args1 = [];
|
|
413
|
+
if (idx.search) {
|
|
414
|
+
args1.push(args[idx.search - 1]);
|
|
415
|
+
Object.assign(idx1, { search: Object.keys(idx1).length + 1 });
|
|
416
|
+
}
|
|
417
|
+
if (idx.uid) {
|
|
418
|
+
args1.push(args[idx.uid - 1]);
|
|
419
|
+
Object.assign(idx1, { uid: Object.keys(idx1).length + 1 });
|
|
420
|
+
}
|
|
421
|
+
if (idx.polyline) {
|
|
422
|
+
args1.push(args[idx.polyline - 1]);
|
|
423
|
+
Object.assign(idx1, { polyline: Object.keys(idx1).length + 1 });
|
|
424
|
+
}
|
|
425
|
+
const search1 = idx.search
|
|
426
|
+
? `(${loadTable.meta.search
|
|
427
|
+
.split(",")
|
|
428
|
+
.map((el) => `${el} ilike $${idx1.search}`)
|
|
429
|
+
.join(" or ")})`
|
|
430
|
+
: null;
|
|
431
|
+
const queryPolyline1 = idx.polyline
|
|
432
|
+
? `ST_Contains(ST_MakePolygon(ST_LineFromEncodedPolyline($${idx1.polyline})),${meta.bbox})`
|
|
433
|
+
: undefined;
|
|
398
434
|
const filterWhere = [
|
|
399
435
|
fData.q,
|
|
400
|
-
|
|
436
|
+
search1,
|
|
401
437
|
bbox,
|
|
402
|
-
|
|
438
|
+
queryPolyline1,
|
|
403
439
|
interfaceQuery,
|
|
404
440
|
loadTable?.query,
|
|
405
441
|
tokenData?.query,
|
|
406
|
-
]
|
|
407
|
-
.filter(Boolean)
|
|
408
|
-
.filter((el) => checkQuery(el));
|
|
442
|
+
].filter(Boolean);
|
|
409
443
|
const aggColumns = columns
|
|
410
444
|
.filter((el) => el.agg)
|
|
411
445
|
.reduce((acc, curr) => Object.assign(acc, { [curr.name]: curr.agg }), {});
|
|
@@ -416,21 +450,20 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
416
450
|
}))
|
|
417
451
|
.filter((el) => ["numeric", "double precision"].includes(el.type) && aggColumns[el.name]);
|
|
418
452
|
const qCount = `select
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
453
|
+
count(*)::int as total,
|
|
454
|
+
count(*) FILTER(WHERE ${filterWhere.join(" and ") || "true"})::int as filtered
|
|
455
|
+
${aggregates.length
|
|
422
456
|
? `,${aggregates
|
|
423
457
|
.map((el) => `${aggColumns[el.name]}(${el.name}) FILTER(WHERE ${filterWhere.join(" and ") || "true"}) as ${el.name}`)
|
|
424
458
|
.join(",")}`
|
|
425
459
|
: ""}
|
|
426
|
-
|
|
460
|
+
from (select * ${sql
|
|
427
461
|
?.filter((el) => el.inline)
|
|
428
462
|
.map((el) => `,(${el.sql})`)
|
|
429
463
|
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable})t
|
|
430
|
-
|
|
464
|
+
where ${[loadTable?.query, tokenData?.query, accessQuery, contextQuery]
|
|
431
465
|
.filter(Boolean)
|
|
432
|
-
.
|
|
433
|
-
.join(" and ") || "true"} `.replace(/{{uid}}/g, uid);
|
|
466
|
+
.join(" and ") || "true"} `.replace(/{{uid}}/g, `$${idx1.uid}`);
|
|
434
467
|
if (query?.sql === "2") {
|
|
435
468
|
return qCount;
|
|
436
469
|
}
|
|
@@ -438,6 +471,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
|
|
|
438
471
|
? { total: rows.length, filtered: rows.length }
|
|
439
472
|
: await pg
|
|
440
473
|
.queryCache?.(qCount, {
|
|
474
|
+
args: args1,
|
|
441
475
|
table: loadTable?.table || tokenData?.table,
|
|
442
476
|
time: 5,
|
|
443
477
|
})
|
|
@@ -32,7 +32,8 @@ function plugin(app, opt = {}) {
|
|
|
32
32
|
},
|
|
33
33
|
schema: suggestSchema,
|
|
34
34
|
}, suggest);
|
|
35
|
-
app.get("/data/:table/:id?", { config: { tags, policy }, schema: tableSchema },
|
|
35
|
+
app.get("/data/:table/:id?", { config: { tags, policy, allowSql: true }, schema: tableSchema }, // query.polyline support w/ allowSql
|
|
36
|
+
data);
|
|
36
37
|
app.get("/table-data/:table", { config: { tags, auth: "creds", policy: "L2" }, schema: tableDataSchema }, data);
|
|
37
38
|
app.get("/table-data/:table/:id", { config: { tags, policy }, schema: tableDataIdSchema }, cardData);
|
|
38
39
|
app.get("/data-info/:id?", { config: { tags, policy }, schema: tableSchema }, dataInfo);
|
|
@@ -4,11 +4,11 @@ declare const tableDataSchema: {
|
|
|
4
4
|
querystring: {
|
|
5
5
|
limit: {
|
|
6
6
|
type: string;
|
|
7
|
-
|
|
7
|
+
minimum: number;
|
|
8
8
|
};
|
|
9
9
|
page: {
|
|
10
10
|
type: string;
|
|
11
|
-
|
|
11
|
+
minimum: number;
|
|
12
12
|
};
|
|
13
13
|
order: {
|
|
14
14
|
type: string;
|
|
@@ -36,7 +36,6 @@ declare const tableDataSchema: {
|
|
|
36
36
|
};
|
|
37
37
|
sql: {
|
|
38
38
|
type: string;
|
|
39
|
-
pattern: string;
|
|
40
39
|
};
|
|
41
40
|
};
|
|
42
41
|
params: {
|
|
@@ -57,11 +56,11 @@ declare const tableSchema: {
|
|
|
57
56
|
querystring: {
|
|
58
57
|
limit: {
|
|
59
58
|
type: string;
|
|
60
|
-
|
|
59
|
+
minimum: number;
|
|
61
60
|
};
|
|
62
61
|
page: {
|
|
63
62
|
type: string;
|
|
64
|
-
|
|
63
|
+
minimum: number;
|
|
65
64
|
};
|
|
66
65
|
order: {
|
|
67
66
|
type: string;
|
|
@@ -85,7 +84,6 @@ declare const tableSchema: {
|
|
|
85
84
|
};
|
|
86
85
|
sql: {
|
|
87
86
|
type: string;
|
|
88
|
-
pattern: string;
|
|
89
87
|
};
|
|
90
88
|
};
|
|
91
89
|
params: {
|
|
@@ -106,11 +104,11 @@ declare const searchSchema: {
|
|
|
106
104
|
querystring: {
|
|
107
105
|
page: {
|
|
108
106
|
type: string;
|
|
109
|
-
|
|
107
|
+
minimum: number;
|
|
110
108
|
};
|
|
111
109
|
limit: {
|
|
112
110
|
type: string;
|
|
113
|
-
|
|
111
|
+
minimum: number;
|
|
114
112
|
};
|
|
115
113
|
order: {
|
|
116
114
|
type: string;
|
|
@@ -161,11 +159,9 @@ declare const suggestSchema: {
|
|
|
161
159
|
};
|
|
162
160
|
sql: {
|
|
163
161
|
type: string;
|
|
164
|
-
pattern: string;
|
|
165
162
|
};
|
|
166
163
|
count: {
|
|
167
164
|
type: string;
|
|
168
|
-
pattern: string;
|
|
169
165
|
};
|
|
170
166
|
};
|
|
171
167
|
params: {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/table/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../server/routes/table/schema.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsBpB,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBhB,CAAC;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAajB,CAAC;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBlB,CAAC;AAEF,QAAA,MAAM,UAAU;;;;;;;;;;;;;;CAQf,CAAC;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;CAOjB,CAAC;AAEF,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;CAUtB,CAAC;AAEF,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;CAQtB,CAAC;AAEF,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,UAAU,EACV,YAAY,EACZ,iBAAiB,GAClB,CAAC"}
|