@opengis/fastify-table 2.0.1 → 2.0.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.js CHANGED
@@ -1,3 +1,4 @@
1
+ import fp from "fastify-plugin";
1
2
  import path from "node:path";
2
3
  import { existsSync, readdirSync, readFileSync } from "node:fs";
3
4
  import { fileURLToPath } from "node:url";
@@ -16,32 +17,20 @@ import metricPlugin from "./server/plugins/metric/index.js";
16
17
  import redisPlugin from "./server/plugins/redis/index.js";
17
18
  import loggerPlugin from "./server/plugins/logger/index.js";
18
19
  import authPlugin from "./server/plugins/auth/index.js";
19
- // routes
20
- import cronRoutes from "./server/routes/cron/index.js";
21
- import crudRoutes from "./server/routes/crud/index.js";
22
- import loggerRoutes from "./server/routes/logger/index.js";
23
- import propertiesRoutes from "./server/routes/properties/index.js";
24
- import tableRoutes from "./server/routes/table/index.js";
25
- import utilRoutes from "./server/routes/util/index.js";
26
- import accessRoutes from "./server/routes/access/index.js";
27
20
  // utils
28
21
  import addTemplateDir from "./server/plugins/table/funcs/addTemplateDir.js";
29
22
  import execMigrations from "./server/plugins/migration/exec.migrations.js";
30
23
  import locales from "./server/routes/table/controllers/utils/locales.js";
31
24
  import pgClients from "./server/plugins/pg/pgClients.js";
32
- import dblistRoutes from "./server/routes/dblist/index.js";
33
- import menuRoutes from "./server/routes/menu/index.js";
34
- import templatesRoutes from "./server/routes/templates/index.js";
35
- import widgetRoutes from "./server/routes/widget/index.js";
36
- import authRoutes from "./server/routes/auth/index.js";
37
25
  // core templates && cls
38
26
  const filename = fileURLToPath(import.meta.url);
39
27
  const cwd = path.dirname(filename);
