@opengis/fastify-table 2.0.0 → 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 +31 -41
- package/dist/server/plugins/auth/funcs/authorizeUser.js +7 -2
- package/dist/server/plugins/auth/index.js +29 -38
- package/dist/server/plugins/logger/index.js +1 -1
- package/dist/server/plugins/pg/index.js +4 -3
- package/dist/server/plugins/sqlite/index.js +1 -1
- package/dist/server/routes/access/index.js +4 -5
- package/dist/server/routes/auth/controllers/2factor/verify.js +32 -23
- package/dist/server/routes/auth/controllers/core/login.js +2 -2
- package/dist/server/routes/auth/controllers/page/login2faTemplate.js +3 -5
- package/dist/server/routes/auth/index.js +1 -3
- package/dist/server/routes/cron/index.js +2 -4
- package/dist/server/routes/crud/index.js +6 -7
- package/dist/server/routes/dblist/index.js +16 -12
- package/dist/server/routes/file/index.js +3 -5
- package/dist/server/routes/grpc/index.js +3 -5
- package/dist/server/routes/logger/index.js +2 -2
- package/dist/server/routes/menu/index.js +3 -4
- package/dist/server/routes/properties/index.js +3 -5
- package/dist/server/routes/table/index.js +17 -17
- package/dist/server/routes/templates/index.js +3 -4
- package/dist/server/routes/util/index.js +8 -8
- package/dist/server/routes/widget/index.js +6 -7
- package/package.json +1 -1
- package/dist/server.js +0 -62
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
|
-
|
|
42
|
-
config.
|
|
43
|
-
config.
|
|
44
|
-
config.
|
|
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
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|
89
|
-
await sqlitePlugin(fastify
|
|
78
|
+
await pgPlugin(fastify);
|
|
79
|
+
await sqlitePlugin(fastify);
|
|
90
80
|
cronPlugin();
|
|
91
|
-
loggerPlugin(fastify
|
|
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,30 +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
|
-
|
|
93
|
+
fastify.register(import("./server/routes/dblist/index.js")); // ! without prefix
|
|
103
94
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// fastify
|
|
117
|
-
// 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
|
|
118
108
|
await fastify.register(import("@fastify/multipart"), {
|
|
119
109
|
limits: {
|
|
120
110
|
fileSize: maxFileSize * 1024 * 1024,
|
|
121
111
|
},
|
|
122
112
|
}); // content parser, await before adding upload routes
|
|
123
|
-
fastify.register(import("./server/routes/file/index.js")
|
|
124
|
-
fastify.register(import("./server/routes/grpc/index.js")
|
|
113
|
+
fastify.register(import("./server/routes/file/index.js"));
|
|
114
|
+
fastify.register(import("./server/routes/grpc/index.js"));
|
|
125
115
|
config.proxy?.forEach?.((el) => {
|
|
126
116
|
if (execName === "bun") {
|
|
127
117
|
fastify.all(`${el.source}/*`, async (req, reply) => {
|
|
@@ -167,4 +157,4 @@ async function plugin(fastify, opt) {
|
|
|
167
157
|
}
|
|
168
158
|
});
|
|
169
159
|
}
|
|
170
|
-
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,17 +1,32 @@
|
|
|
1
|
-
|
|
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
|
|
12
|
-
if (!
|
|
10
|
+
async function plugin(fastify) {
|
|
11
|
+
if (!config.redis) {
|
|
13
12
|
return;
|
|
14
13
|
}
|
|
14
|
+
await fastify.register(cookie, {
|
|
15
|
+
parseOptions: config?.auth?.cookieOptions || { secure: false },
|
|
16
|
+
});
|
|
17
|
+
await fastify.register(session, {
|
|
18
|
+
secret: config?.auth?.secret || "61b820e12858570a4b0633020d4394a17903d9a9",
|
|
19
|
+
cookieName: "session_auth",
|
|
20
|
+
cookie: config?.auth?.cookieOptions || { secure: false },
|
|
21
|
+
store: new RedisStore({ client: getRedis({ db: 10 }) }),
|
|
22
|
+
});
|
|
23
|
+
// register passport AFTER session is ready
|
|
24
|
+
await fastify.register(fastifyPassport.initialize());
|
|
25
|
+
await fastify.register(fastifyPassport.secureSession());
|
|
26
|
+
// serialize user used to store user info in session store
|
|
27
|
+
fastifyPassport.registerUserSerializer(async (user) => ({ user }));
|
|
28
|
+
// deserialize user used to add user info from session store to req
|
|
29
|
+
fastifyPassport.registerUserDeserializer(async (passport) => passport?.user || passport);
|
|
15
30
|
fastify.addHook("onRequest", async (req, reply) => {
|
|
16
31
|
const { pg, hostname, headers, routeOptions } = req;
|
|
17
32
|
const { policy = [] } = routeOptions?.config || {};
|
|
@@ -35,8 +50,8 @@ async function plugin(fastify, opt = config) {
|
|
|
35
50
|
const isPublic = Array.isArray(policy)
|
|
36
51
|
? policy.includes("public")
|
|
37
52
|
: policy === "L0";
|
|
38
|
-
// if 2factor is enabled and
|
|
39
|
-
const {
|
|
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 +
|
|
40
55
|
if (!passport.user?.uid &&
|
|
41
56
|
(config.auth?.disable || config.auth?.user) &&
|
|
42
57
|
!isPublic) {
|
|
@@ -57,7 +72,8 @@ async function plugin(fastify, opt = config) {
|
|
|
57
72
|
console.log("req.user?.uid", req.user?.uid, "req.session?.passport?.user?.uid", req.session?.passport?.user?.uid, "config.auth", config.auth);
|
|
58
73
|
}
|
|
59
74
|
// currently 2factor + auth with passwd file not supported
|
|
60
|
-
const ispasswd = !
|
|
75
|
+
const ispasswd = (existsSync("passwd") && !config.auth?.["2factor"]) ||
|
|
76
|
+
config.auth?.passwd;
|
|
61
77
|
if (!passport.user?.uid &&
|
|
62
78
|
!config.auth?.disable &&
|
|
63
79
|
isAdmin &&
|
|
@@ -68,43 +84,18 @@ async function plugin(fastify, opt = config) {
|
|
|
68
84
|
return reply.redirect(`${config?.auth?.redirect || "/login"}` + `?redirect=${req.url}`);
|
|
69
85
|
}
|
|
70
86
|
if (passport.user?.uid &&
|
|
71
|
-
|
|
87
|
+
passport.user?.twofa &&
|
|
72
88
|
config.auth?.["2factor"] &&
|
|
73
|
-
|
|
89
|
+
!isPublic &&
|
|
74
90
|
(routeOptions?.method || "GET") === "GET" &&
|
|
75
|
-
!
|
|
91
|
+
!secondFactorPassed &&
|
|
76
92
|
!ispasswd) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"/2factor?recovery=1",
|
|
81
|
-
"/2factor/verify",
|
|
82
|
-
"/2factor/recovery",
|
|
83
|
-
"/user",
|
|
84
|
-
config.auth?.["2factorRedirect"],
|
|
85
|
-
]
|
|
86
|
-
.filter((el) => el)
|
|
87
|
-
.includes(req.url)) {
|
|
88
|
-
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);
|
|
89
96
|
}
|
|
90
97
|
}
|
|
91
98
|
return null;
|
|
92
99
|
});
|
|
93
|
-
await fastify.register(cookie, {
|
|
94
|
-
parseOptions: opt?.auth?.cookieOptions || { secure: false },
|
|
95
|
-
});
|
|
96
|
-
await fastify.register(session, {
|
|
97
|
-
secret: opt?.auth?.secret || "61b820e12858570a4b0633020d4394a17903d9a9",
|
|
98
|
-
cookieName: "session_auth",
|
|
99
|
-
cookie: opt?.auth?.cookieOptions || { secure: false },
|
|
100
|
-
store: new RedisStore({ client: getRedis({ db: 10 }) }),
|
|
101
|
-
});
|
|
102
|
-
// register passport AFTER session is ready
|
|
103
|
-
await fastify.register(fastifyPassport.initialize());
|
|
104
|
-
await fastify.register(fastifyPassport.secureSession());
|
|
105
|
-
// serialize user used to store user info in session store
|
|
106
|
-
fastifyPassport.registerUserSerializer(async (user) => ({ user }));
|
|
107
|
-
// deserialize user used to add user info from session store to req
|
|
108
|
-
fastifyPassport.registerUserDeserializer(async (passport) => passport?.user || passport);
|
|
109
100
|
}
|
|
110
101
|
export default plugin;
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
6
|
-
|
|
7
|
-
fastify.
|
|
8
|
-
fastify.
|
|
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
|
|
2
|
-
import { fileURLToPath } from
|
|
3
|
-
import { readFile } from
|
|
4
|
-
import config from
|
|
5
|
-
import getTemplate from
|
|
6
|
-
import pgClients from
|
|
7
|
-
import { handlebars } from
|
|
8
|
-
import { verify, enableSecret } from
|
|
9
|
-
import sendNotification from
|
|
10
|
-
const 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 = {}
|
|
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?.[
|
|
35
|
-
return reply.status(400).send(
|
|
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(
|
|
38
|
+
return reply.status(400).send("empty pg");
|
|
39
39
|
}
|
|
40
40
|
if (!code) {
|
|
41
|
-
return reply.status(400).send(
|
|
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,
|
|
46
|
+
pg,
|
|
47
|
+
TYPE: "TOTP",
|
|
48
|
+
uid,
|
|
47
49
|
});
|
|
48
|
-
req.session.
|
|
50
|
+
req.session.secondFactorPassed = true;
|
|
49
51
|
if (!enabled) {
|
|
50
|
-
const { recoveryCodes } = await pg
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
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
|
-
|
|
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
|
|
14
|
-
if (
|
|
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?.
|
|
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?.
|
|
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 =
|
|
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
|
-
|
|
11
|
-
|
|
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 =
|
|
15
|
-
async function plugin(app,
|
|
16
|
-
|
|
17
|
-
app.
|
|
18
|
-
app.
|
|
19
|
-
app.
|
|
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.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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,
|
|
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(
|
|
18
|
+
app.get(`/api/export`, { config: { policy: ["public"] } }, exportTable);
|
|
21
19
|
}
|
|
22
|
-
export default
|
|
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
|
-
|
|
6
|
-
app.
|
|
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
|
|
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:
|
|
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,
|
|
4
|
-
|
|
5
|
-
app.get(
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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 =
|
|
16
|
-
async function plugin(app,
|
|
17
|
-
|
|
18
|
-
app.get(
|
|
19
|
-
app.get(
|
|
20
|
-
app.get(
|
|
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(
|
|
34
|
-
app.get(
|
|
35
|
-
app.get(
|
|
36
|
-
app.get(
|
|
37
|
-
app.get(
|
|
38
|
-
app.get(
|
|
39
|
-
app.get(
|
|
40
|
-
app.get(
|
|
41
|
-
app.get(
|
|
42
|
-
app.get(
|
|
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 =
|
|
4
|
-
export default async function route(app,
|
|
5
|
-
|
|
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,
|
|
6
|
-
|
|
7
|
-
app.get(
|
|
8
|
-
app.get(
|
|
9
|
-
app.get(
|
|
10
|
-
app.get(
|
|
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("/
|
|
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 =
|
|
34
|
+
const policy = "L0";
|
|
35
35
|
const params = { config: { policy }, schema: tableSchema };
|
|
36
|
-
export default async function route(app,
|
|
37
|
-
|
|
38
|
-
app.
|
|
39
|
-
app.
|
|
40
|
-
app.
|
|
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
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
|
-
});
|