@opengis/fastify-table 2.0.42 → 2.0.44

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.
@@ -6,6 +6,7 @@ ALTER TABLE admin.users add column if not exists uid text NOT NULL DEFAULT next_
6
6
  ALTER TABLE admin.users DROP CONSTRAINT if exists admin_user_uid_pkey cascade;
7
7
  ALTER TABLE admin.users DROP CONSTRAINT if exists user_pk cascade;
8
8
  ALTER TABLE admin.users DROP CONSTRAINT if exists admin_user_user_rnokpp;
9
+ ALTER TABLE admin.users DROP CONSTRAINT if exists admin_user_type_check;
9
10
 
10
11
  ALTER TABLE admin.users add column if not exists login text;
11
12
  ALTER TABLE admin.users add column if not exists password text NOT NULL DEFAULT ''::text;
@@ -32,6 +33,11 @@ ALTER TABLE admin.users add column if not exists twofa boolean not null DEFAULT
32
33
  ALTER TABLE admin.users add CONSTRAINT admin_user_uid_pkey PRIMARY KEY (uid);
33
34
  ALTER TABLE admin.users add CONSTRAINT admin_user_user_rnokpp UNIQUE (user_rnokpp);
34
35
 
36
+ update admin.users set user_type='regular' where user_type not in ('viewer', 'regular','admin','superadmin');
37
+ ALTER TABLE admin.users add constraint admin_user_type_check CHECK (user_type=any(array['viewer', 'regular','admin','superadmin']));
38
+ insert into admin.users (uid,login,password,user_type,enabled)values('viewer','viewer','viewer','viewer', false) on conflict (uid) do update set enabled=excluded.enabled;
39
+ -- update admin.users set enabled=true where uid='viewer';
40
+
35
41
  COMMENT ON TABLE admin.users IS 'Користувачі';
36
42
 
37
43
  COMMENT ON COLUMN admin.users.uid IS 'ID користувача';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAkB1C,iBAAS,MAAM,CAAC,OAAO,EAAE,eAAe,QAsIvC;AAED,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAkB1C,iBAAS,MAAM,CAAC,OAAO,EAAE,eAAe,QAuIvC;AAED,eAAe,MAAM,CAAC"}
@@ -80,7 +80,9 @@ function plugin(fastify) {
80
80
  !config.auth?.disableRedirect &&
81
81
  !req.url.startsWith(prefix) &&
82
82
  !req.url.startsWith("/api") &&
83
- !req.url.startsWith("/login")) {
83
+ !req.url.startsWith("/login") &&
84
+ !req.url.includes('.') &&
85
+ !req.url.includes('@')) {
84
86
  return reply.redirect(`${config?.auth?.redirect || "/login"}` + `?redirect=${req.url}`);
85
87
  }
86
88
  // by default, disable 2factor for id.gov.ua auth