40
28
  async function plugin(fastify, opt) {
41
- config.pg = opt.pg;
42
- config.redis = opt.redis;
43
- config.root = opt.root;
44
- config.mapServerRoot = opt.mapServerRoot;
29
+ const prefix = opt.prefix ?? "/api";
30
+ config.pg = opt.pg || config.pg;
31
+ config.redis = opt.redis || config.redis;
32
+ config.root = opt.root || config.root;
33
+ config.mapServerRoot = opt.mapServerRoot || config.mapServerRoot;
45
34
  // fastify.register(import('@fastify/sensible'), {
46
35
  // errorHandler: false,
47
36
  // });
@@ -80,15 +69,16 @@ async function plugin(fastify, opt) {
80
69
  // core templates && cls
81
70
  config.templates?.forEach((el) => addTemplateDir(el));
82
71
  addTemplateDir(path.join(cwd, "module/core"));
83
- // plugins / utils / funcs
84
- policyPlugin(fastify);
85
- await authPlugin(fastify, config); // fastify-auth api + hooks integrated to core
72
+ // plugins
73
+ policyPlugin(fastify); // !first
74
+ // ! fastify-auth api + hooks integrated to core
75
+ await authPlugin(fastify); // ! session, before any route
86
76
  metricPlugin();
87
77
  redisPlugin(fastify);
88
- await pgPlugin(fastify, opt);
89
- await sqlitePlugin(fastify, opt);
78
+ await pgPlugin(fastify);
79
+ await sqlitePlugin(fastify);
90
80
  cronPlugin();
91
- loggerPlugin(fastify, opt);
81
+ loggerPlugin(fastify);
92
82
  if (config.rateLimit !== false) {
93
83
  await fastify.register(import("@fastify/rate-limit"), {
94
84
  max: parseInt(config.rateLimit?.max || 100),
@@ -98,29 +88,30 @@ async function plugin(fastify, opt) {
98
88
  keyGenerator: (req) => `${req.ip}-${req.raw.url.split("?")[0]}`,
99
89
  });
100
90
  }
91
+ // routes / api
101
92
  if (config.dblist) {
102
- dblistRoutes(fastify);
93
+ fastify.register(import("./server/routes/dblist/index.js")); // ! without prefix
103
94
  }
104
- // routes / api
105
- cronRoutes(fastify);
106
- crudRoutes(fastify);
107
- loggerRoutes(fastify);
108
- propertiesRoutes(fastify);
109
- tableRoutes(fastify, opt);
110
- utilRoutes(fastify);
111
- accessRoutes(fastify, opt);
112
- widgetRoutes(fastify, opt);
113
- menuRoutes(fastify, opt);
114
- templatesRoutes(fastify, opt);
115
- authRoutes(fastify, opt); // from fastify-auth
116
- // from fastify-file
95
+ fastify.register(import("./server/routes/cron/index.js"), { prefix });
96
+ fastify.register(import("./server/routes/crud/index.js"), { prefix });
97
+ fastify.register(import("./server/routes/logger/index.js")); // ! without prefix
98
+ fastify.register(import("./server/routes/properties/index.js"), { prefix });
99
+ fastify.register(import("./server/routes/table/index.js"), { prefix });
100
+ fastify.register(import("./server/routes/util/index.js"), { prefix });
101
+ fastify.register(import("./server/routes/access/index.js"), { prefix });
102
+ fastify.register(import("./server/routes/menu/index.js"), { prefix });
103
+ fastify.register(import("./server/routes/templates/index.js"), { prefix });
104
+ fastify.register(import("./server/routes/widget/index.js"), { prefix });
105
+ // ! from fastify-auth, without prefix
106
+ fastify.register(import("./server/routes/auth/index.js"));
107
+ // ! from fastify-file, without prefix
117
108
  await fastify.register(import("@fastify/multipart"), {
118
109
  limits: {
119
110
  fileSize: maxFileSize * 1024 * 1024,
120
111
  },
121
112
  }); // content parser, await before adding upload routes
122
- fastify.register(import("./server/routes/file/index.js"), opt);
123
- fastify.register(import("./server/routes/grpc/index.js"), opt);
113
+ fastify.register(import("./server/routes/file/index.js"));
114
+ fastify.register(import("./server/routes/grpc/index.js"));
124
115
  config.proxy?.forEach?.((el) => {
125
116
  if (execName === "bun") {
126
117
  fastify.all(`${el.source}/*`, async (req, reply) => {
@@ -166,4 +157,4 @@ async function plugin(fastify, opt) {
166
157
  }
167
158
  });
168
159
  }
169
- export default plugin;
160
+ export default fp(plugin);
@@ -51,13 +51,18 @@ export default async function authorizeUser(user, req, loginType = "login", expi
51
51
  if (req.method === "POST") {
52
52
  return { message: "ok", status: "200" };
53
53
  }
54
+ const redirectUrl = req.headers?.referer?.match?.(/[?&]redirect=([^&]+)/)?.[1] || "/";
55
+ if (config.auth?.["2factor"]) {
56
+ return ("/2factor?redirect=" +
57
+ (href ||
58
+ config.auth?.redirectAfter ||
59
+ (redirectUrl.startsWith("/") ? redirectUrl : "/")));
60
+ }
54
61
  if (href) {
55
62
  return href;
56
63
  }
57
64
  if (config.auth?.redirectAfter) {
58
65
  return config.auth?.redirectAfter;
59
66
  }
60
- const redirectUrl = req.headers?.referer?.match?.(/[?&]redirect=([^&]+)/)?.[1] || "/";
61
- // logger.debug('login', { redirect, ref: headers?.referer, sid: req.sid });
62
67
  return redirectUrl.startsWith("/") ? redirectUrl : "/";
63
68
  }
@@ -1,24 +1,23 @@
1
- // import fp from "fastify-plugin";
1
+ import { existsSync } from "node:fs";
2
2
  import cookie from "@fastify/cookie";
3
3
  import session from "@fastify/session";
4
- // import fastifyPassport from "@fastify/passport";
5
4
  import { Authenticator } from "@fastify/passport";
6
5
  import RedisStore from "fastify-session-redis-store";
7
6
  import config from "../../../config.js";
8
7
  import getRedis from "../redis/funcs/getRedis.js";
9
8
  const fastifyPassport = new Authenticator();
10
9
  const { prefix = "/api" } = config;
11
- async function plugin(fastify, opt = config) {
12
- if (!opt.redis) {
10
+ async function plugin(fastify) {
11
+ if (!config.redis) {
13
12
  return;
14
13
  }
15
14
  await fastify.register(cookie, {
16
- parseOptions: opt?.auth?.cookieOptions || { secure: false },
15
+ parseOptions: config?.auth?.cookieOptions || { secure: false },
17
16
  });
18
17
  await fastify.register(session, {
19
- secret: opt?.auth?.secret || "61b820e12858570a4b0633020d4394a17903d9a9",
18
+ secret: config?.auth?.secret || "61b820e12858570a4b0633020d4394a17903d9a9",
20
19
  cookieName: "session_auth",
21
- cookie: opt?.auth?.cookieOptions || { secure: false },
20
+ cookie: config?.auth?.cookieOptions || { secure: false },
22
21
  store: new RedisStore({ client: getRedis({ db: 10 }) }),
23
22
  });
24
23
  // register passport AFTER session is ready
@@ -51,8 +50,8 @@ async function plugin(fastify, opt = config) {
51
50
  const isPublic = Array.isArray(policy)
52
51
  ? policy.includes("public")
53
52
  : policy === "L0";
54
- // if 2factor is enabled and secondFactor not true => redirect to 2factor login page
55
- const { secondFactor, passport = {} } = req.session || {}; // base login +
53
+ // if 2factor is enabled globally + for user and secondFactorPassed not true => redirect to 2factor login page
54
+ const { secondFactorPassed, passport = {} } = req.session || {}; // base login +
56
55
  if (!passport.user?.uid &&
57
56
  (config.auth?.disable || config.auth?.user) &&
58
57
  !isPublic) {
@@ -73,7 +72,8 @@ async function plugin(fastify, opt = config) {
73
72
  console.log("req.user?.uid", req.user?.uid, "req.session?.passport?.user?.uid", req.session?.passport?.user?.uid, "config.auth", config.auth);
74
73
  }
75
74
  // currently 2factor + auth with passwd file not supported
76
- const ispasswd = !pg?.pk?.["admin.users"] || config.auth?.passwd;
75
+ const ispasswd = (existsSync("passwd") && !config.auth?.["2factor"]) ||
76
+ config.auth?.passwd;
77
77
  if (!passport.user?.uid &&
78
78
  !config.auth?.disable &&
79
79
  isAdmin &&
@@ -84,24 +84,15 @@ async function plugin(fastify, opt = config) {
84
84
  return reply.redirect(`${config?.auth?.redirect || "/login"}` + `?redirect=${req.url}`);
85
85
  }
86
86
  if (passport.user?.uid &&
87
- !config.auth?.disable &&
87
+ passport.user?.twofa &&
88
88
  config.auth?.["2factor"] &&
89
- isAdmin &&
89
+ !isPublic &&
90
90
  (routeOptions?.method || "GET") === "GET" &&
91
- !secondFactor &&
91
+ !secondFactorPassed &&
92
92
  !ispasswd) {
93
- if (![
94
- "/logout",
95
- "/2factor",
96
- "/2factor?recovery=1",
97
- "/2factor/verify",
98
- "/2factor/recovery",
99
- "/user",
100
- config.auth?.["2factorRedirect"],
101
- ]
102
- .filter((el) => el)
103
- .includes(req.url)) {
104
- return reply.redirect(config.auth?.["2factorRedirect"] || "/2factor");
93
+ const href = config.auth?.["2factorRedirect"] || "/2factor";
94
+ if (!href.includes(req.url)) {
95
+ return reply.redirect(href);
105
96
  }
106
97
  }
107
98
  return null;
@@ -1,7 +1,7 @@
1
1
  import errorMessage from "./errorMessage.js";
2
2
  import logger from "./getLogger.js";
3
3
  import pgClients from "../pg/pgClients.js";
4
- async function plugin(fastify, opt) {
4
+ async function plugin(fastify) {
5
5
  fastify.addHook("onResponse", async (req, reply) => {
6
6
  if (reply?.statusCode && reply.statusCode >= 400) {
7
7
  logger.metrics(`error-count:${reply.statusCode}`);
@@ -1,3 +1,4 @@
1
+ import config from "../../../config.js";
1
2
  import pgClients from "./pgClients.js";
2
3
  import getPGAsync from "./funcs/getPGAsync.js";
3
4
  import logger from "../logger/getLogger.js";
@@ -6,7 +7,7 @@ function close() {
6
7
  pgClients[el].end();
7
8
  });
8
9
  }
9
- async function getHeadersPG(req, config) {
10
+ async function getHeadersPG(req) {
10
11
  if (!req.headers?.token)
11
12
  return null;
12
13
  const validToken = (req.ip === "193.239.152.181" ||
@@ -21,10 +22,10 @@ async function getHeadersPG(req, config) {
21
22
  }
22
23
  return null;
23
24
  }
24
- async function plugin(fastify, config) {
25
+ async function plugin(fastify) {
25
26
  const client = await getPGAsync({ ...(config.pg || {}), name: "client" });
26
27
  fastify.addHook("onRequest", async (req) => {
27
- const headersPG = await getHeadersPG(req, config);
28
+ const headersPG = await getHeadersPG(req);
28
29
  req.pg = headersPG || req.pg || client || pgClients.client;
29
30
  if (headersPG) {
30
31
  req.user = { uid: req.headers?.uid };
@@ -1,6 +1,6 @@
1
1
  import fp from "fastify-plugin";
2
2
  import sqliteClients from "./sqliteClients.js";
3
- async function dbPlugin(app, opt) {
3
+ async function dbPlugin(app) {
4
4
  app.addHook("onClose", async () => {
5
5
  Object.keys(sqliteClients).forEach((key) => sqliteClients[key].close());
6
6
  });
@@ -2,9 +2,8 @@ import accessGroup from "./controllers/access.group.js";
2
2
  import accessGroupPost from "./controllers/access.group.post.js";
3
3
  import accessInterface from "./controllers/access.interface.js";
4
4
  import { accessGroupPostSchema, accessGroupSchema, accessInterfaceSchema, } from "./schema.js";
5
- export default async function route(fastify, config = {}) {
6
- const { prefix = "/api" } = config;
7
- fastify.get(`${prefix}/access-group/:id`, { schema: accessGroupSchema }, accessGroup);
8
- fastify.post(`${prefix}/access-group/:id`, { schema: accessGroupPostSchema }, accessGroupPost);
9
- fastify.get(`${prefix}/access-interface/:name`, { schema: accessInterfaceSchema }, accessInterface);
5
+ export default async function route(fastify, opt = {}) {
6
+ fastify.get("/access-group/:id", { schema: accessGroupSchema }, accessGroup);
7
+ fastify.post("/access-group/:id", { schema: accessGroupPostSchema }, accessGroupPost);
8
+ fastify.get("/access-interface/:name", { schema: accessInterfaceSchema }, accessInterface);
10
9
  }
@@ -1,13 +1,13 @@
1
- import path from 'node:path';
2
- import { fileURLToPath } from 'url';
3
- import { readFile } from 'node:fs/promises';
4
- import config from '../../../../../config.js';
5
- import getTemplate from '../../../../plugins/table/funcs/getTemplate.js';
6
- import pgClients from '../../../../plugins/pg/pgClients.js';
7
- import { handlebars } from '../../../../helpers/index.js';
8
- import { verify, enableSecret } from './providers/totp.js';
9
- import sendNotification from '../../../../plugins/auth/funcs/sendNotification.js';
10
- const template = 'recovery-codes-email-template';
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "url";
3
+ import { readFile } from "node:fs/promises";
4
+ import config from "../../../../../config.js";
5
+ import getTemplate from "../../../../plugins/table/funcs/getTemplate.js";
6
+ import pgClients from "../../../../plugins/pg/pgClients.js";
7
+ import { handlebars } from "../../../../helpers/index.js";
8
+ import { verify, enableSecret } from "./providers/totp.js";
9
+ import sendNotification from "../../../../plugins/auth/funcs/sendNotification.js";
10
+ const template = "recovery-codes-email-template";
11
11
  const dirname = path.dirname(fileURLToPath(import.meta.url));
12
12
  /**
13
13
  * Перевірка двохфакторної авторизації для користувача
@@ -27,31 +27,39 @@ const dirname = path.dirname(fileURLToPath(import.meta.url));
27
27
  * @returns {String} redirect Шлях до переадресації
28
28
  */
29
29
  export default async function verifyFunction(req, reply) {
30
- const { pg = pgClients.client, session = {}, body = {}, query = {}, } = req;
30
+ const { pg = pgClients.client, session = {}, body = {} } = req;
31
31
  const { uid, email } = session?.passport?.user || {};
32
32
  // const { nocache = config.local } = query;
33
33
  const { code } = body;
34
- if (!config?.auth?.['2factor']) {
35
- return reply.status(400).send('2fa not enabled');
34
+ if (!config?.auth?.["2factor"]) {
35
+ return reply.status(400).send("2fa not enabled");
36
36
  }
37
37
  if (!config.pg) {
38
- return reply.status(400).send('empty pg');
38
+ return reply.status(400).send("empty pg");
39
39
  }
40
40
  if (!code) {
41
- return reply.status(400).send('not enough params');
41
+ return reply.status(400).send("not enough params");
42
42
  }
43
43
  try {
44
44
  const { enabled } = await verify({ uid, code, pg });
45
45
  await enableSecret({
46
- pg, TYPE: 'TOTP', uid,
46
+ pg,
47
+ TYPE: "TOTP",
48
+ uid,
47
49
  });
48
- req.session.secondFactor = true;
50
+ req.session.secondFactorPassed = true;
49
51
  if (!enabled) {
50
- const { recoveryCodes } = await pg.query(`select social_auth_obj->'codesArray' as "recoveryCodes"
51
- from admin.users_social_auth where uid=$1 and social_auth_type='TOTP'`, [uid])?.then((el) => el.rows?.[0] || {});
52
- const customPt = await getTemplate('pt', template);
53
- const pt = customPt || await readFile(path.join(dirname, `../templates/pt/${template}.html`), 'utf8');
54
- const html = await handlebars.compile(pt)({ recoveryCodes, domain: `${req.protocol || 'https'}://${req.hostname}` });
52
+ const { recoveryCodes } = await pg
53
+ .query(`select social_auth_obj->'codesArray' as "recoveryCodes"
54
+ from admin.users_social_auth where uid=$1 and social_auth_type='TOTP'`, [uid])
55
+ ?.then((el) => el.rows?.[0] || {});
56
+ const customPt = await getTemplate("pt", template);
57
+ const pt = customPt ||
58
+ (await readFile(path.join(dirname, `../templates/pt/${template}.html`), "utf8"));
59
+ const html = await handlebars.compile(pt)({
60
+ recoveryCodes,
61
+ domain: `${req.protocol || "https"}://${req.hostname}`,
62
+ });
55
63
  await sendNotification({
56
64
  pg,
57
65
  to: email,
@@ -60,7 +68,8 @@ export default async function verifyFunction(req, reply) {
60
68
  nocache: config.local || config.debug,
61
69
  });
62
70
  }
63
- return reply.redirect('/');
71
+ const redirectUrl = req.headers?.referer?.match?.(/[?&]redirect=([^&]+)/)?.[1] || "/";
72
+ return reply.redirect(redirectUrl.startsWith("/") ? redirectUrl : "/");
64
73
  }
65
74
  catch (err) {
66
75
  return reply.status(500).send(err.toString());
@@ -10,8 +10,8 @@ import loginFile from "../../../../plugins/auth/funcs/loginFile.js";
10
10
  *
11
11
  */
12
12
  export default async function login(req, reply) {
13
- const exists = existsSync("passwd");
14
- if (exists && !req.unittest && !config.auth?.disablePasswd) {
13
+ const ispasswd = existsSync("passwd") && !config.auth?.["2factor"];
14
+ if (ispasswd && !req.unittest && !config.auth?.disablePasswd) {
15
15
  // login with passwd file
16
16
  const res = await loginFile(req, reply);
17
17
  return res;
@@ -43,7 +43,7 @@ export default async function loginTemplate(req, reply) {
43
43
  : await generate({ uid, pg });
44
44
  /* -- access recovery start */
45
45
  // user already authorized via euSign / social / login
46
- if (uid && !req.session?.secondFactor && req.query?.recovery) {
46
+ if (uid && !req.session?.secondFactorPassed && req.query?.recovery) {
47
47
  const defaultPagePath = path.join(dirname, "../../server/templates/page/2factor-recovery.html");
48
48
  const customBodyRecovery = await getTemplate("page", "2factor-recovery");
49
49
  const bodyRecovery = customBodyRecovery || (await readFile(defaultPagePath, "utf8"));
@@ -54,12 +54,10 @@ export default async function loginTemplate(req, reply) {
54
54
  return reply.headers(headers).send(html);
55
55
  }
56
56
  /* -- access recovery end -- */
57
- if (req.session?.secondFactor) {
57
+ if (req.session?.secondFactorPassed) {
58
58
  return reply.redirect("/");
59
59
  }
60
- const base64 = !enabled && otp
61
- ? await qr.toDataURL(otp)
62
- : "";
60
+ const base64 = !enabled && otp ? await qr.toDataURL(otp) : "";
63
61
  const qrCode = base64 ? `<img src="${base64}" alt="qrcode">` : "";
64
62
  const html = await handlebars.compile(body)({
65
63
  secretKey: qrCode ? secret || key : undefined,
@@ -1,5 +1,3 @@
1
- // import fp from "fastify-plugin";
2
- import config from "../../../config.js";
3
1
  // login-password
4
2
  import login from "./controllers/core/login.js";
5
3
  import registration from "./controllers/core/registration.js";
@@ -20,7 +18,7 @@ import login2faTemplate from "./controllers/page/login2faTemplate.js";
20
18
  import oauthAuthorize from "./controllers/jwt/authorize.js";
21
19
  import oauthToken from "./controllers/jwt/token.js";
22
20
  const params = { config: { policy: "L0" } };
23
- async function plugin(app, opt = config) {
21
+ async function plugin(app, opt = {}) {
24
22
  if (opt.routes === false) {
25
23
  return;
26
24
  }
@@ -7,9 +7,7 @@ const cronSchema = {
7
7
  },
8
8
  },
9
9
  };
10
- const policy = ["site", "admin"];
11
- async function plugin(app, config = { prefix: "/api" }) {
12
- const { prefix = "/api" } = config;
13
- app.get(`${prefix}/cron/:name`, { config: { policy }, schema: cronSchema }, cronApi);
10
+ async function plugin(app, opt = {}) {
11
+ app.get("/cron/:name", { config: { policy: "L0" }, schema: cronSchema }, cronApi);
14
12
  }
15
13
  export default plugin;
@@ -11,12 +11,11 @@ const tableSchema = {
11
11
  },
12
12
  },
13
13
  };
14
- const policy = ["public"];
15
- async function plugin(app, config = { prefix: "/api" }) {
16
- const { prefix = "/api" } = config;
17
- app.put(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, update);
18
- app.delete(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, deleteCrud);
19
- app.post(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, insert);
20
- app.get(`${prefix}/table/:table/:id?`, { config: { policy }, schema: tableSchema }, table);
14
+ const policy = "L0";
15
+ async function plugin(app, opt = {}) {
16
+ app.put("/table/:table/:id?", { config: { policy }, schema: tableSchema }, update);
17
+ app.delete("/table/:table/:id?", { config: { policy }, schema: tableSchema }, deleteCrud);
18
+ app.post("/table/:table/:id?", { config: { policy }, schema: tableSchema }, insert);
19
+ app.get("/table/:table/:id?", { config: { policy }, schema: tableSchema }, table);
21
20
  }
22
21
  export default plugin;
@@ -2,16 +2,20 @@ import readItemList from "./controllers/readItems.js";
2
2
  import setItem from "./controllers/setItem.js";
3
3
  const policy = ["site"];
4
4
  export default async function plugin(app) {
5
- app.route({
6
- method: "GET",
7
- url: "/db-list",
8
- config: { policy },
9
- handler: readItemList,
10
- });
11
- app.route({
12
- method: "GET",
13
- url: "/db-list/:id",
14
- config: { policy },
15
- handler: setItem,
16
- });
5
+ if (!app.hasRoute({ method: "GET", url: "/db-list" })) {
6
+ app.route({
7
+ method: "GET",
8
+ url: "/db-list",
9
+ config: { policy },
10
+ handler: readItemList,
11
+ });
12
+ }
13
+ if (!app.hasRoute({ method: "GET", url: "/db-list/:id" })) {
14
+ app.route({
15
+ method: "GET",
16
+ url: "/db-list/:id",
17
+ config: { policy },
18
+ handler: setItem,
19
+ });
20
+ }
17
21
  }
@@ -1,4 +1,3 @@
1
- import fp from "fastify-plugin";
2
1
  import files from "./controllers/files.js";
3
2
  import resize from "./controllers/resize.js";
4
3
  import resizeAll from "./controllers/resizeAll.js";
@@ -8,8 +7,7 @@ import exportTable from "./controllers/export.js";
8
7
  import uploadImage from "./controllers/uploadImage.js";
9
8
  import deleteFileAPI from "./controllers/delete.js";
10
9
  import { resizeSchema } from "./schema.js";
11
- async function plugin(app, config = {}) {
12
- const { prefix = "/api" } = config;
10
+ async function plugin(app, opt = {}) {
13
11
  app.get("/files/*", { config: { policy: ["public"] } }, files);
14
12
  app.get("/file/resize", { config: { policy: ["public"] }, schema: resizeSchema }, resize);
15
13
  app.get("/api/resize-all", { config: { policy: ["admin", "site"] }, schema: resizeSchema }, resizeAll);
@@ -17,6 +15,6 @@ async function plugin(app, config = {}) {
17
15
  app.post("/file/upload-image/*", { config: { policy: ["public"] } }, uploadImage);
18
16
  app.get("/file/download/*", { config: { policy: ["public"] } }, download);
19
17
  app.get("/file/delete/*", { config: { policy: ["public"] } }, deleteFileAPI);
20
- app.get(`${prefix}/export`, { config: { policy: ["public"] } }, exportTable);
18
+ app.get(`/api/export`, { config: { policy: ["public"] } }, exportTable);
21
19
  }
22
- export default fp(plugin);
20
+ export default plugin;
@@ -1,9 +1,7 @@
1
- import fp from "fastify-plugin";
2
1
  import file2geojson from "./controllers/file2geojson.js";
3
2
  import filePreview from "./controllers/filePreview.js";
4
3
  async function plugin(app, opts) {
5
- const { prefix = "/api" } = opts || {};
6
- app.post(`${prefix}/file2geojson`, { config: { policy: ["public"] } }, file2geojson);
7
- app.get(`${prefix}/file-preview`, { config: { policy: ["public"] } }, filePreview);
4
+ app.post("/file2geojson", { config: { policy: ["public"] } }, file2geojson);
5
+ app.get("/file-preview", { config: { policy: ["public"] } }, filePreview);
8
6
  }
9
- export default fp(plugin);
7
+ export default plugin;
@@ -12,7 +12,7 @@ const loggerSchema = {
12
12
  additionalProperties: false,
13
13
  },
14
14
  };
15
- async function plugin(app) {
16
- app.get("/logger-file/*", { config: { policy: ["public"], rateLimit: false }, schema: loggerSchema }, loggerFile);
15
+ async function plugin(app, opt = {}) {
16
+ app.get("/logger-file/*", { config: { policy: "L0", rateLimit: false }, schema: loggerSchema }, loggerFile);
17
17
  }
18
18
  export default plugin;
@@ -1,7 +1,6 @@
1
1
  import getMenu from "./controllers/getMenu.js";
2
2
  import interfaces from "./controllers/interfaces.js";
3
- export default async function route(app, config = {}) {
4
- const { prefix = "/api" } = config;
5
- app.get(`${prefix}/user-menu`, getMenu);
6
- app.get(`${prefix}/interfaces`, { config: { policy: ["admin"] } }, interfaces);
3
+ export default async function route(app, opt = {}) {
4
+ app.get("/user-menu", getMenu);
5
+ app.get("/interfaces", { config: { role: "admin" } }, interfaces);
7
6
  }
@@ -12,10 +12,8 @@ const propertiesSchema = {
12
12
  },
13
13
  },
14
14
  };
15
- const policy = ["site"]; // cms etc.
16
- async function plugin(app, config = { prefix: "/api" }) {
17
- const { prefix = "/api" } = config;
18
- app.get(`${prefix}/settings-app/:entity?`, { config: { policy }, schema: propertiesSchema }, getAppSettings);
19
- app.post(`${prefix}/settings-app/:entity?`, { config: { policy: ["admin"] } }, postAppSettings);
15
+ async function plugin(app, opt = {}) {
16
+ app.get("/settings-app/:entity?", { config: { role: "admin" }, schema: propertiesSchema }, getAppSettings);
17
+ app.post("/settings-app/:entity?", { config: { role: "admin" } }, postAppSettings);
20
18
  }
21
19
  export default plugin;
@@ -1,3 +1,4 @@
1
+ import config from "../../../config.js";
1
2
  import suggest from "./controllers/suggest.js";
2
3
  import data from "./controllers/tableData.js";
3
4
  import cardTabData from "./controllers/cardTabData.js";
@@ -12,13 +13,12 @@ import filter from "./controllers/filter.js";
12
13
  import form from "./controllers/getFormByTable.js";
13
14
  import loadTemplatePath from "../../plugins/table/funcs/loadTemplatePath.js";
14
15
  import { tableDataSchema, tableSchema, searchSchema, suggestSchema, formSchema, filterSchema, cardTabDataSchema, tableDataIdSchema, } from "./schema.js";
15
- const policy = ["public"];
16
- async function plugin(app, config) {
17
- const { prefix = "/api" } = config;
18
- app.get(`${prefix}/token-info/:token`, { config: { policy: ["admin"] } }, tokenInfo);
19
- app.get(`${prefix}/table-filter/:table`, { config: { policy }, schema: filterSchema }, filter);
20
- app.get(`${prefix}/table-info/:table/:id?`, { config: { policy }, schema: tableDataSchema }, tableInfo);
21
- app.get(`${prefix}/suggest/:data`, {
16
+ const policy = "L0";
17
+ async function plugin(app, opt = {}) {
18
+ app.get("/token-info/:token", { config: { role: "admin" } }, tokenInfo);
19
+ app.get("/table-filter/:table", { config: { policy }, schema: filterSchema }, filter);
20
+ app.get("/table-info/:table/:id?", { config: { policy }, schema: tableDataSchema }, tableInfo);
21
+ app.get("/suggest/:data", {
22
22
  config: {
23
23
  policy,
24
24
  rateLimit: config.rateLimit
@@ -30,15 +30,15 @@ async function plugin(app, config) {
30
30
  },
31
31
  schema: suggestSchema,
32
32
  }, suggest);
33
- app.get(`${prefix}/data/:table/:id?`, { config: { policy: ["public", "no-sql"] }, schema: tableSchema }, data);
34
- app.get(`${prefix}/table-data/:table`, { config: { policy: ["user", "no-sql"] }, schema: tableDataSchema }, data);
35
- app.get(`${prefix}/table-data/:table/:id`, { config: { policy }, schema: tableDataIdSchema }, cardData);
36
- app.get(`${prefix}/data-info/:id?`, { config: { policy: ["public", "no-sql"] }, schema: tableSchema }, dataInfo);
37
- app.get(`${prefix}/card-data/:token`, { config: { policy }, scheme: cardTabDataSchema }, cardTabData);
38
- app.get(`${prefix}/card/:table/:id`, { config: { policy }, schema: tableSchema }, card);
39
- app.get(`${prefix}/search`, { config: { policy }, schema: searchSchema }, search);
40
- app.get(`${prefix}/templates`, () => loadTemplatePath);
41
- app.get(`${prefix}/filter/:table`, { config: { policy }, schema: filterSchema }, filter);
42
- app.get(`${prefix}/form/:name/:id?`, { config: { policy: ["user", "site"] }, schema: formSchema }, form);
33
+ app.get("/data/:table/:id?", { config: { policy }, schema: tableSchema }, data);
34
+ app.get("/table-data/:table", { config: { auth: "creds", policy: "L2" }, schema: tableDataSchema }, data);
35
+ app.get("/table-data/:table/:id", { config: { policy }, schema: tableDataIdSchema }, cardData);
36
+ app.get("/data-info/:id?", { config: { policy }, schema: tableSchema }, dataInfo);
37
+ app.get("/card-data/:token", { config: { policy }, scheme: cardTabDataSchema }, cardTabData);
38
+ app.get("/card/:table/:id", { config: { policy }, schema: tableSchema }, card);
39
+ app.get("/search", { config: { policy }, schema: searchSchema }, search);
40
+ app.get("/templates", () => loadTemplatePath);
41
+ app.get("/filter/:table", { config: { policy }, schema: filterSchema }, filter);
42
+ app.get("/form/:name/:id?", { config: { auth: "creds", policy: "L2" }, schema: formSchema }, form);
43
43
  }
44
44
  export default plugin;
@@ -1,7 +1,6 @@
1
1
  import getTemplateApi from "./controllers/getTemplate.js";
2
2
  import { getTemplateSchema } from "./schema.js";
3
- const policy = ["public"];
4
- export default async function route(app, config = {}) {
5
- const { prefix = "/api" } = config;
6
- app.get(`${prefix}/template/:type/:name`, { config: { policy }, schema: getTemplateSchema }, getTemplateApi);
3
+ const policy = "L0";
4
+ export default async function route(app, opt = {}) {
5
+ app.get("/template/:type/:name", { config: { policy }, schema: getTemplateSchema }, getTemplateApi);
7
6
  }
@@ -1,17 +1,17 @@
1
+ import config from "../../../config.js";
1
2
  import nextId from "./controllers/next.id.js";
2
3
  import statusMonitor from "./controllers/status.monitor.js";
3
4
  import userTokens from "./controllers/user.tokens.js";
4
5
  import codeGenerator from "./controllers/code.generator.js";
5
- async function plugin(app, config = { prefix: "/api" }) {
6
- const { prefix = "/api" } = config;
7
- app.get(`${prefix}/next-id`, { config: { policy: "L0" } }, nextId);
8
- app.get(`${prefix}/status-monitor`, { config: { role: "admin" } }, statusMonitor);
9
- app.get(`${prefix}/user-tokens/:token`, { config: { role: "admin|regular" } }, userTokens);
10
- app.get(`${prefix}/code-gen/:token/:column/:id?`, { config: { role: "admin|regular" } }, codeGenerator);
11
- app.get("/api/test-proxy", { config: { policy: "L0" } }, (req) => ({
6
+ async function plugin(app, opt = {}) {
7
+ app.get("/next-id", { config: { policy: "L0" } }, nextId);
8
+ app.get("/status-monitor", { config: { role: "admin" } }, statusMonitor);
9
+ app.get("/user-tokens/:token", { config: { role: "admin|regular" } }, userTokens);
10
+ app.get("/code-gen/:token/:column/:id?", { config: { role: "admin|regular" } }, codeGenerator);
11
+ app.get("/test-proxy", { config: { policy: "L0" } }, (req) => ({
12
12
  ...(req.headers || {}),
13
13
  sessionId: req.session?.sessionId,
14
14
  }));
15
- app.get("/api/config", { config: { role: "admin" } }, () => config);
15
+ app.get("/config", { config: { role: "admin" } }, () => config);
16
16
  }
17
17
  export default plugin;
@@ -31,12 +31,11 @@ const tableSchema = {
31
31
  },
32
32
  };
33
33
  addHook("onWidgetSet", onWidgetSet);
34
- const policy = ["site"];
34
+ const policy = "L0";
35
35
  const params = { config: { policy }, schema: tableSchema };
36
- export default async function route(app, config = {}) {
37
- const { prefix = "/api" } = config;
38
- app.delete(`${prefix}/widget/:type/:objectid/:id`, params, widgetDel);
39
- app.post(`${prefix}/widget/:type/:objectid/:id?`, params, widgetSet);
40
- app.put(`${prefix}/file-edit/:id`, params, fileEdit);
41
- app.get(`${prefix}/widget/:type/:objectid`, { config: { policy: ["public"] }, schema: tableSchema }, widgetGet);
36
+ export default async function route(app, opt = {}) {
37
+ app.delete("/widget/:type/:objectid/:id", params, widgetDel);
38
+ app.post("/widget/:type/:objectid/:id?", params, widgetSet);
39
+ app.put("/file-edit/:id", params, fileEdit);
40
+ app.get("/widget/:type/:objectid", { config: { policy }, schema: tableSchema }, widgetGet);
42
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [
package/dist/server.js DELETED
@@ -1,62 +0,0 @@
1
- /* eslint-disable no-return-assign */
2
- // This file contains code that we reuse
3
- // between our tests.
4
- import Fastify from 'fastify';
5
-
6
- import config from './config.js';
7
- import plugin from './index.js';
8
- import addHook from "./server/plugins/hook/funcs/addHook.js";
9
- import loginEuSign from './server/routes/auth/controllers/page/loginEuSign.js';
10
-
11
- import loggerTest from './server/routes/logger/controllers/logger.test.api.js';
12
- import { logger, addTemplateDir } from './utils.js';
13
-
14
- const cwd = process.cwd();
15
-
16
- const app = Fastify({ loggerInstance: logger });
17
- await app.register(plugin, config);
18
-
19
- // debug only
20
- app.get('/login1', { config: { policy: 'L0' } }, loginEuSign);
21
- addHook("afterAuth", async () => {
22
- if (config.auth?.redirectAfter) return; // let config decide
23
- return { href: "/user" }; // force redirect to specific page after login
24
- });
25
-
26
- addTemplateDir(`${cwd}/module/test`);
27
-
28
- app.get('/logger-test', { schema: {} }, loggerTest);
29
- app.get('/err', { schema: {} }, () => {
30
- throw new Error('test error code 500');
31
- });
32
-
33
- app.get('/health', {
34
- // preHandler: userJwt,
35
- config: {
36
- policy: 'L1', // L0, L1, L2
37
- auth: 'user-jwt', // none, user-jwt, creds
38
- role: 'admin', // role
39
- scope: 'logger', // logger, admin, gis, bi
40
- rateLimit: { max: 100, timeWindow: '1 minute', hook: 'preHandler' },
41
- cors: { origins: ['https://app.example.com'] },
42
- rbac: { resource: 'id', action: 'add' },
43
- }
44
- }, async () => ({ ok: true }));
45
-
46
- /* addCron(async function testCron() {
47
- return (config.local || true) ? null : { message: 'Done', status: 200 };
48
- }, 60 * 1); */
49
-
50
- /* const user = { user_type: config.auth?.type || 'admin', uid: config.auth?.uid || '2' };
51
- app.addHook('onRequest', async (req) => {
52
- req.user = user;
53
- }); */
54
-
55
- app.listen({ host: config.host || '0.0.0.0', port: config.port || process.env.PORT || 3000 }, (err) => {
56
- console.log(`Server started via port: ${config.port || process.env.PORT || 3000}`);
57
- if (err) {
58
- console.error(err.toString());
59
- logger.error(err);
60
- process.exit(1);
61
- }
62
- });