@opengis/fastify-table 2.1.2 → 2.1.4

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.
Files changed (27) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/server/helpers/list/descriptionList.d.ts.map +1 -1
  3. package/dist/server/helpers/list/descriptionList.js +9 -5
  4. package/dist/server/plugins/auth/index.d.ts.map +1 -1
  5. package/dist/server/plugins/auth/index.js +8 -4
  6. package/dist/server/plugins/auth/onRequest.d.ts +4 -0
  7. package/dist/server/plugins/auth/onRequest.d.ts.map +1 -0
  8. package/dist/server/plugins/auth/onRequest.js +104 -0
  9. package/dist/server/plugins/crud/funcs/dataInsert.d.ts +2 -1
  10. package/dist/server/plugins/crud/funcs/dataInsert.d.ts.map +1 -1
  11. package/dist/server/plugins/crud/funcs/dataInsert.js +13 -11
  12. package/dist/server/plugins/crud/funcs/dataUpdate.d.ts +2 -1
  13. package/dist/server/plugins/crud/funcs/dataUpdate.d.ts.map +1 -1
  14. package/dist/server/plugins/crud/funcs/dataUpdate.js +13 -11
  15. package/dist/server/plugins/policy/funcs/checkAuth.d.ts +4 -0
  16. package/dist/server/plugins/policy/funcs/checkAuth.d.ts.map +1 -0
  17. package/dist/server/plugins/policy/funcs/checkAuth.js +104 -0
  18. package/dist/server/plugins/policy/funcs/checkPermissions.d.ts +4 -2
  19. package/dist/server/plugins/policy/funcs/checkPermissions.d.ts.map +1 -1
  20. package/dist/server/plugins/policy/funcs/checkPermissions.js +2 -4
  21. package/dist/server/plugins/policy/funcs/checkPolicy.d.ts +4 -2
  22. package/dist/server/plugins/policy/funcs/checkPolicy.d.ts.map +1 -1
  23. package/dist/server/plugins/policy/funcs/checkPolicy.js +8 -8
  24. package/dist/server/plugins/policy/index.d.ts +1 -1
  25. package/dist/server/plugins/policy/index.d.ts.map +1 -1
  26. package/dist/server/plugins/policy/index.js +6 -6
  27. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -111,8 +111,8 @@ function plugin(fastify) {
111
111
  // core migrations (second argument for core only)
112
112
  execMigrations(path.join(cwd, "server/migrations"), pgClients.client, true).catch((err) => console.warn(err.toString()));
113
113
  // plugins / utils / funcs
114
- policyPlugin(fastify);
115
114
  authPlugin(fastify); // fastify-auth api + hooks integrated to core
115
+ policyPlugin(fastify);
116
116
  metricPlugin();
117
117
  redisPlugin(fastify);
118
118
  pgPlugin(fastify);
@@ -1 +1 @@
1
- {"version":3,"file":"descriptionList.d.ts","sourceRoot":"","sources":["../../../../server/helpers/list/descriptionList.ts"],"names":[],"mappings":"AAkBA,wBAA8B,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,gBA8BhE"}
1
+ {"version":3,"file":"descriptionList.d.ts","sourceRoot":"","sources":["../../../../server/helpers/list/descriptionList.ts"],"names":[],"mappings":"AAkBA,wBAA8B,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,gBAkChE"}
@@ -33,11 +33,15 @@ export default async function descriptionList(data, opt) {
33
33
  continue;
34
34
  const key = keys[i + 1];
35
35
  const d1 = (await format(data[key], key, data)) || '-';
36
- result.push(`<div class="grid grid-cols-1 gap-1 py-3 sm:grid-cols-3 sm:gap-4 even:bg-gray-50 text-[12px]">
37
- <dt class="text-gray-900">${nameHBS || name}</dt>
38
- <dd class="text-gray-700 sm:col-span-2">${d1}</dd>
39
- </div>
40
- `);
36
+ result.push(`<div class="flex flex-wrap sm:grid sm:grid-cols-3 gap-1 py-3 even:bg-gray-50 text-[12px]">
37
+ <dt class="text-gray-900 w-full sm:w-auto sm:col-span-1 pr-2 break-words">
38
+ ${nameHBS || name}
39
+ </dt>
40
+
41
+ <dd class="text-gray-700 sm:col-span-2 w-full sm:w-auto break-words whitespace-normal">
42
+ ${d1}
43
+ </dd>
44
+ </div>`);
41
45
  }
42
46
  return `<dl class=" divide-y divide-gray-100 py-[5px] w-full">${result.join('')}</dl>`;
43
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAYxD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAMtD,wBAAsB,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,iBA8HxE;AAED,iBAAS,MAAM,CAAC,OAAO,EAAE,eAAe,QAgCvC;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,YAAY,EAAE,MAAM,SAAS,CAAC;AAYxD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAMtD,wBAAsB,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,iBA+HxE;AAED,iBAAS,MAAM,CAAC,OAAO,EAAE,eAAe,QAmCvC;AAED,eAAe,MAAM,CAAC"}
@@ -21,11 +21,12 @@ export async function onRequest(req, reply) {
21
21
  req.ip === "127.0.0.1" ||
22
22
  req.ip?.startsWith?.("192.168.") ||
23
23
  config.debug) &&
24
- req.headers?.token &&
25
- config.auth?.tokens?.includes?.(headers.token);
24
+ ((req.headers?.token && config.auth?.tokens?.includes?.(headers.token)) ||
25
+ process.env.NODE_ENV === "test" ||
26
+ process.env.VITEST);
26
27
  if (validToken && !req?.user?.uid) {
27
28
  req.user = {
28
- uid: req.headers?.uid?.toString?.(),
29
+ uid: req.headers?.uid?.toString?.() || "1",
29
30
  user_type: req.headers?.user_type?.toString?.() || "regular",
30
31
  };
31
32
  }
@@ -112,6 +113,10 @@ function plugin(fastify) {
112
113
  if (!config.redis) {
113
114
  return;
114
115
  }
116
+ fastify.addHook("onRequest", onRequest);
117
+ if (process.env.NODE_ENV === "test" || process.env.VITEST) {
118
+ return;
119
+ }
115
120
  fastify.register(cookie, {
116
121
  parseOptions: config?.auth?.cookieOptions || { secure: false },
117
122
  });
@@ -131,6 +136,5 @@ function plugin(fastify) {
131
136
  fastifyPassport.registerUserSerializer(async (user) => ({ user }));
132
137
  // deserialize user used to add user info from session store to req
133
138
  fastifyPassport.registerUserDeserializer(async (passport) => passport?.user || passport);
134
- fastify.addHook("onRequest", onRequest);
135
139
  }
136
140
  export default plugin;
@@ -0,0 +1,4 @@
1
+ import { FastifyReply } from "fastify";
2
+ import { ExtendedRequest } from "../../types/core.js";
3
+ export default function onRequest(req: ExtendedRequest, reply: FastifyReply): Promise<null>;
4
+ //# sourceMappingURL=onRequest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onRequest.d.ts","sourceRoot":"","sources":["../../../../server/plugins/auth/onRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAMvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAItD,wBAA8B,SAAS,CACrC,GAAG,EAAE,eAAe,EACpB,KAAK,EAAE,YAAY,iBA+HpB"}
@@ -0,0 +1,104 @@
1
+ import { existsSync } from "node:fs";
2
+ import config from "../../../config.js";
3
+ const { prefix = "/api" } = config;
4
+ export default async function onRequest(req, reply) {
5
+ const { hostname, headers, routeOptions } = req;
6
+ const { config: routeConfig, method, handler, url } = routeOptions || {};
7
+ const { policy } = routeConfig || {};
8
+ const isApi = method && url && typeof handler === "function" && url !== "*";
9
+ // handle non-api at vite/vike
10
+ if (!isApi) {
11
+ return null;
12
+ }
13
+ // proxy from old apps to editor, bi etc.
14
+ const validToken = (req.ip === "193.239.152.181" ||
15
+ req.ip === "127.0.0.1" ||
16
+ req.ip?.startsWith?.("192.168.") ||
17
+ config.debug) &&
18
+ req.headers?.token &&
19
+ config.auth?.tokens?.includes?.(headers.token);
20
+ if (validToken && !req?.user?.uid) {
21
+ req.user = {
22
+ uid: req.headers?.uid?.toString?.(),
23
+ user_type: req.headers?.user_type?.toString?.() || "regular",
24
+ };
25
+ }
26
+ const isAdmin = process.env.NODE_ENV === "admin" ||
27
+ hostname?.split?.(":")?.shift?.() === config.adminDomain ||
28
+ config.admin ||
29
+ hostname?.startsWith?.("admin");
30
+ const isPublic = Array.isArray(policy)
31
+ ? policy.includes("public")
32
+ : policy === "L0";
33
+ if (req.cookies?.["session_auth"] &&
34
+ !req.session?.passport?.user?.uid &&
35
+ (config.auth?.disable || config.auth?.user)) {
36
+ req.session = req.session || {};
37
+ req.session.passport = req.session.passport || {}; // ensure passport session exists
38
+ req.session.passport.user = {
39
+ ...(config.auth?.user || {}),
40
+ uid: config.auth?.user?.uid?.toString?.() || "1",
41
+ user_rnokpp: config.auth?.user?.rnokpp,
42
+ user_type: config.auth?.user?.type || "regular",
43
+ };
44
+ req.user = req.session.passport.user;
45
+ }
46
+ // ! intentional: null || undefined > undefined
47
+ req.user = req.user || req.session?.passport?.user || undefined; // fix for user.uid errors, by default user is null, while with express passport it was {}, unauthorized user does not trigger serializer
48
+ // currently 2factor + auth with passwd file not supported
49
+ const ispasswd = (existsSync("passwd") && !config.auth?.["2factor"]) || config.auth?.passwd;
50
+ const loginPageUrl = config.auth?.link?.core?.login || config?.auth?.redirect || "/login";
51
+ if (!req.user?.uid &&
52
+ !config.auth?.disable &&
53
+ isAdmin &&
54
+ !isPublic &&
55
+ !config.auth?.disableRedirect &&
56
+ !req.url.startsWith(prefix) &&
57
+ !req.url.startsWith("/api") &&
58
+ !req.url.includes(loginPageUrl) &&
59
+ !req.url.includes(".") &&
60
+ !req.url.includes("@")) {
61
+ if (isApi) {
62
+ return reply.status(401).send({ error: "unauthorized", code: 401 });
63
+ }
64
+ return reply.redirect(`${loginPageUrl}` + `?redirect=${req.url}`);
65
+ }
66
+ // by default, disable 2factor for id.gov.ua auth
67
+ const check = req.user?.auth_type === "govid" ? config.auth?.["2factor"]?.govid : true;
68
+ const login2faPage = config.auth?.link?.["2fa"]?.login || "/2factor";
69
+ // example: 2factor for admin env only, while public env does not require it
70
+ const checkEnv = () => {
71
+ if (!config.auth?.["2factorEnv"])
72
+ return true;
73
+ if ((config.auth?.["2factorEnv"] &&
74
+ process.env.NODE_ENV === config.auth?.["2factorEnv"]) ||
75
+ (config.auth?.["2factorEnv"] === "admin" && isAdmin)) {
76
+ return true;
77
+ }
78
+ return false;
79
+ };
80
+ // if 2factor is enabled globally + for user and secondFactorPassed not true => redirect to 2factor login page
81
+ if (req.user?.uid &&
82
+ req.user?.twofa &&
83
+ // config.auth?.["2factor"] &&
84
+ // !isPublic &&
85
+ (routeOptions?.method || "GET") === "GET" &&
86
+ !req.session?.secondFactorPassed &&
87
+ !ispasswd &&
88
+ !config.auth?.disableRedirect &&
89
+ !config.auth?.disable &&
90
+ check &&
91
+ checkEnv() &&
92
+ !req.url.startsWith(login2faPage) &&
93
+ !routeOptions.url?.includes?.("/logout") &&
94
+ !routeOptions.url?.includes?.("/2fa") &&
95
+ !routeOptions.url?.includes?.("/assets")) {
96
+ if (isApi) {
97
+ return reply
98
+ .status(403)
99
+ .send({ error: "access restricted: twofa", code: 403 });
100
+ }
101
+ return reply.redirect(login2faPage);
102
+ }
103
+ return null;
104
+ }
@@ -1,5 +1,5 @@
1
1
  import type { ExtendedPG } from "../../../types/core.js";
2
- export default function dataInsert({ id, table: table1, referer, data, pg: pg1, uid, tokenData, }: {
2
+ export default function dataInsert({ id, table: table1, referer, data, pg: pg1, uid, tokenData, log, }: {
3
3
  id?: string | number;
4
4
  table: string;
5
5
  referer?: string;
@@ -7,5 +7,6 @@ export default function dataInsert({ id, table: table1, referer, data, pg: pg1,
7
7
  pg?: ExtendedPG;
8
8
  uid?: string;
9
9
  tokenData?: Record<string, any>;
10
+ log?: Boolean;
10
11
  }): Promise<any>;
11
12
  //# sourceMappingURL=dataInsert.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataInsert.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataInsert.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAgBzD,wBAA8B,UAAU,CAAC,EACvC,EAAE,EACF,KAAK,EAAE,MAAM,EACb,OAAO,EACP,IAAI,EACJ,EAAE,EAAE,GAAG,EACP,GAAG,EACH,SAAc,GACf,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC,gBAoKA"}
1
+ {"version":3,"file":"dataInsert.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataInsert.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAgBzD,wBAA8B,UAAU,CAAC,EACvC,EAAE,EACF,KAAK,EAAE,MAAM,EACb,OAAO,EACP,IAAI,EACJ,EAAE,EAAE,GAAG,EACP,GAAG,EACH,SAAc,EACd,GAAU,GACX,EAAE;IACD,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,gBAsKA"}
@@ -9,7 +9,7 @@ import logger from "../../logger/getLogger.js";
9
9
  import extraData from "../../extra/extraData.js";
10
10
  import getMeta from "../../pg/funcs/getMeta.js";
11
11
  const rclient = getRedis();
12
- export default async function dataInsert({ id, table: table1, referer, data, pg: pg1, uid, tokenData = {}, }) {
12
+ export default async function dataInsert({ id, table: table1, referer, data, pg: pg1, uid, tokenData = {}, log = true, }) {
13
13
  const pg = pg1 || getPG({ name: "client" });
14
14
  if (!pg) {
15
15
  return null;
@@ -95,16 +95,18 @@ export default async function dataInsert({ id, table: table1, referer, data, pg:
95
95
  Object.assign(res.rows[0], { [key]: parentRows.filter(Boolean) });
96
96
  }));
97
97
  }
98
- await logChanges({
99
- pg: client,
100
- table,
101
- tokenData,
102
- referer,
103
- data,
104
- id: id1,
105
- uid,
106
- type: "INSERT",
107
- });
98
+ if (log) {
99
+ await logChanges({
100
+ pg: client,
101
+ table,
102
+ tokenData,
103
+ referer,
104
+ data,
105
+ id: id1,
106
+ uid,
107
+ type: "INSERT",
108
+ });
109
+ }
108
110
  if (config.redis && rclient?.status !== "end") {
109
111
  rclient.incr(`pg:${client.options?.database}:${table}:crud`);
110
112
  }
@@ -1,5 +1,5 @@
1
1
  import { ExtendedPG } from "../../../types/core.js";
2
- export default function dataUpdate({ table: table1, tokenData, referer, id, data, pg: pg1, uid, }: {
2
+ export default function dataUpdate({ table: table1, tokenData, referer, id, data, pg: pg1, uid, log, }: {
3
3
  table: string;
4
4
  tokenData?: Record<string, any>;
5
5
  referer?: string;
@@ -7,5 +7,6 @@ export default function dataUpdate({ table: table1, tokenData, referer, id, data
7
7
  data: Record<string, any>;
8
8
  pg?: ExtendedPG;
9
9
  uid?: string;
10
+ log?: Boolean;
10
11
  }): Promise<any>;
11
12
  //# sourceMappingURL=dataUpdate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataUpdate.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataUpdate.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAepD,wBAA8B,UAAU,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,IAAI,EACJ,EAAE,EAAE,GAAG,EACP,GAAG,GACJ,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,gBAsPA"}
1
+ {"version":3,"file":"dataUpdate.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataUpdate.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAepD,wBAA8B,UAAU,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,IAAI,EACJ,EAAE,EAAE,GAAG,EACP,GAAG,EACH,GAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,gBAwPA"}
@@ -19,7 +19,7 @@ function assignValue(key, i, srid = 4326, columnType = "text") {
19
19
  }
20
20
  return `"${key}"=$${i + 2}`;
21
21
  }
22
- export default async function dataUpdate({ table: table1, tokenData, referer, id, data, pg: pg1, uid, }) {
22
+ export default async function dataUpdate({ table: table1, tokenData, referer, id, data, pg: pg1, uid, log = true, }) {
23
23
  if (!data || !table1 || !id) {
24
24
  return null;
25
25
  }
@@ -161,16 +161,18 @@ export default async function dataUpdate({ table: table1, tokenData, referer, id
161
161
  }
162
162
  }));
163
163
  }
164
- await logChanges({
165
- pg,
166
- table,
167
- tokenData,
168
- referer,
169
- data,
170
- id,
171
- uid,
172
- type: "UPDATE",
173
- });
164
+ if (log) {
165
+ await logChanges({
166
+ pg: client,
167
+ table,
168
+ tokenData,
169
+ referer,
170
+ data,
171
+ id,
172
+ uid,
173
+ type: "UPDATE",
174
+ });
175
+ }
174
176
  if (config.redis && rclient?.status !== "end") {
175
177
  rclient.incr(`pg:${client.options?.database}:${table}:crud`);
176
178
  }
@@ -0,0 +1,4 @@
1
+ import { FastifyReply } from "fastify";
2
+ import { ExtendedRequest } from "../../../types/core.js";
3
+ export default function onRequest(req: ExtendedRequest, reply: FastifyReply): Promise<null>;
4
+ //# sourceMappingURL=checkAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkAuth.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAMvC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD,wBAA8B,SAAS,CACrC,GAAG,EAAE,eAAe,EACpB,KAAK,EAAE,YAAY,iBA+HpB"}
@@ -0,0 +1,104 @@
1
+ import { existsSync } from "node:fs";
2
+ import config from "../../../../config.js";
3
+ const { prefix = "/api" } = config;
4
+ export default async function onRequest(req, reply) {
5
+ const { hostname, headers, routeOptions } = req;
6
+ const { config: routeConfig, method, handler, url } = routeOptions || {};
7
+ const { policy } = routeConfig || {};
8
+ const isApi = method && url && typeof handler === "function" && url !== "*";
9
+ // handle non-api at vite/vike
10
+ if (!isApi) {
11
+ return null;
12
+ }
13
+ // proxy from old apps to editor, bi etc.
14
+ const validToken = (req.ip === "193.239.152.181" ||
15
+ req.ip === "127.0.0.1" ||
16
+ req.ip?.startsWith?.("192.168.") ||
17
+ config.debug) &&
18
+ req.headers?.token &&
19
+ config.auth?.tokens?.includes?.(headers.token);
20
+ if (validToken && !req?.user?.uid) {
21
+ req.user = {
22
+ uid: req.headers?.uid?.toString?.(),
23
+ user_type: req.headers?.user_type?.toString?.() || "regular",
24
+ };
25
+ }
26
+ const isAdmin = process.env.NODE_ENV === "admin" ||
27
+ hostname?.split?.(":")?.shift?.() === config.adminDomain ||
28
+ config.admin ||
29
+ hostname?.startsWith?.("admin");
30
+ const isPublic = Array.isArray(policy)
31
+ ? policy.includes("public")
32
+ : policy === "L0";
33
+ if (req.cookies?.["session_auth"] &&
34
+ !req.session?.passport?.user?.uid &&
35
+ (config.auth?.disable || config.auth?.user)) {
36
+ req.session = req.session || {};
37
+ req.session.passport = req.session.passport || {}; // ensure passport session exists
38
+ req.session.passport.user = {
39
+ ...(config.auth?.user || {}),
40
+ uid: config.auth?.user?.uid?.toString?.() || "1",
41
+ user_rnokpp: config.auth?.user?.rnokpp,
42
+ user_type: config.auth?.user?.type || "regular",
43
+ };
44
+ req.user = req.session.passport.user;
45
+ }
46
+ // ! intentional: null || undefined > undefined
47
+ req.user = req.user || req.session?.passport?.user || undefined; // fix for user.uid errors, by default user is null, while with express passport it was {}, unauthorized user does not trigger serializer
48
+ // currently 2factor + auth with passwd file not supported
49
+ const ispasswd = (existsSync("passwd") && !config.auth?.["2factor"]) || config.auth?.passwd;
50
+ const loginPageUrl = config.auth?.link?.core?.login || config?.auth?.redirect || "/login";
51
+ if (!req.user?.uid &&
52
+ !config.auth?.disable &&
53
+ isAdmin &&
54
+ !isPublic &&
55
+ !config.auth?.disableRedirect &&
56
+ !req.url.startsWith(prefix) &&
57
+ !req.url.startsWith("/api") &&
58
+ !req.url.includes(loginPageUrl) &&
59
+ !req.url.includes(".") &&
60
+ !req.url.includes("@")) {
61
+ if (isApi) {
62
+ return reply.status(401).send({ error: "unauthorized", code: 401 });
63
+ }
64
+ return reply.redirect(`${loginPageUrl}` + `?redirect=${req.url}`);
65
+ }
66
+ // by default, disable 2factor for id.gov.ua auth
67
+ const check = req.user?.auth_type === "govid" ? config.auth?.["2factor"]?.govid : true;
68
+ const login2faPage = config.auth?.link?.["2fa"]?.login || "/2factor";
69
+ // example: 2factor for admin env only, while public env does not require it
70
+ const checkEnv = () => {
71
+ if (!config.auth?.["2factorEnv"])
72
+ return true;
73
+ if ((config.auth?.["2factorEnv"] &&
74
+ process.env.NODE_ENV === config.auth?.["2factorEnv"]) ||
75
+ (config.auth?.["2factorEnv"] === "admin" && isAdmin)) {
76
+ return true;
77
+ }
78
+ return false;
79
+ };
80
+ // if 2factor is enabled globally + for user and secondFactorPassed not true => redirect to 2factor login page
81
+ if (req.user?.uid &&
82
+ req.user?.twofa &&
83
+ // config.auth?.["2factor"] &&
84
+ // !isPublic &&
85
+ (routeOptions?.method || "GET") === "GET" &&
86
+ !req.session?.secondFactorPassed &&
87
+ !ispasswd &&
88
+ !config.auth?.disableRedirect &&
89
+ !config.auth?.disable &&
90
+ check &&
91
+ checkEnv() &&
92
+ !req.url.startsWith(login2faPage) &&
93
+ !routeOptions.url?.includes?.("/logout") &&
94
+ !routeOptions.url?.includes?.("/2fa") &&
95
+ !routeOptions.url?.includes?.("/assets")) {
96
+ if (isApi) {
97
+ return reply
98
+ .status(403)
99
+ .send({ error: "access restricted: twofa", code: 403 });
100
+ }
101
+ return reply.redirect(login2faPage);
102
+ }
103
+ return null;
104
+ }
@@ -1,4 +1,6 @@
1
- import type { FastifyReply } from "fastify";
2
1
  import type { ExtendedRequest } from "../../../types/core.js";
3
- export default function checkPermissions(req: ExtendedRequest, reply: FastifyReply): Promise<null>;
2
+ export default function checkPermissions(req: ExtendedRequest): Promise<{
3
+ error: string;
4
+ code: number;
5
+ } | null>;
4
6
  //# sourceMappingURL=checkPermissions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkPermissions.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPermissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAMhC,wBAA8B,gBAAgB,CAC5C,GAAG,EAAE,eAAe,EACpB,KAAK,EAAE,YAAY,iBAkEpB"}
1
+ {"version":3,"file":"checkPermissions.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPermissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAMhC,wBAA8B,gBAAgB,CAAC,GAAG,EAAE,eAAe;;;UA+DlE"}
@@ -1,7 +1,7 @@
1
1
  import logger from "../../logger/getLogger.js";
2
2
  import getUserPermissions from "../../access/funcs/getUserPermissions.js";
3
3
  import pgClients from "../../pg/pgClients.js";
4
- export default async function checkPermissions(req, reply) {
4
+ export default async function checkPermissions(req) {
5
5
  const { originalUrl: path, query, params, method, routeOptions, pg = pgClients.client, } = req;
6
6
  const user = req.user || req.session?.passport?.user;
7
7
  const body = req.body
@@ -31,9 +31,7 @@ export default async function checkPermissions(req, reply) {
31
31
  message: "access restricted: permissions",
32
32
  uid: user?.uid,
33
33
  });
34
- return reply
35
- .status(403)
36
- .send({ error: "access restricted: permissions", code: 403 });
34
+ return { error: "access restricted: permissions", code: 403 };
37
35
  }
38
36
  return null;
39
37
  }
@@ -1,4 +1,6 @@
1
- import type { FastifyReply } from "fastify";
2
1
  import type { ExtendedRequest } from "../../../types/core.js";
3
- export default function checkPolicy(req: ExtendedRequest, reply: FastifyReply): FastifyReply<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, unknown, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown> | null;
2
+ export default function checkPolicy(req: ExtendedRequest): {
3
+ error: string;
4
+ code: number;
5
+ } | null;
4
6
  //# sourceMappingURL=checkPolicy.d.ts.map
@@ -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,oSAoK5E"}
1
+ {"version":3,"file":"checkPolicy.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAKhC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,GAAG,EAAE,eAAe;;;SAoKvD"}
@@ -1,6 +1,6 @@
1
1
  import { config, logger } from "../../../../utils.js";
2
2
  import block from "../sqlInjection.js";
3
- export default function checkPolicy(req, reply) {
3
+ export default function checkPolicy(req) {
4
4
  const { originalUrl: path, hostname, query, params, headers, method, routeOptions, } = req;
5
5
  const user = req.user || req.session?.passport?.user;
6
6
  const body = req.body
@@ -31,7 +31,7 @@ export default function checkPolicy(req, reply) {
31
31
  method,
32
32
  userRole: user.user_type,
33
33
  });
34
- return reply.status(403).send({ error: "access restricted: 0", code: 403 });
34
+ return { error: "access restricted: 0", code: 403 };
35
35
  }
36
36
  // ! role
37
37
  if (isRole) {
@@ -45,7 +45,7 @@ export default function checkPolicy(req, reply) {
45
45
  body,
46
46
  uid: user?.uid,
47
47
  });
48
- return reply.status(403).send({ error: "access restricted: 0", code: 403 });
48
+ return { error: "access restricted: 0", code: 403 };
49
49
  }
50
50
  // ! file injection
51
51
  if (JSON.stringify(params || {})?.includes("../") ||
@@ -59,7 +59,7 @@ export default function checkPolicy(req, reply) {
59
59
  body,
60
60
  uid: user?.uid,
61
61
  });
62
- return reply.status(409).send({ error: "access restricted: 1", code: 409 });
62
+ return { error: "access restricted: 1", code: 409 };
63
63
  }
64
64
  // ! invalid file extension
65
65
  if (path.includes("files/") && allowExtPublic.includes(ext)) {
@@ -77,7 +77,7 @@ export default function checkPolicy(req, reply) {
77
77
  stopWords,
78
78
  uid: user?.uid,
79
79
  });
80
- return reply.status(409).send({ error: "access restricted: 2", code: 409 });
80
+ return { error: "access restricted: 2", code: 409 };
81
81
  }
82
82
  // ! user required, but not logged in
83
83
  if (requireUser && !user) {
@@ -88,7 +88,7 @@ export default function checkPolicy(req, reply) {
88
88
  query,
89
89
  body,
90
90
  });
91
- return reply.status(401).send({ error: "access restricted: 3", code: 401 });
91
+ return { error: "access restricted: 3", code: 401 };
92
92
  }
93
93
  // ! referer
94
94
  if (requireReferer && !headers?.referer?.includes?.(hostname)) {
@@ -100,7 +100,7 @@ export default function checkPolicy(req, reply) {
100
100
  body,
101
101
  uid: user?.uid,
102
102
  });
103
- return reply.status(403).send({ error: "access restricted: 4", code: 403 });
103
+ return { error: "access restricted: 4", code: 403 };
104
104
  }
105
105
  // ! public / token
106
106
  if (isPublic || config.debug) {
@@ -120,7 +120,7 @@ export default function checkPolicy(req, reply) {
120
120
  message: "access restricted: 6",
121
121
  uid: user?.uid,
122
122
  });
123
- return reply.status(403).send({ error: "access restricted: 6", code: 403 });
123
+ return { error: "access restricted: 6", code: 403 };
124
124
  }
125
125
  return null;
126
126
  }
@@ -1,3 +1,3 @@
1
- declare function plugin(fastify: any): Promise<void>;
1
+ declare function plugin(fastify: any): void;
2
2
  export default plugin;
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/policy/index.ts"],"names":[],"mappings":"AAKA,iBAAe,MAAM,CAAC,OAAO,EAAE,GAAG,iBAkCjC;AAED,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/policy/index.ts"],"names":[],"mappings":"AAKA,iBAAS,MAAM,CAAC,OAAO,EAAE,GAAG,QAiC3B;AAED,eAAe,MAAM,CAAC"}
@@ -1,8 +1,8 @@
1
1
  import config from "../../../config.js";
2
2
  import checkPolicy from "./funcs/checkPolicy.js";
3
3
  import checkPermissions from "./funcs/checkPermissions.js";
4
- async function plugin(fastify) {
5
- fastify.addHook("preParsing", async (request, reply) => {
4
+ function plugin(fastify) {
5
+ fastify.addHook("preHandler", async (request, reply) => {
6
6
  // ! skip locally, skip tests
7
7
  if ((process.env.local === "true" || process.env.NODE_ENV === "test") &&
8
8
  !config.debugAuth &&
@@ -18,13 +18,13 @@ async function plugin(fastify) {
18
18
  if (!isApi) {
19
19
  return null;
20
20
  }
21
- const resp1 = await checkPermissions(request, reply);
21
+ const resp1 = await checkPermissions(request);
22
22
  if (resp1) {
23
- return resp1;
23
+ return reply.status(resp1.code || 403).send(resp1);
24
24
  }
25
- const resp = checkPolicy(request, reply);
25
+ const resp = checkPolicy(request);
26
26
  if (resp) {
27
- return resp;
27
+ return reply.status(resp.code || 403).send(resp);
28
28
  }
29
29
  return null;
30
30
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [