2023-04-09 11:36:01 +02:00
|
|
|
// Boot scripts
|
2024-03-11 13:43:20 +01:00
|
|
|
import('./server/bootstrap.js');
|
2023-04-09 11:36:01 +02:00
|
|
|
|
2024-01-29 07:24:38 +01:00
|
|
|
import cookie from '@fastify/cookie';
|
|
|
|
import cors from '@fastify/cors';
|
|
|
|
import helmet from '@fastify/helmet';
|
|
|
|
import jwt from '@fastify/jwt';
|
2024-03-11 13:43:20 +01:00
|
|
|
import fastifyStatic from '@fastify/static';
|
|
|
|
import FastifyVite from '@fastify/vite';
|
2022-08-27 19:25:14 +02:00
|
|
|
import config from 'config';
|
2024-01-29 07:24:38 +01:00
|
|
|
import importFastify from 'fastify';
|
2023-11-15 07:36:47 +01:00
|
|
|
import { JSDOM } from 'jsdom';
|
2024-03-11 13:43:20 +01:00
|
|
|
import fs from 'node:fs';
|
|
|
|
import path from 'node:path';
|
|
|
|
import { fileURLToPath } from 'node:url';
|
2023-11-15 07:36:47 +01:00
|
|
|
import template from 'y8';
|
2024-01-29 07:24:38 +01:00
|
|
|
|
2024-03-11 13:43:20 +01:00
|
|
|
import rateLimit from './server/plugins/rate-limit.js';
|
|
|
|
|
|
|
|
import adminDecorator from './server/decorators/admin.js';
|
|
|
|
import allowedIp from './server/decorators/allowed-ip.js';
|
|
|
|
import attachment from './server/decorators/attachment-upload.js';
|
|
|
|
import jwtDecorator from './server/decorators/jwt.js';
|
|
|
|
import userFeatures from './server/decorators/user-features.js';
|
|
|
|
|
|
|
|
import readCookieAllRoutesHandler from './server/prehandlers/cookie-all-routes.js';
|
|
|
|
import disableUserAccountCreationHandler from './server/prehandlers/disable-user-account-creation.js';
|
|
|
|
import disableUserHandler from './server/prehandlers/disable-users.js';
|
|
|
|
import readOnlyHandler from './server/prehandlers/read-only.js';
|
|
|
|
import restrictOrganizationEmailHandler from './server/prehandlers/restrict-organization-email.js';
|
|
|
|
|
|
|
|
import accountRoute from './server/controllers/account.js';
|
|
|
|
import adminSettingsRoute from './server/controllers/admin/settings.js';
|
|
|
|
import usersRoute from './server/controllers/admin/users.js';
|
|
|
|
import authenticationRoute from './server/controllers/authentication.js';
|
|
|
|
import downloadRoute from './server/controllers/download.js';
|
|
|
|
import healthzRoute from './server/controllers/healthz.js';
|
|
|
|
import secretRoute from './server/controllers/secret.js';
|
|
|
|
import statsRoute from './server/controllers/stats.js';
|
2024-05-01 18:14:46 +02:00
|
|
|
import customHeaders from './server/plugins/custom-headers.js';
|
2024-03-11 13:43:20 +01:00
|
|
|
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
|
|
const __dirname = path.dirname(__filename);
|
2022-08-27 19:25:14 +02:00
|
|
|
|
2023-04-02 17:18:19 +02:00
|
|
|
const isDev = process.env.NODE_ENV === 'development';
|
|
|
|
|
2022-09-07 19:19:35 +02:00
|
|
|
const MAX_FILE_BYTES = 1024 * config.get('file.size') * 1000; // Example: 1024 * 2 * 1000 = 2 024 000 bytes
|
|
|
|
|
2024-03-11 13:43:20 +01:00
|
|
|
const staticPath = path.join(__dirname, !isDev ? 'client/build' : 'client');
|
|
|
|
|
2022-08-27 19:25:14 +02:00
|
|
|
const fastify = importFastify({
|
2021-06-13 18:11:25 +02:00
|
|
|
logger: config.get('logger'),
|
2022-09-07 19:19:35 +02:00
|
|
|
bodyLimit: MAX_FILE_BYTES,
|
2021-06-13 18:11:25 +02:00
|
|
|
});
|
|
|
|
|
2024-03-11 13:43:20 +01:00
|
|
|
await fastify.register(FastifyVite, {
|
|
|
|
root: import.meta.url,
|
|
|
|
dev: process.argv.includes('--dev'),
|
|
|
|
spa: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
fastify.register(fastifyStatic, {
|
|
|
|
root: path.join(__dirname, 'public'),
|
|
|
|
prefix: '/static/',
|
|
|
|
});
|
|
|
|
|
|
|
|
fastify.register(fastifyStatic, {
|
|
|
|
root: path.join(__dirname, 'public', 'locales'),
|
|
|
|
prefix: '/locales/',
|
|
|
|
decorateReply: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!isDev) {
|
|
|
|
const script = template(
|
|
|
|
`
|
|
|
|
try {
|
|
|
|
window.__SECRET_CONFIG = {{config}}
|
|
|
|
} catch (e) {
|
|
|
|
window.__SECRET_CONFIG = '';
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
{ config: `'${JSON.stringify(config.get('__client_config'))}';` }
|
|
|
|
);
|
|
|
|
|
|
|
|
const index = staticPath + '/index.html';
|
|
|
|
|
|
|
|
const dom = new JSDOM(fs.readFileSync(index));
|
|
|
|
dom.window.document.querySelector('#__secret_config').textContent = script;
|
|
|
|
|
|
|
|
fs.writeFileSync(index, dom.serialize());
|
|
|
|
}
|
|
|
|
|
2024-05-01 18:14:46 +02:00
|
|
|
fastify.register(customHeaders);
|
|
|
|
|
2023-04-03 22:00:10 +02:00
|
|
|
fastify.register(rateLimit, {
|
2023-04-25 17:04:39 +02:00
|
|
|
prefix: '/api/',
|
2024-01-29 07:24:38 +01:00
|
|
|
max: config.get('rateLimit.max'),
|
|
|
|
timeWindow: config.get('rateLimit.timeWindow'),
|
2023-04-03 22:00:10 +02:00
|
|
|
});
|
|
|
|
|
2021-06-22 20:26:25 +02:00
|
|
|
// https://github.com/fastify/fastify-helmet
|
2023-02-13 19:16:20 +01:00
|
|
|
fastify.register(helmet, {
|
|
|
|
contentSecurityPolicy: {
|
|
|
|
directives: {
|
2023-08-23 06:39:22 +02:00
|
|
|
'font-src': ["'self'"],
|
2023-02-13 19:16:20 +01:00
|
|
|
'script-src': ["'self'", "'unsafe-inline'"],
|
2023-08-23 06:39:08 +02:00
|
|
|
upgradeInsecureRequests: null,
|
2023-02-13 19:16:20 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
crossOriginEmbedderPolicy: false,
|
|
|
|
});
|
2021-06-22 20:26:25 +02:00
|
|
|
|
2021-06-13 18:11:25 +02:00
|
|
|
// https://github.com/fastify/fastify-cors
|
2022-08-27 19:25:14 +02:00
|
|
|
fastify.register(cors, { origin: config.get('cors') });
|
2021-06-13 18:11:25 +02:00
|
|
|
|
2023-03-11 17:58:35 +01:00
|
|
|
// https://github.com/fastify/fastify-jwt#cookie
|
|
|
|
fastify.register(jwt, {
|
|
|
|
secret: config.get('jwt.secret'),
|
|
|
|
cookie: {
|
|
|
|
cookieName: config.get('jwt.cookie'),
|
|
|
|
signed: false,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
fastify.register(cookie);
|
|
|
|
|
2021-06-18 14:57:10 +02:00
|
|
|
// Define decorators
|
2023-04-09 11:36:01 +02:00
|
|
|
fastify.register(adminDecorator);
|
2023-03-11 17:58:35 +01:00
|
|
|
fastify.register(jwtDecorator);
|
2022-08-27 19:25:14 +02:00
|
|
|
fastify.register(userFeatures);
|
|
|
|
fastify.register(allowedIp);
|
|
|
|
fastify.register(attachment);
|
2021-06-18 14:57:10 +02:00
|
|
|
|
2023-04-09 11:36:01 +02:00
|
|
|
// Define pre handlers
|
|
|
|
fastify.addHook('preHandler', readCookieAllRoutesHandler(fastify));
|
|
|
|
fastify.addHook('preHandler', disableUserHandler);
|
2023-04-11 09:20:38 +02:00
|
|
|
fastify.addHook('preHandler', disableUserAccountCreationHandler);
|
2023-04-09 11:36:01 +02:00
|
|
|
fastify.addHook('preHandler', readOnlyHandler);
|
2023-04-17 13:19:06 +02:00
|
|
|
fastify.addHook('preHandler', restrictOrganizationEmailHandler);
|
2023-04-09 11:36:01 +02:00
|
|
|
|
2024-10-30 06:25:53 +01:00
|
|
|
fastify.get('/*', (request, reply) => {
|
|
|
|
if (request.url.startsWith('/api/')) {
|
|
|
|
return reply.callNotFound();
|
|
|
|
}
|
2024-03-11 13:43:20 +01:00
|
|
|
return reply.html();
|
2024-10-30 06:25:53 +01:00
|
|
|
});
|
2024-03-11 13:43:20 +01:00
|
|
|
|
2023-04-09 11:36:01 +02:00
|
|
|
fastify.register(authenticationRoute, {
|
|
|
|
prefix: '/api/authentication',
|
|
|
|
});
|
|
|
|
|
|
|
|
fastify.register(accountRoute, {
|
|
|
|
prefix: '/api/account',
|
|
|
|
});
|
|
|
|
|
2023-04-10 15:37:14 +02:00
|
|
|
fastify.register(usersRoute, {
|
|
|
|
prefix: '/api/admin/users',
|
|
|
|
});
|
|
|
|
|
2023-04-09 11:36:01 +02:00
|
|
|
fastify.register(adminSettingsRoute, {
|
|
|
|
prefix: '/api/admin/settings',
|
|
|
|
});
|
2022-09-08 17:06:09 +02:00
|
|
|
|
|
|
|
fastify.register(downloadRoute, { prefix: '/api/download' });
|
2022-08-27 19:25:14 +02:00
|
|
|
fastify.register(secretRoute, { prefix: '/api/secret' });
|
2022-08-29 22:28:48 +02:00
|
|
|
fastify.register(statsRoute, { prefix: '/api/stats' });
|
2022-08-27 19:25:14 +02:00
|
|
|
fastify.register(healthzRoute, { prefix: '/api/healthz' });
|
|
|
|
fastify.register(healthzRoute, { prefix: '/healthz' });
|
2021-06-13 18:11:25 +02:00
|
|
|
|
|
|
|
const startServer = async () => {
|
|
|
|
try {
|
2024-03-11 13:43:20 +01:00
|
|
|
await fastify.vite.ready();
|
2022-08-27 19:34:22 +02:00
|
|
|
await fastify.listen({ port: config.get('port'), host: config.get('localHostname') });
|
2021-06-13 18:11:25 +02:00
|
|
|
} catch (err) {
|
|
|
|
fastify.log.error(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
startServer();
|