@@ -1 +1 @@
1
- {"version":3,"file":"getAccess.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/getAccess.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;GASG;AAEH,wBAA8B,SAAS,CACrC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAS,EAAE,EAAE,GAAG,EAC/B,EAAE,MAAmB,sBAmEtB"}
1
+ {"version":3,"file":"getAccess.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/getAccess.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;GASG;AAEH,wBAA8B,SAAS,CACrC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAS,EAAE,EAAE,GAAG,EAC/B,EAAE,MAAmB,sBAuEtB"}
@@ -37,6 +37,9 @@ export default async function getAccess({ table, form, user = {} }, pg = pgClien
37
37
  if (userType === "superadmin") {
38
38
  return { actions: allActions, query: "1=1" };
39
39
  }
40
+ if (userType === "viewer") {
41
+ return { actions: ["view"], query: "1=1" };
42
+ }
40
43
  const body = await getTemplate("table", table);
41
44
  const tableActions = !body && form
42
45
  ? allActions // if db table and form => full access (token)
@@ -1 +1 @@
1
- {"version":3,"file":"checkPolicy.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAKhC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,oSAiK5E"}
1
+ {"version":3,"file":"checkPolicy.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAKhC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,oSA6K5E"}
@@ -3,8 +3,10 @@ import block from "../sqlInjection.js";
3
3
  export default function checkPolicy(req, reply) {
4
4
  const { originalUrl: path, hostname, query, params, headers, method, routeOptions, unittest, // legacy
5
5
  } = req;
6
+ const user = req.user || req.session?.passport?.user;
6
7
  // ! skip locally, skip tests
7
- if (config.local || unittest || process.env.NODE_ENV === "test") {
8
+ if ((config.local || unittest || process.env.NODE_ENV === "test") &&
9
+ user?.user_type !== "viewer") {
8
10
  return null;
9
11
  }
10
12
  // ! skip non-API Requests
@@ -19,8 +21,6 @@ export default function checkPolicy(req, reply) {
19
21
  hostname.split(":").shift() === config.adminDomain ||
20
22
  config.admin ||
21
23
  hostname.startsWith("admin");
22
- const user = req.user || req.session?.passport?.user;
23
- // const isServer = process.argv[2];
24
24
  const { role, referer, policy = [], } = (routeOptions?.config || {});
25
25
  const isRole = (role && user?.user_type !== role) ||
26
26
  (policy.includes("admin") && user?.user_type !== "admin");
@@ -35,9 +35,19 @@ export default function checkPolicy(req, reply) {
35
35
  const requireReferer = Array.isArray(policy)
36
36
  ? policy.includes("referer")
37
37
  : referer;
38
+ if (method !== "GET" && user?.user_type === "viewer") {
39
+ logger.file("policy/role", {
40
+ path,
41
+ method,
42
+ userRole: user.user_type,
43
+ });
44
+ return reply.status(403).send("access restricted: 0");
45
+ }
38
46
  // ! role
39
47
  if (isRole) {
40
48
  logger.file("policy/role", {
49
+ role,
50
+ userRole: user?.user_type || "none",
41
51
  path,
42
52
  method,
43
53
  params,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAiC1C,iBAAe,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,GAAE,GAAQ,iBA0ExD;AAED,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/routes/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAiC1C,iBAAe,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,GAAE,GAAQ,iBA4ExD;AAED,eAAe,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getMenu.d.ts","sourceRoot":"","sources":["../../../../../server/routes/menu/controllers/getMenu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA4CzD,wBAA8B,SAAS,CACrC,EACE,IAAS,EACT,OAAO,EACP,EAAqB,GACtB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,EAAE,EAAE,UAAU,CAAC;CAChB,EACD,KAAK,EAAE,YAAY,GAAG,IAAI;;;;;;;;;;;;GAuG3B"}
1
+ {"version":3,"file":"getMenu.d.ts","sourceRoot":"","sources":["../../../../../server/routes/menu/controllers/getMenu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA4CzD,wBAA8B,SAAS,CACrC,EACE,IAAS,EACT,OAAO,EACP,EAAqB,GACtB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,EAAE,EAAE,UAAU,CAAC;CAChB,EACD,KAAK,EAAE,YAAY,GAAG,IAAI;;;;;;;;;;;;GAwG3B"}
@@ -66,6 +66,7 @@ export default async function adminMenu({ user = {}, session, pg = pgClients.cli
66
66
  user?.uid &&
67
67
  !user.user_type?.includes?.("admin") &&
68
68
  !user.type?.includes?.("admin") &&
69
+ user.user_type !== "viewer" &&
69
70
  pg.pk?.["admin.role_access"]) {
70
71
  const { type, gl = [], routes = [], } = await pg
71
72
  .query(`select user_type as type, b.gl,routes from admin.users a
@@ -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;AA4DzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,GACtB,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,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,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,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;CACpB,EACD,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE,GAAG,gBAkzBb"}
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;AA4DzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,GACtB,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,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,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,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;CACpB,EACD,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE,GAAG,gBAgzBb"}
@@ -48,11 +48,10 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
48
48
  if (!paramsTable) {
49
49
  return { message: "not enough params: table", status: 400 };
50
50
  }
51
- const paramsId = params?.id || id;
52
51
  const hookData = (await applyHook("preData", {
53
52
  pg,
54
53
  table: paramsTable,
55
- id: paramsId,
54
+ id: params?.id || id,
56
55
  user,
57
56
  }));
58
57
  if (hookData?.message && hookData?.status) {
@@ -108,10 +107,10 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
108
107
  !(called && pkey)) {
109
108
  return reply.status(404).send("template not found");
110
109
  }
111
- const id1 = tokenData?.id || hookData?.id || paramsId;
110
+ const objectId = tokenData?.id || hookData?.id || params?.id || id;
112
111
  const { actions = [], query: accessQuery } = (await getAccess({
113
112
  table: templateName,
114
- id: id1,
113
+ id: objectId,
115
114
  user,
116
115
  }, pg));
117
116
  if (!actions.includes("view") && !config?.local && !called) {
@@ -130,7 +129,6 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
130
129
  // console.warn('invalid filters in template: filter_list / filterList');
131
130
  // logger.file('crud/warning', { msg: 'invalid filters', template: templateName });
132
131
  }
133
- const objectId = tokenData?.id || hookData?.id || paramsId;
134
132
  const { list: filters = [] } = objectId
135
133
  ? {}
136
134
  : (await getFilter({
@@ -166,7 +164,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
166
164
  (!el.sql.includes("{{uid}}") || uid))
167
165
  .map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", uid)}) ${el.name || `t${i}`} on 1=1 `)
168
166
  ?.join("") || "";
169
- const cardSqlFiltered = hookData?.id || paramsId
167
+ const cardSqlFiltered = objectId
170
168
  ? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) || []
171
169
  : [];
172
170
  const cardSqlTable = cardSqlFiltered.length
@@ -191,11 +189,11 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
191
189
  ?.filter((el) => !cols.includes(el))
192
190
  .join(",")}`
193
191
  : "";
194
- if (paramsId && columnList.includes(paramsId)) {
192
+ if (objectId && columnList.includes(objectId)) {
195
193
  return gisIRColumn({
196
194
  pg,
197
195
  layer: paramsTable,
198
- column: paramsId,
196
+ column: objectId,
199
197
  sql: query.sql,
200
198
  filter: query.filter,
201
199
  search: query.search,
@@ -269,7 +267,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
269
267
  ? await handlebars.compile(params?.query)({ user, uid })
270
268
  : undefined;
271
269
  const where = [
272
- id1 ? ` "${pk}" = $1` : null,
270
+ objectId ? ` "${pk}" = $1` : null,
273
271
  keyQuery,
274
272
  loadTable?.query,
275
273
  tokenData?.query,
@@ -285,7 +283,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
285
283
  .filter(Boolean)
286
284
  .filter((el) => checkQuery(el));
287
285
  const q = `select ${pk ? `"${pk}" as id,` : ""}
288
- ${paramsId || query.key ? "*" : sqlColumns || cols || "*"}
286
+ ${objectId || query.key ? "*" : sqlColumns || cols || "*"}
289
287
  ${metaCols}
290
288
 
291
289
  ${dbColumns.filter((el) => pg.pgType?.[el.dataTypeID] === "geometry").length
@@ -299,7 +297,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
299
297
  .map((el) => `,(${el.sql})`)
300
298
  .join("") || ""} from ${table1} t ${sqlTable} ) t
301
299
 
302
- ${paramsId ? cardSqlTable : ""}
300
+ ${objectId ? cardSqlTable : ""}
303
301
  where ${where.join(" and ") || "true"}
304
302
  ${order} ${offset} limit ${limit}`.replace(/{{uid}}/g, uid);
305
303
  if (config.trace)
@@ -308,7 +306,8 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
308
306
  return q;
309
307
  }
310
308
  const { rows = [] } = await pg
311
- .query(q, (id1 ? [id1] : null) || (query.key && loadTable.key ? [query.key] : []))
309
+ .query(q, (objectId ? [objectId] : null) ||
310
+ (query.key && loadTable.key ? [query.key] : []))
312
311
  .catch((err) => {
313
312
  console.error(err.toString());
314
313
  throw err;
@@ -382,7 +381,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
382
381
  if (query.sql === "2") {
383
382
  return qCount;
384
383
  }
385
- const counts = keyQuery || id1
384
+ const counts = keyQuery || objectId
386
385
  ? { total: rows.length, filtered: rows.length }
387
386
  : await pg
388
387
  .queryCache?.(qCount, {
@@ -428,6 +427,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
428
427
  .filter((key) => index?.tokens[key]?.public ||
429
428
  actions?.includes?.("edit") ||
430
429
  actions?.includes?.("add") ||
430
+ user?.user_type === "viewer" ||
431
431
  !index?.tokens[key]?.table)
432
432
  .forEach((key) => {
433
433
  const item = index?.tokens[key];
@@ -437,7 +437,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
437
437
  item[el] = handlebarsSync.compile(item[el])({
438
438
  user,
439
439
  uid,
440
- id,
440
+ id: objectId,
441
441
  data: rows[0],
442
442
  });
443
443
  });
@@ -469,7 +469,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
469
469
  .map(async (el) => {
470
470
  const filtered1 = el.items.filter((item) => item.count?.toLowerCase?.().includes("select"));
471
471
  const data = await Promise.all(filtered1.map(async (item) => pg
472
- .query(item.count.replace(/{{id}}/g, paramsId))
472
+ .query(item.count.replace(/{{id}}/g, objectId))
473
473
  .then((item1) => item1.rows[0] || {})));
474
474
  filtered1.forEach((el1, i) => {
475
475
  // el1.title = data[i].title;
@@ -479,9 +479,9 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
479
479
  .map((item) => item.component ? components[item.component] : null)
480
480
  .filter((item) => item)
481
481
  .join(" union all ");
482
- const counts1 = q1 && id
482
+ const counts1 = q1 && objectId
483
483
  ? await pg
484
- .query(q1, [id1])
484
+ .query(q1, [objectId])
485
485
  .then((e) => e.rows.reduce((acc, curr) => Object.assign(acc, { [curr.component]: curr.count }), {}))
486
486
  : {};
487
487
  el.items
@@ -498,7 +498,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
498
498
  data: rows[0],
499
499
  user,
500
500
  uid,
501
- id: id1,
501
+ id: objectId,
502
502
  });
503
503
  const { rows: sqlData } = await pg.query(q2);
504
504
  data[el.name] = sqlData;
@@ -528,7 +528,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
528
528
  const name = el[0].substring(0, el[0].lastIndexOf("."));
529
529
  logger.file("handlebars/error", {
530
530
  table,
531
- id: paramsId,
531
+ id: objectId,
532
532
  error: err.toString(),
533
533
  stack: err.stack,
534
534
  });
@@ -602,7 +602,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
602
602
  const result = await applyHook("afterData", {
603
603
  pg,
604
604
  table: loadTable?.table || tokenData?.table,
605
- id: id1,
605
+ id: objectId,
606
606
  template: templateName,
607
607
  payload: res,
608
608
  user,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "2.0.42",
3
+ "version": "2.0.44",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [