@opengis/fastify-table 2.6.2 → 2.6.3
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/README.md +86 -86
- package/dist/functions.js +20 -20
- package/dist/module/core/cls/constraint_action.json +9 -9
- package/dist/module/core/cls/constraint_matchtype.json +5 -5
- package/dist/module/core/cls/constraint_type_full.json +17 -17
- package/dist/module/core/cls/core.user_type.json +13 -13
- package/dist/module/core/pt/schemaItem.pt.hbs +17 -17
- package/dist/module/core/select/core.user_mentioned.sql +1 -1
- package/dist/script/adduser +14 -14
- package/dist/script/dump.js +48 -48
- package/dist/script/dump.ts +216 -216
- package/dist/script/migrate.ts +23 -23
- package/dist/server/helpers/core/badge.js +1 -1
- package/dist/server/helpers/list/descriptionList.js +8 -8
- package/dist/server/helpers/list/tableList.js +4 -4
- package/dist/server/helpers/list/utils/button.js +1 -1
- package/dist/server/helpers/list/utils/buttonDel.js +3 -3
- package/dist/server/helpers/list/utils/buttonEdit.js +3 -3
- package/dist/server/helpers/utils/button.js +1 -1
- package/dist/server/helpers/utils/buttonAdd.js +15 -15
- package/dist/server/helpers/utils/buttonDel.js +11 -11
- package/dist/server/helpers/utils/buttonEdit.js +3 -3
- package/dist/server/migrations/0.sql +99 -99
- package/dist/server/migrations/1_users.sql +145 -145
- package/dist/server/migrations/cls.sql +105 -105
- package/dist/server/migrations/context.sql +136 -136
- package/dist/server/migrations/dictionaries.sql +78 -78
- package/dist/server/migrations/oauth.sql +79 -79
- package/dist/server/migrations/properties.sql +115 -115
- package/dist/server/migrations/roles.sql +201 -201
- package/dist/server/migrations/template.sql +43 -43
- package/dist/server/plugins/access/funcs/getUserPermissions.js +7 -7
- package/dist/server/plugins/auth/funcs/authorizeUser.js +4 -4
- package/dist/server/plugins/auth/funcs/getQuery.js +20 -20
- package/dist/server/plugins/auth/index.js +3 -3
- package/dist/server/plugins/crud/funcs/dataUpdate.js +7 -7
- package/dist/server/plugins/crud/funcs/getAccess.js +14 -14
- package/dist/server/plugins/crud/funcs/utils/getInsertQuery.js +6 -6
- package/dist/server/plugins/crud/funcs/utils/logChanges.js +18 -18
- package/dist/server/plugins/grpc/utils/convertp.proto +143 -143
- package/dist/server/plugins/grpc/utils/htmlTemplate.js +10 -10
- package/dist/server/plugins/grpc/utils/office2pdf.proto +13 -13
- package/dist/server/plugins/metric/loggerSystem.js +1 -1
- package/dist/server/plugins/pg/funcs/autoIndex.js +5 -5
- package/dist/server/plugins/pg/funcs/getMeta.js +15 -15
- package/dist/server/plugins/pg/funcs/init.js +36 -36
- package/dist/server/plugins/sqlite/funcs/init.js +22 -22
- package/dist/server/plugins/table/funcs/getData.js +13 -13
- package/dist/server/plugins/table/funcs/getFilterSQL/util/getCustomQuery.js +1 -1
- package/dist/server/plugins/table/funcs/getSelect.js +1 -1
- package/dist/server/plugins/table/funcs/gisIRColumn.js +3 -3
- package/dist/server/plugins/usercls/index.js +2 -2
- package/dist/server/routes/access/controllers/access.group.js +6 -6
- package/dist/server/routes/access/controllers/access.group.post.js +3 -3
- package/dist/server/routes/access/controllers/access.interface.js +14 -14
- package/dist/server/routes/access/controllers/access.user.js +6 -6
- package/dist/server/routes/auth/controllers/2factor/providers/totp.js +5 -5
- package/dist/server/routes/auth/controllers/2factor/qrcode.js +1 -1
- package/dist/server/routes/auth/controllers/2factor/recovery.js +1 -1
- package/dist/server/routes/auth/controllers/2factor/verify.js +1 -1
- package/dist/server/routes/auth/controllers/core/getUserInfo.js +33 -33
- package/dist/server/routes/auth/controllers/core/passwordRecovery.js +1 -1
- package/dist/server/routes/auth/controllers/core/registration.js +2 -2
- package/dist/server/routes/auth/controllers/page/login2faTemplate.js +1 -1
- package/dist/server/routes/crud/functions/deleteTableRelation.js +9 -9
- package/dist/server/routes/crud/functions/updateTableRelation.js +9 -9
- package/dist/server/routes/file/controllers/resizeAll.js +7 -7
- package/dist/server/routes/grpc/controllers/file2geojson.js +13 -13
- package/dist/server/routes/menu/controllers/getMenu.js +9 -9
- package/dist/server/routes/notifications/controllers/readNotifications.js +4 -4
- package/dist/server/routes/notifications/controllers/userNotifications.js +3 -3
- package/dist/server/routes/table/controllers/card.js +1 -1
- package/dist/server/routes/table/controllers/filter.js +6 -6
- package/dist/server/routes/table/controllers/form.js +1 -1
- package/dist/server/routes/table/controllers/getFormByTable.js +6 -6
- package/dist/server/routes/table/controllers/suggest.d.ts.map +1 -1
- package/dist/server/routes/table/controllers/suggest.js +33 -22
- package/dist/server/routes/table/controllers/tableData.js +2 -2
- package/dist/server/routes/table/controllers/tableInfo.js +10 -10
- package/dist/server/routes/table/functions/getData.js +13 -13
- package/dist/server/routes/table/schema.d.ts +5 -0
- package/dist/server/routes/table/schema.d.ts.map +1 -1
- package/dist/server/routes/table/schema.js +1 -0
- package/dist/server/routes/widget/controllers/widget.get.js +33 -33
- package/dist/server/routes/widget/controllers/widget.set.js +4 -4
- package/dist/server/routes/widget/services/widget.entity.get.js +33 -33
- package/dist/server/routes/widget/services/widget.entity.set.js +4 -4
- package/dist/server/templates/page/2factor-recovery.html +101 -101
- package/dist/server/templates/page/2factor.html +140 -140
- package/dist/server/templates/page/login.html +90 -90
- package/dist/server/templates/pt/recovery-codes-email-template.hbs +12 -12
- package/dist/server/templates/pt/recovery-password-email-template.html +20 -20
- package/package.json +99 -99
|
@@ -3,28 +3,28 @@ function init(client) {
|
|
|
3
3
|
if (!client) {
|
|
4
4
|
return;
|
|
5
5
|
}
|
|
6
|
-
const rows = client.prepare(`WITH tables AS (
|
|
7
|
-
SELECT name AS table_name
|
|
8
|
-
FROM sqlite_master
|
|
9
|
-
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
10
|
-
),
|
|
11
|
-
pk_columns AS (
|
|
12
|
-
SELECT
|
|
13
|
-
m.name AS table_name,
|
|
14
|
-
ti.name AS column_name,
|
|
15
|
-
ti.pk
|
|
16
|
-
FROM sqlite_master m
|
|
17
|
-
JOIN pragma_table_info(m.name) AS ti
|
|
18
|
-
WHERE ti.pk = 1
|
|
19
|
-
)
|
|
20
|
-
SELECT table_name, column_name
|
|
21
|
-
FROM pk_columns
|
|
22
|
-
WHERE table_name IN (
|
|
23
|
-
SELECT table_name
|
|
24
|
-
FROM pk_columns
|
|
25
|
-
GROUP BY table_name
|
|
26
|
-
HAVING COUNT(*) = 1
|
|
27
|
-
)
|
|
6
|
+
const rows = client.prepare(`WITH tables AS (
|
|
7
|
+
SELECT name AS table_name
|
|
8
|
+
FROM sqlite_master
|
|
9
|
+
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
10
|
+
),
|
|
11
|
+
pk_columns AS (
|
|
12
|
+
SELECT
|
|
13
|
+
m.name AS table_name,
|
|
14
|
+
ti.name AS column_name,
|
|
15
|
+
ti.pk
|
|
16
|
+
FROM sqlite_master m
|
|
17
|
+
JOIN pragma_table_info(m.name) AS ti
|
|
18
|
+
WHERE ti.pk = 1
|
|
19
|
+
)
|
|
20
|
+
SELECT table_name, column_name
|
|
21
|
+
FROM pk_columns
|
|
22
|
+
WHERE table_name IN (
|
|
23
|
+
SELECT table_name
|
|
24
|
+
FROM pk_columns
|
|
25
|
+
GROUP BY table_name
|
|
26
|
+
HAVING COUNT(*) = 1
|
|
27
|
+
)
|
|
28
28
|
ORDER BY table_name;`).all();
|
|
29
29
|
const pk = Object.fromEntries(rows.map((row) => [row.table_name, row.column_name]));
|
|
30
30
|
const tlist = client.prepare('SELECT name FROM sqlite_master WHERE type=\'table\' AND name NOT LIKE \'sqlite_%\';').all().reduce((acc, curr) => {
|
|
@@ -342,9 +342,9 @@ export default async function dataAPI({ table, id, page, limit: queryLimit, sql,
|
|
|
342
342
|
interfaceQuery1,
|
|
343
343
|
].filter(Boolean);
|
|
344
344
|
const omitGeometry = omitGeometryParam || (!objectId && loadTable?.showGeometryMode === "card");
|
|
345
|
-
const q1 = `select ${pk ? `"${pk}" as id,` : ""}
|
|
346
|
-
${objectId ? "*" : columnsParam || sqlColumns || cols || "*"}
|
|
347
|
-
${metaCols}
|
|
345
|
+
const q1 = `select ${pk ? `"${pk}" as id,` : ""}
|
|
346
|
+
${objectId ? "*" : columnsParam || sqlColumns || cols || "*"}
|
|
347
|
+
${metaCols}
|
|
348
348
|
${dbColumns.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry")
|
|
349
349
|
.length &&
|
|
350
350
|
!columnsParam &&
|
|
@@ -353,14 +353,14 @@ export default async function dataAPI({ table, id, page, limit: queryLimit, sql,
|
|
|
353
353
|
.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry")
|
|
354
354
|
.map((el) => `st_asgeojson("${el.name.replace(/'/g, "''")}")::json as "${el.name.replace(/'/g, "''")}"`)
|
|
355
355
|
.join(",")}`
|
|
356
|
-
: ""}
|
|
356
|
+
: ""}
|
|
357
357
|
from (select * ${sqlQueryList
|
|
358
358
|
?.filter((el) => el.inline && !(isExport && el.export === false))
|
|
359
359
|
.map((el) => `,(${el.sql})`)
|
|
360
|
-
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable} ) t
|
|
361
|
-
|
|
362
|
-
${objectId ? cardSqlTable : ""}
|
|
363
|
-
where ${where.join(" and ") || "true"}
|
|
360
|
+
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable} ) t
|
|
361
|
+
|
|
362
|
+
${objectId ? cardSqlTable : ""}
|
|
363
|
+
where ${where.join(" and ") || "true"}
|
|
364
364
|
${order} limit $${idx.limit}::bigint offset $${idx.offset}::bigint`;
|
|
365
365
|
if (q1.includes("{{uid}}")) {
|
|
366
366
|
args.push(uid || "");
|
|
@@ -445,18 +445,18 @@ export default async function dataAPI({ table, id, page, limit: queryLimit, sql,
|
|
|
445
445
|
type: pg.pgType?.[el.dataTypeID],
|
|
446
446
|
}))
|
|
447
447
|
.filter((el) => ["numeric", "double precision"].includes(el.type) && aggColumns[el.name]);
|
|
448
|
-
const qCount = `select
|
|
449
|
-
count(*)::int as total,
|
|
450
|
-
count(*) FILTER(WHERE ${filterWhere.join(" and ") || "true"})::int as filtered
|
|
448
|
+
const qCount = `select
|
|
449
|
+
count(*)::int as total,
|
|
450
|
+
count(*) FILTER(WHERE ${filterWhere.join(" and ") || "true"})::int as filtered
|
|
451
451
|
${aggregates.length
|
|
452
452
|
? `,${aggregates
|
|
453
453
|
.map((el) => `${aggColumns[el.name]}(${el.name}) FILTER(WHERE ${filterWhere.join(" and ") || "true"}) as ${el.name}`)
|
|
454
454
|
.join(",")}`
|
|
455
|
-
: ""}
|
|
455
|
+
: ""}
|
|
456
456
|
from (select * ${sqlQueryList
|
|
457
457
|
?.filter((el) => el.inline)
|
|
458
458
|
.map((el) => `,(${el.sql})`)
|
|
459
|
-
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable})t
|
|
459
|
+
.join("") || ""} from ${viewSql ? `(${viewSql})` : table1} t ${sqlTable})t
|
|
460
460
|
where ${[loadTable?.query, tokenData?.query, accessQuery, contextQuery]
|
|
461
461
|
.filter(Boolean)
|
|
462
462
|
.join(" and ") || "true"} `.replace(/'{{uid}}'/g, `$${idx1.uid}`);
|
|
@@ -6,7 +6,7 @@ async function getCustomQuery({ pg, table, customFilter }) {
|
|
|
6
6
|
?.map((el) => el?.split("_").pop());
|
|
7
7
|
const customFilterSQL = pg?.pk?.["admin.properties"]
|
|
8
8
|
? await pg
|
|
9
|
-
.query(`select json_agg(json_build_object('id',property_id,'name',property_key,'query',property_text)
|
|
9
|
+
.query(`select json_agg(json_build_object('id',property_id,'name',property_key,'query',property_text)
|
|
10
10
|
) as property_json from admin.properties where property_key is not null and property_entity='customQuery' and object_id=$1`, [table])
|
|
11
11
|
.then((el) => el.rows?.[0]?.property_json || [])
|
|
12
12
|
: [];
|
|
@@ -4,7 +4,7 @@ import getTemplate from "./getTemplate.js";
|
|
|
4
4
|
const loadCls = {};
|
|
5
5
|
const sqls = {
|
|
6
6
|
sql: "select data from admin.user_cls where name=$1 union all select data from admin.cls where name=$1",
|
|
7
|
-
json: `select json_agg(json_build_object('id', code, 'text', name, 'icon', icon, 'color', color)) as data from admin.user_cls where parent=$1
|
|
7
|
+
json: `select json_agg(json_build_object('id', code, 'text', name, 'icon', icon, 'color', color)) as data from admin.user_cls where parent=$1
|
|
8
8
|
union all select json_agg(json_build_object('id', code, 'text', name, 'icon', icon, 'color', color, 'ua', ua, 'en', en)) as data from admin.cls where parent=$1`,
|
|
9
9
|
};
|
|
10
10
|
export default async function getSelect(name, pg = pgClients.client, nocache = false) {
|
|
@@ -18,7 +18,7 @@ export default async function gisIRColumn({ pg = pgClients.client, layer, column
|
|
|
18
18
|
custom,
|
|
19
19
|
});
|
|
20
20
|
const { tlist } = await pg
|
|
21
|
-
.query(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist from pg_class
|
|
21
|
+
.query(`select array_agg((select nspname from pg_namespace where oid=relnamespace)||'.'||relname) tlist from pg_class
|
|
22
22
|
where relkind in ('r','v','m')`)
|
|
23
23
|
.then((el) => el.rows?.[0] || {});
|
|
24
24
|
const tableName = body?.table || layer;
|
|
@@ -33,9 +33,9 @@ export default async function gisIRColumn({ pg = pgClients.client, layer, column
|
|
|
33
33
|
const colField = pg.pgType?.[col.dataTypeID]?.includes("[]")
|
|
34
34
|
? `unnest(${column})`
|
|
35
35
|
: column;
|
|
36
|
-
const q = `select ${colField} as id, count(*)::int from (
|
|
36
|
+
const q = `select ${colField} as id, count(*)::int from (
|
|
37
37
|
${fData?.optimizedSQL ||
|
|
38
|
-
`select * from ${tableName} where ${body?.query || "true"}`}
|
|
38
|
+
`select * from ${tableName} where ${body?.query || "true"}`}
|
|
39
39
|
)t group by ${colField} order by count desc limit 15`;
|
|
40
40
|
if (sql)
|
|
41
41
|
return q;
|
|
@@ -162,9 +162,9 @@ export async function getUserClsList({ name, search, sql, custom, }, pg = pgClie
|
|
|
162
162
|
}
|
|
163
163
|
const whereQuery = where.join(" and ") || "1=1";
|
|
164
164
|
console.log(name, search, whereQuery);
|
|
165
|
-
const customQuery = `select true as custom, name, type, description, alias, case when type = 'sql' then 1 else (select count(*) from admin.user_cls where parent=t.name limit 1) end as count
|
|
165
|
+
const customQuery = `select true as custom, name, type, description, alias, case when type = 'sql' then 1 else (select count(*) from admin.user_cls where parent=t.name limit 1) end as count
|
|
166
166
|
from admin.user_cls t where parent is null and ${whereQuery}`;
|
|
167
|
-
const gitQuery = `select false as custom, name, type, null as description, null as alias, case when type = 'sql' then 1 else (select count(*) from admin.cls where parent=t.name limit 1) end as count
|
|
167
|
+
const gitQuery = `select false as custom, name, type, null as description, null as alias, case when type = 'sql' then 1 else (select count(*) from admin.cls where parent=t.name limit 1) end as count
|
|
168
168
|
from admin.cls t where parent is null and ${whereQuery.replace(/admin.user_cls/g, "admin.cls")}`;
|
|
169
169
|
const q = [
|
|
170
170
|
custom !== "0" ? customQuery : null,
|
|
@@ -12,18 +12,18 @@ export default async function accessGroup({ pg = pgClients.client, params, user
|
|
|
12
12
|
throw ForbiddenError("not an admin");
|
|
13
13
|
}
|
|
14
14
|
const routes = await pg
|
|
15
|
-
.query(`select a.route_id as path, b.actions from admin.routes a
|
|
16
|
-
left join admin.role_access b on a.route_id=b.route_id
|
|
15
|
+
.query(`select a.route_id as path, b.actions from admin.routes a
|
|
16
|
+
left join admin.role_access b on a.route_id=b.route_id
|
|
17
17
|
where b.role_id=$1`, [params.id])
|
|
18
18
|
.then((el) => el.rows || []);
|
|
19
19
|
const resources = await pg
|
|
20
|
-
.query(`select resource_id, actions from admin.role_access
|
|
20
|
+
.query(`select resource_id, actions from admin.role_access
|
|
21
21
|
where resource_id is not null and role_id=$1`, [params.id])
|
|
22
22
|
.then((el) => el.rows || []);
|
|
23
23
|
const users = await pg
|
|
24
|
-
.query(`select user_uid as id, user_name as name, access_granted,
|
|
25
|
-
b.cdate as user_created, b.last_activity_date as last_activity from admin.user_roles a
|
|
26
|
-
left join admin.users b on a.user_uid=b.uid
|
|
24
|
+
.query(`select user_uid as id, user_name as name, access_granted,
|
|
25
|
+
b.cdate as user_created, b.last_activity_date as last_activity from admin.user_roles a
|
|
26
|
+
left join admin.users b on a.user_uid=b.uid
|
|
27
27
|
where a.role_id=$1`, [params.id])
|
|
28
28
|
.then((el) => el.rows || []);
|
|
29
29
|
return { routes, resources, users };
|
|
@@ -39,12 +39,12 @@ export default async function accessGroupPost({ pg = pgClients.client, params, u
|
|
|
39
39
|
.filter((el) => el.resource && el.actions)
|
|
40
40
|
.map((el) => pg.query("insert into admin.role_access(role_id,resource_id,route_id,actions) values ($1,$2,$3,$4)", [id, el.resource, el.path, el.actions])));
|
|
41
41
|
const rows = await pg
|
|
42
|
-
.query(`select a.route_id as path, b.actions as actions from admin.routes a
|
|
43
|
-
left join admin.role_access b on a.route_id=b.route_id
|
|
42
|
+
.query(`select a.route_id as path, b.actions as actions from admin.routes a
|
|
43
|
+
left join admin.role_access b on a.route_id=b.route_id
|
|
44
44
|
where b.role_id=$1`, [id])
|
|
45
45
|
.then((el) => el.rows || []);
|
|
46
46
|
const resources = await pg
|
|
47
|
-
.query(`select resource_id, actions from admin.role_access
|
|
47
|
+
.query(`select resource_id, actions from admin.role_access
|
|
48
48
|
where resource_id is not null and role_id=$1`, [id])
|
|
49
49
|
.then((el) => el.rows || []);
|
|
50
50
|
if (!users?.length) {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { ForbiddenError, UnauthorizedError } from "../../../../errors.js";
|
|
2
2
|
import { pgClients, metaFormat } from "../../../../utils.js";
|
|
3
|
-
const q = `select a.route_id as id, coalesce(b.user_uid, d.user_uid) as user_uid, coalesce(d.actions, b.actions, array['view']) as actions, b.scope, c.role_id
|
|
4
|
-
from admin.routes a
|
|
5
|
-
left join admin.role_access b on
|
|
6
|
-
a.route_id=b.route_id
|
|
7
|
-
left join admin.roles c on
|
|
8
|
-
b.role_id=c.role_id
|
|
9
|
-
and c.enabled
|
|
10
|
-
left join admin.user_roles d on
|
|
11
|
-
c.role_id=d.role_id
|
|
12
|
-
and ( case when
|
|
13
|
-
d.expiration is not null
|
|
14
|
-
then d.expiration > CURRENT_DATE
|
|
15
|
-
else 1=1
|
|
16
|
-
end )
|
|
3
|
+
const q = `select a.route_id as id, coalesce(b.user_uid, d.user_uid) as user_uid, coalesce(d.actions, b.actions, array['view']) as actions, b.scope, c.role_id
|
|
4
|
+
from admin.routes a
|
|
5
|
+
left join admin.role_access b on
|
|
6
|
+
a.route_id=b.route_id
|
|
7
|
+
left join admin.roles c on
|
|
8
|
+
b.role_id=c.role_id
|
|
9
|
+
and c.enabled
|
|
10
|
+
left join admin.user_roles d on
|
|
11
|
+
c.role_id=d.role_id
|
|
12
|
+
and ( case when
|
|
13
|
+
d.expiration is not null
|
|
14
|
+
then d.expiration > CURRENT_DATE
|
|
15
|
+
else 1=1
|
|
16
|
+
end )
|
|
17
17
|
where $1 in (a.route_id, a.alias, a.table_name) and coalesce(b.user_uid, d.user_uid) is not null`;
|
|
18
18
|
export default async function accessInterface(req) {
|
|
19
19
|
const { pg = pgClients.client, params = {}, user = {} } = req;
|
|
@@ -13,18 +13,18 @@ export default async function accessUser({ pg = pgClients.client, params, user,
|
|
|
13
13
|
// throw ForbiddenError("not an admin");
|
|
14
14
|
}
|
|
15
15
|
const routes = await pg
|
|
16
|
-
.query(`select a.route_id as path, b.actions from admin.routes a
|
|
17
|
-
left join admin.role_access b on a.route_id=b.route_id
|
|
16
|
+
.query(`select a.route_id as path, b.actions from admin.routes a
|
|
17
|
+
left join admin.role_access b on a.route_id=b.route_id
|
|
18
18
|
where b.user_uid=$1`, [params.id])
|
|
19
19
|
.then((r) => r.rows || []);
|
|
20
20
|
const resources = await pg
|
|
21
|
-
.query(`select resource_id, actions from admin.role_access
|
|
21
|
+
.query(`select resource_id, actions from admin.role_access
|
|
22
22
|
where resource_id is not null and user_uid=$1`, [params.id])
|
|
23
23
|
.then((r) => r.rows || []);
|
|
24
24
|
const userRoles = await pg
|
|
25
|
-
.query(`select user_uid as id, user_name as name, access_granted,
|
|
26
|
-
b.cdate as user_created, b.last_activity_date as last_activity from admin.user_roles a
|
|
27
|
-
left join admin.users b on a.user_uid=b.uid
|
|
25
|
+
.query(`select user_uid as id, user_name as name, access_granted,
|
|
26
|
+
b.cdate as user_created, b.last_activity_date as last_activity from admin.user_roles a
|
|
27
|
+
left join admin.users b on a.user_uid=b.uid
|
|
28
28
|
where a.user_uid=$1`, [params.id])
|
|
29
29
|
.then((r) => r.rows?.[0]);
|
|
30
30
|
return { routes, resources, user: userRoles };
|
|
@@ -24,20 +24,20 @@ const deleteSecret = async ({ uid, pg }) => {
|
|
|
24
24
|
};
|
|
25
25
|
const getSecret = async ({ uid, pg }) => {
|
|
26
26
|
const { social_auth_code: secret, enabled, recoveryCodes, } = await pg
|
|
27
|
-
.query(`select social_auth_code, enabled, social_auth_obj->'codesArray' as "recoveryCodes"
|
|
28
|
-
from admin.users_social_auth
|
|
27
|
+
.query(`select social_auth_code, enabled, social_auth_obj->'codesArray' as "recoveryCodes"
|
|
28
|
+
from admin.users_social_auth
|
|
29
29
|
where uid = $1 and social_auth_type = $2`, [uid, TYPE])
|
|
30
30
|
.then((r) => r.rows?.[0] || {});
|
|
31
31
|
return { secret, enabled, recoveryCodes };
|
|
32
32
|
};
|
|
33
33
|
const addSecret = async ({ uid, secret, pg, recoveryCodes, otp }) => {
|
|
34
|
-
await pg.query(`insert into admin.users_social_auth(uid, social_auth_code, social_auth_type, social_auth_obj, social_auth_url, enabled)
|
|
34
|
+
await pg.query(`insert into admin.users_social_auth(uid, social_auth_code, social_auth_type, social_auth_obj, social_auth_url, enabled)
|
|
35
35
|
values($1, $2, $3, $4::json, $5, false)`, [uid, secret, TYPE, { codesArray: recoveryCodes }, otp]);
|
|
36
36
|
};
|
|
37
37
|
const updateSecret = async ({ uid, pg, secret, recoveryCodes, otp }) => {
|
|
38
38
|
const result = await pg
|
|
39
|
-
.query(`update admin.users_social_auth
|
|
40
|
-
set social_auth_code=$3, social_auth_obj=$4::json, social_auth_url=$5
|
|
39
|
+
.query(`update admin.users_social_auth
|
|
40
|
+
set social_auth_code=$3, social_auth_obj=$4::json, social_auth_url=$5
|
|
41
41
|
where uid = $1 and social_auth_type = $2`, [uid, TYPE, secret, { codesArray: recoveryCodes }, otp])
|
|
42
42
|
.then((r) => r.rows?.[0] || {});
|
|
43
43
|
return result;
|
|
@@ -24,7 +24,7 @@ export default async function qrCode(req, reply) {
|
|
|
24
24
|
const { enabled, secret } = await getSecret({ pg, uid });
|
|
25
25
|
const { otp } = secret
|
|
26
26
|
? await pg
|
|
27
|
-
.query(`select social_auth_url as otp from admin.users_social_auth
|
|
27
|
+
.query(`select social_auth_url as otp from admin.users_social_auth
|
|
28
28
|
where uid=$1 and social_auth_type=$2`, [uid, "TOTP"])
|
|
29
29
|
?.then((el) => el.rows?.[0] || {})
|
|
30
30
|
: await generate({ uid, pg });
|
|
@@ -48,7 +48,7 @@ export default async function recovery(req, reply) {
|
|
|
48
48
|
const pt = customPt ||
|
|
49
49
|
(await readFile(path.join(dirname, `../../../../../dist/server/templates/pt/${template}.hbs`), "utf8"));
|
|
50
50
|
const recoveryCodes = await pg
|
|
51
|
-
.query(`select social_auth_obj->'codesArray' as "recoveryCodes" from admin.users_social_auth
|
|
51
|
+
.query(`select social_auth_obj->'codesArray' as "recoveryCodes" from admin.users_social_auth
|
|
52
52
|
where uid = $1 and social_auth_type = $2`, [uid, "TOTP"])
|
|
53
53
|
.then((el) => el.rows?.[0]?.recoveryCodes || []);
|
|
54
54
|
if (!recoveryCodes?.length) {
|
|
@@ -48,7 +48,7 @@ export default async function verifyFunction(req, reply) {
|
|
|
48
48
|
req.session.secondFactorPassed = true;
|
|
49
49
|
if (!enabled && email) {
|
|
50
50
|
const { recoveryCodes } = await pg
|
|
51
|
-
.query(`select social_auth_obj->'codesArray' as "recoveryCodes"
|
|
51
|
+
.query(`select social_auth_obj->'codesArray' as "recoveryCodes"
|
|
52
52
|
from admin.users_social_auth where uid=$1 and social_auth_type='TOTP'`, [uid])
|
|
53
53
|
?.then((el) => el.rows?.[0] || {});
|
|
54
54
|
const customPt = await getTemplate("pt", template);
|
|
@@ -5,31 +5,31 @@ import applyHook from "../../../../plugins/hook/applyHook.js";
|
|
|
5
5
|
import getRedis from "../../../../plugins/redis/funcs/getRedis.js";
|
|
6
6
|
import getUserPermissions from "../../../../plugins/access/funcs/getUserPermissions.js";
|
|
7
7
|
const rclient2 = getRedis({ db: 2 });
|
|
8
|
-
const q = `select
|
|
9
|
-
|
|
10
|
-
a.route_id as id,
|
|
11
|
-
/* coalesce(d.actions, array['view', 'edit','add','del']) as role_actions,
|
|
12
|
-
coalesce(b.actions, array['view']) as interface_actions, */
|
|
13
|
-
array_intersect(coalesce(b.actions, array['view']), coalesce(d.actions, array['view', 'edit','add','del'])) as actions,
|
|
14
|
-
b.scope,
|
|
15
|
-
c.role_id,
|
|
16
|
-
c.name as role_name
|
|
17
|
-
|
|
18
|
-
from admin.routes a
|
|
19
|
-
left join admin.role_access b on
|
|
20
|
-
a.route_id=b.route_id
|
|
21
|
-
left join admin.roles c on
|
|
22
|
-
b.role_id=c.role_id
|
|
23
|
-
and c.enabled
|
|
24
|
-
left join admin.user_roles d on
|
|
25
|
-
c.role_id=d.role_id
|
|
26
|
-
and (
|
|
27
|
-
case when
|
|
28
|
-
d.expiration is not null
|
|
29
|
-
then d.expiration > CURRENT_DATE
|
|
30
|
-
else 1=1
|
|
31
|
-
end
|
|
32
|
-
)
|
|
8
|
+
const q = `select
|
|
9
|
+
|
|
10
|
+
a.route_id as id,
|
|
11
|
+
/* coalesce(d.actions, array['view', 'edit','add','del']) as role_actions,
|
|
12
|
+
coalesce(b.actions, array['view']) as interface_actions, */
|
|
13
|
+
array_intersect(coalesce(b.actions, array['view']), coalesce(d.actions, array['view', 'edit','add','del'])) as actions,
|
|
14
|
+
b.scope,
|
|
15
|
+
c.role_id,
|
|
16
|
+
c.name as role_name
|
|
17
|
+
|
|
18
|
+
from admin.routes a
|
|
19
|
+
left join admin.role_access b on
|
|
20
|
+
a.route_id=b.route_id
|
|
21
|
+
left join admin.roles c on
|
|
22
|
+
b.role_id=c.role_id
|
|
23
|
+
and c.enabled
|
|
24
|
+
left join admin.user_roles d on
|
|
25
|
+
c.role_id=d.role_id
|
|
26
|
+
and (
|
|
27
|
+
case when
|
|
28
|
+
d.expiration is not null
|
|
29
|
+
then d.expiration > CURRENT_DATE
|
|
30
|
+
else 1=1
|
|
31
|
+
end
|
|
32
|
+
)
|
|
33
33
|
where $1 in (b.user_uid, d.user_uid)`;
|
|
34
34
|
export default async function getUserInfo(req) {
|
|
35
35
|
const { pg = pgClients.client, user, session, cookies } = req;
|
|
@@ -53,14 +53,14 @@ export default async function getUserInfo(req) {
|
|
|
53
53
|
: config.settingKeys || ["site", "map", "admin"];
|
|
54
54
|
const settings = pg?.pk?.["admin.properties"]
|
|
55
55
|
? await pg
|
|
56
|
-
.query(`select
|
|
57
|
-
property_key as key,
|
|
58
|
-
case
|
|
59
|
-
when property_text is not null then to_jsonb(property_text)
|
|
60
|
-
when property_int is not null then to_jsonb(property_int)
|
|
61
|
-
when property_json is not null then property_json::jsonb
|
|
62
|
-
end as val
|
|
63
|
-
from admin.properties
|
|
56
|
+
.query(`select
|
|
57
|
+
property_key as key,
|
|
58
|
+
case
|
|
59
|
+
when property_text is not null then to_jsonb(property_text)
|
|
60
|
+
when property_int is not null then to_jsonb(property_int)
|
|
61
|
+
when property_json is not null then property_json::jsonb
|
|
62
|
+
end as val
|
|
63
|
+
from admin.properties
|
|
64
64
|
where property_key like any($1)`, [settingKeys.map((key) => `${key}%`)])
|
|
65
65
|
.then((el) => el.rows.reduce((p, { key, val }) => {
|
|
66
66
|
const [k1, k2] = key.split(".");
|
|
@@ -78,7 +78,7 @@ export default async function passwordRecovery(req, reply) {
|
|
|
78
78
|
if (config.pg) {
|
|
79
79
|
await pg.query(q, [code, body.email]);
|
|
80
80
|
}
|
|
81
|
-
const userQuery = `select coalesce(sur_name,'')|| coalesce(' '||user_name,'')||coalesce(' '||father_name,'') as user
|
|
81
|
+
const userQuery = `select coalesce(sur_name,'')|| coalesce(' '||user_name,'')||coalesce(' '||father_name,'') as user
|
|
82
82
|
from admin.users where $1 in (login,email) limit 1`;
|
|
83
83
|
const userName = config.pg
|
|
84
84
|
? await pg
|
|
@@ -84,8 +84,8 @@ export default async function registration(req, reply) {
|
|
|
84
84
|
const { uid } = await pg
|
|
85
85
|
.query(q3, [login])
|
|
86
86
|
.then((el) => el.rows?.[0] || {});
|
|
87
|
-
await pg.query(`insert into admin.users (uid, login, password, user_name, sur_name, father_name, email,phone, enabled, user_personal_code )
|
|
88
|
-
select contact_id, $4, $3, first_name, last_name, middle_name, $2, phone, true, md5(random()::text)
|
|
87
|
+
await pg.query(`insert into admin.users (uid, login, password, user_name, sur_name, father_name, email,phone, enabled, user_personal_code )
|
|
88
|
+
select contact_id, $4, $3, first_name, last_name, middle_name, $2, phone, true, md5(random()::text)
|
|
89
89
|
from crm_acc.crm_contact where contact_id = $1 and contact_id not in (select uid from admin.users)`, [uid, email, password, login]);
|
|
90
90
|
}
|
|
91
91
|
else {
|
|
@@ -37,7 +37,7 @@ export default async function loginTemplate(req, reply) {
|
|
|
37
37
|
const { enabled, secret } = config.pg ? await getSecret({ pg, uid }) : {};
|
|
38
38
|
const { otp, recoveryCodes, key } = secret && pg?.pk?.["admin.users_social_auth"]
|
|
39
39
|
? await pg
|
|
40
|
-
.query(`select social_auth_obj->'codesArray' as "recoveryCodes", enabled, social_auth_url as otp
|
|
40
|
+
.query(`select social_auth_obj->'codesArray' as "recoveryCodes", enabled, social_auth_url as otp
|
|
41
41
|
from admin.users_social_auth where uid=$1 and social_auth_type='TOTP'`, [uid])
|
|
42
42
|
?.then((el) => el.rows?.[0] || {})
|
|
43
43
|
: await generate({ uid, pg });
|
|
@@ -43,15 +43,15 @@ export default async function deleteTableRelation({ table: paramsTable, id: para
|
|
|
43
43
|
}
|
|
44
44
|
const relationTableTemplate = await getTemplate("table", relationTable);
|
|
45
45
|
const pks = await pg
|
|
46
|
-
.query(`
|
|
47
|
-
SELECT
|
|
48
|
-
connamespace::regnamespace::text,
|
|
49
|
-
conrelid::regclass,
|
|
50
|
-
(
|
|
51
|
-
SELECT attname FROM pg_attribute WHERE attrelid = c.conrelid AND attnum = c.conkey[1]
|
|
52
|
-
) as pk
|
|
53
|
-
FROM pg_constraint c
|
|
54
|
-
WHERE contype = 'p'
|
|
46
|
+
.query(`
|
|
47
|
+
SELECT
|
|
48
|
+
connamespace::regnamespace::text,
|
|
49
|
+
conrelid::regclass,
|
|
50
|
+
(
|
|
51
|
+
SELECT attname FROM pg_attribute WHERE attrelid = c.conrelid AND attnum = c.conkey[1]
|
|
52
|
+
) as pk
|
|
53
|
+
FROM pg_constraint c
|
|
54
|
+
WHERE contype = 'p'
|
|
55
55
|
AND connamespace::regnamespace::text NOT IN ('sde')`)
|
|
56
56
|
.then((r) => r.rows || []);
|
|
57
57
|
const pkList = pks.reduce((acc, curr) => ({
|
|
@@ -49,15 +49,15 @@ export default async function updateTableRelation({ table: paramsTable, id: para
|
|
|
49
49
|
throw new Error("invalid relation: foreignKey not set");
|
|
50
50
|
}
|
|
51
51
|
const pks = await pg
|
|
52
|
-
.query(`
|
|
53
|
-
SELECT
|
|
54
|
-
connamespace::regnamespace::text,
|
|
55
|
-
conrelid::regclass,
|
|
56
|
-
(
|
|
57
|
-
SELECT attname FROM pg_attribute WHERE attrelid = c.conrelid AND attnum = c.conkey[1]
|
|
58
|
-
) as pk
|
|
59
|
-
FROM pg_constraint c
|
|
60
|
-
WHERE contype = 'p'
|
|
52
|
+
.query(`
|
|
53
|
+
SELECT
|
|
54
|
+
connamespace::regnamespace::text,
|
|
55
|
+
conrelid::regclass,
|
|
56
|
+
(
|
|
57
|
+
SELECT attname FROM pg_attribute WHERE attrelid = c.conrelid AND attnum = c.conkey[1]
|
|
58
|
+
) as pk
|
|
59
|
+
FROM pg_constraint c
|
|
60
|
+
WHERE contype = 'p'
|
|
61
61
|
AND connamespace::regnamespace::text NOT IN ('sde')`)
|
|
62
62
|
.then((r) => r.rows || []);
|
|
63
63
|
const pkList = pks.reduce((acc, curr) => ({
|
|
@@ -69,9 +69,9 @@ export default async function resizeAll(req, reply) {
|
|
|
69
69
|
const { pg = pgClients.client, query = {} } = req;
|
|
70
70
|
const { nocache, filepath, quality = 80, limit, sql, w = 2048 } = query;
|
|
71
71
|
if (nocache) {
|
|
72
|
-
const clearQ = `update crm.files set resized=null
|
|
73
|
-
where ext=any($1)
|
|
74
|
-
and ${filepath ? "file_path=$2" : "1=1"}
|
|
72
|
+
const clearQ = `update crm.files set resized=null
|
|
73
|
+
where ext=any($1)
|
|
74
|
+
and ${filepath ? "file_path=$2" : "1=1"}
|
|
75
75
|
and resized is not null`;
|
|
76
76
|
if (sql)
|
|
77
77
|
return clearQ;
|
|
@@ -79,10 +79,10 @@ export default async function resizeAll(req, reply) {
|
|
|
79
79
|
return reply.status(200).send({ msg: "clear cache success", rowCount });
|
|
80
80
|
}
|
|
81
81
|
const resizeQuality = Math.min(quality, 100);
|
|
82
|
-
const q = `select file_id as id, file_path as relpath from crm.files
|
|
83
|
-
where ext=any($1)
|
|
84
|
-
and ${filepath ? "file_path=$3" : "1=1"}
|
|
85
|
-
and resized is null
|
|
82
|
+
const q = `select file_id as id, file_path as relpath from crm.files
|
|
83
|
+
where ext=any($1)
|
|
84
|
+
and ${filepath ? "file_path=$3" : "1=1"}
|
|
85
|
+
and resized is null
|
|
86
86
|
limit $2`;
|
|
87
87
|
if (sql)
|
|
88
88
|
return q;
|
|
@@ -23,19 +23,19 @@ export default async function file2geojson({ pg = pgClients.client, body = {}, }
|
|
|
23
23
|
const JsonArr = JsonData?.features
|
|
24
24
|
? JsonData
|
|
25
25
|
: { type: "FeatureCollection", features: [JsonData] };
|
|
26
|
-
const { rows = [] } = await pg.query(`
|
|
27
|
-
select
|
|
28
|
-
features->>'type' as type,
|
|
29
|
-
features->'properties' as properties,
|
|
30
|
-
st_asgeojson(st_transform(st_setsrid(st_geomfromgeojson(features->>'geometry'),$2),4326))::json as geometry
|
|
31
|
-
from (
|
|
32
|
-
select d->>'type' as type,d->>'name' as name,json_array_elements(d->'features') as features
|
|
33
|
-
from (
|
|
34
|
-
select json_array_elements(case when json_typeof(d)='array' then d else json_build_array(d) end)d
|
|
35
|
-
from (
|
|
36
|
-
select ($1)::json as d
|
|
37
|
-
)q
|
|
38
|
-
)q
|
|
26
|
+
const { rows = [] } = await pg.query(`
|
|
27
|
+
select
|
|
28
|
+
features->>'type' as type,
|
|
29
|
+
features->'properties' as properties,
|
|
30
|
+
st_asgeojson(st_transform(st_setsrid(st_geomfromgeojson(features->>'geometry'),$2),4326))::json as geometry
|
|
31
|
+
from (
|
|
32
|
+
select d->>'type' as type,d->>'name' as name,json_array_elements(d->'features') as features
|
|
33
|
+
from (
|
|
34
|
+
select json_array_elements(case when json_typeof(d)='array' then d else json_build_array(d) end)d
|
|
35
|
+
from (
|
|
36
|
+
select ($1)::json as d
|
|
37
|
+
)q
|
|
38
|
+
)q
|
|
39
39
|
)q`, [JSON.stringify(JsonArr).replace(/'/g, "''"), srid]);
|
|
40
40
|
return [{ features: [rows.slice(0, 1)] }];
|
|
41
41
|
}
|
|
@@ -75,15 +75,15 @@ export default async function adminMenu({ user = {}, session, pg = pgClients.cli
|
|
|
75
75
|
user.user_type !== "viewer" &&
|
|
76
76
|
pg.pk?.["admin.role_access"]) {
|
|
77
77
|
const { type, gl = [], routes = [], } = await pg
|
|
78
|
-
.query(`select user_type as type, b.gl,routes from admin.users a
|
|
79
|
-
left join lateral (
|
|
80
|
-
select array_agg(role_id) as gl from admin.user_roles
|
|
81
|
-
where user_uid=a.uid
|
|
82
|
-
and role_id in ( select role_id from admin.roles where enabled)
|
|
83
|
-
)b on 1=1
|
|
84
|
-
left join lateral (
|
|
85
|
-
select array_agg(route_id) as routes from admin.role_access where role_id=any(b.gl)
|
|
86
|
-
)r on 1=1
|
|
78
|
+
.query(`select user_type as type, b.gl,routes from admin.users a
|
|
79
|
+
left join lateral (
|
|
80
|
+
select array_agg(role_id) as gl from admin.user_roles
|
|
81
|
+
where user_uid=a.uid
|
|
82
|
+
and role_id in ( select role_id from admin.roles where enabled)
|
|
83
|
+
)b on 1=1
|
|
84
|
+
left join lateral (
|
|
85
|
+
select array_agg(route_id) as routes from admin.role_access where role_id=any(b.gl)
|
|
86
|
+
)r on 1=1
|
|
87
87
|
where uid=$1`, [user.uid])
|
|
88
88
|
.then((el) => el.rows[0] || {});
|
|
89
89
|
/* const { interfaces = [] } = await pg.query(`select array_agg(route_id) as interfaces from admin.role_access
|
|
@@ -7,10 +7,10 @@ export default async function readNotifications(req) {
|
|
|
7
7
|
}
|
|
8
8
|
const ids = pg && pg.pk?.["crm.notifications"]
|
|
9
9
|
? await pg
|
|
10
|
-
.query(`update crm.notifications
|
|
11
|
-
set read=true
|
|
12
|
-
where read is not true
|
|
13
|
-
and addressee_id=$1
|
|
10
|
+
.query(`update crm.notifications
|
|
11
|
+
set read=true
|
|
12
|
+
where read is not true
|
|
13
|
+
and addressee_id=$1
|
|
14
14
|
and ${params.id ? "notification_id=$2" : "1=1"} returning notification_id`, [user.uid, params?.id].filter(Boolean))
|
|
15
15
|
.then((el) => el.rows?.map((row) => row.notification_id) || [])
|
|
16
16
|
: [];
|
|
@@ -2,9 +2,9 @@ import pgClients from "../../../plugins/pg/pgClients.js";
|
|
|
2
2
|
import getSelectVal from "../../../plugins/table/funcs/metaFormat/getSelectVal.js";
|
|
3
3
|
import { UnauthorizedError } from "../../../../errors.js";
|
|
4
4
|
const maxLimit = 100;
|
|
5
|
-
const q = `select notification_id as id, subject, body, created_at,
|
|
6
|
-
author_id, read, link, entity_id, (select avatar from admin.users where uid=a.author_id limit 1) as avatar
|
|
7
|
-
from crm.notifications a
|
|
5
|
+
const q = `select notification_id as id, subject, body, created_at,
|
|
6
|
+
author_id, read, link, entity_id, (select avatar from admin.users where uid=a.author_id limit 1) as avatar
|
|
7
|
+
from crm.notifications a
|
|
8
8
|
where addressee_id=$1 order by created_at desc limit $2::bigint offset $3::bigint`;
|
|
9
9
|
export default async function userNotifications(req) {
|
|
10
10
|
const { pg = pgClients.client, query, user, } = req;
|
|
@@ -57,7 +57,7 @@ export default async function card(req, reply) {
|
|
|
57
57
|
: "";
|
|
58
58
|
const q = `select ${pk ? `"${pk}" as id,` : ""} ${dbColumns.find((el) => el.name === "geom" && pg.pgType[el.dataTypeID] === "geometry")
|
|
59
59
|
? "st_asgeojson(geom)::json as geom,"
|
|
60
|
-
: ""} ${cols || "*"} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable}
|
|
60
|
+
: ""} ${cols || "*"} ${cardColumns} from ${table} t ${sqlTable} ${cardSqlTable}
|
|
61
61
|
where ${where.join(" and ") || "true"} limit 1`;
|
|
62
62
|
if (query.sql === "1") {
|
|
63
63
|
return q;
|