193 lines
4.8 KiB
JavaScript
193 lines
4.8 KiB
JavaScript
import config from 'config';
|
|
import path from 'path';
|
|
import express from 'express';
|
|
import boolParser from 'express-query-boolean';
|
|
import Router from 'express-promise-router';
|
|
import session from 'express-session';
|
|
import RedisStore from 'connect-redis';
|
|
import compression from 'compression';
|
|
import cookie from 'cookie';
|
|
|
|
import redis from '../redis.js';
|
|
|
|
import errorHandler from './error.js';
|
|
import consentHandler from './consent.js';
|
|
import initRestrictionHandler from './restrictions.js';
|
|
|
|
import { scenesRouter } from './scenes.js';
|
|
import { actorsRouter } from './actors.js';
|
|
|
|
import { fetchMoviesApi } from './movies.js';
|
|
import { fetchEntitiesApi } from './entities.js';
|
|
import { fetchTagsApi } from './tags.js';
|
|
|
|
import { verifyKey } from '../auth.js';
|
|
import { graphqlApi } from './graphql.js';
|
|
|
|
import mainHandler from './main.js';
|
|
|
|
import {
|
|
setUserApi,
|
|
loginApi,
|
|
logoutApi,
|
|
signupApi,
|
|
fetchUserKeysApi,
|
|
createKeyApi,
|
|
removeUserKeyApi,
|
|
flushUserKeysApi,
|
|
} from './auth.js';
|
|
|
|
import { router as userRouter } from './users.js';
|
|
import { router as stashesRouter } from './stashes.js';
|
|
import { router as alertsRouter } from './alerts.js';
|
|
|
|
import { initCachesApi } from './system.js';
|
|
|
|
import initLogger from '../logger.js';
|
|
|
|
const logger = initLogger();
|
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
|
|
export default async function initServer() {
|
|
const app = express();
|
|
const router = Router();
|
|
const restrictionHandler = await initRestrictionHandler();
|
|
|
|
app.use(compression());
|
|
app.disable('x-powered-by');
|
|
app.set('view engine', 'ejs');
|
|
|
|
router.use(boolParser());
|
|
|
|
router.use('/', express.static('public'));
|
|
router.use('/', express.static('static'));
|
|
router.use('/media', express.static(config.media.path));
|
|
|
|
router.use((req, _res, next) => {
|
|
if (req.headers.cookie) {
|
|
const cookies = cookie.parse(req.headers.cookie);
|
|
|
|
/* eslint-disable no-param-reassign */
|
|
req.cookies = cookies;
|
|
req.tagFilter = cookies.tags ? JSON.parse(cookies.tags) : [];
|
|
/* eslint-enable no-param-reassign */
|
|
}
|
|
|
|
next();
|
|
});
|
|
|
|
router.use(express.json());
|
|
|
|
const redisStore = new RedisStore({
|
|
client: redis,
|
|
prefix: 'traxxx:session:',
|
|
});
|
|
|
|
router.use(session({
|
|
...config.web.session,
|
|
store: redisStore,
|
|
}));
|
|
|
|
router.use(setUserApi);
|
|
|
|
// Vite integration
|
|
if (isProduction) {
|
|
app.enable('trust proxy');
|
|
|
|
// In production, we need to serve our static assets ourselves.
|
|
// (In dev, Vite's middleware serves our static assets.)
|
|
const sirv = (await import('sirv')).default;
|
|
router.use(sirv('dist/client'));
|
|
} else {
|
|
// We instantiate Vite's development server and integrate its middleware to our server.
|
|
// ⚠️ We instantiate it only in development. (It isn't needed in production and it
|
|
// would unnecessarily bloat our production server.)
|
|
const vite = await import('vite');
|
|
|
|
const viteDevMiddleware = (
|
|
await vite.createServer({
|
|
// root,
|
|
server: { middlewareMode: true },
|
|
})
|
|
).middlewares;
|
|
|
|
router.use(viteDevMiddleware);
|
|
}
|
|
|
|
router.use(restrictionHandler);
|
|
|
|
router.get('/consent', (_req, res) => {
|
|
res.sendFile(path.join(import.meta.dirname, '../../assets/consent.html'));
|
|
});
|
|
|
|
router.use('/api/*', async (req, _res, next) => {
|
|
if (req.headers['api-user']) {
|
|
await verifyKey(req.headers['api-user'], req.headers['api-key'], req);
|
|
|
|
req.user = { // eslint-disable-line no-param-reassign
|
|
id: Number(req.headers['api-user']),
|
|
};
|
|
}
|
|
|
|
next();
|
|
});
|
|
|
|
// SESSION
|
|
router.post('/api/session', loginApi);
|
|
router.delete('/api/session', logoutApi);
|
|
|
|
// USERS
|
|
router.post('/api/users', signupApi);
|
|
|
|
// API KEYS
|
|
router.get('/api/me/keys', fetchUserKeysApi);
|
|
router.post('/api/me/keys', createKeyApi);
|
|
router.delete('/api/me/keys/:keyIdentifier', removeUserKeyApi);
|
|
router.delete('/api/me/keys', flushUserKeysApi);
|
|
|
|
router.use(userRouter);
|
|
router.use(stashesRouter);
|
|
router.use(alertsRouter);
|
|
router.use(scenesRouter);
|
|
router.use(actorsRouter);
|
|
|
|
// MOVIES
|
|
router.get('/api/movies', fetchMoviesApi);
|
|
|
|
// ENTITIES
|
|
router.get('/api/entities', fetchEntitiesApi);
|
|
|
|
// TAGS
|
|
router.get('/api/tags', fetchTagsApi);
|
|
|
|
router.post('/api/caches', initCachesApi);
|
|
|
|
if (config.apiAccess.graphqlEnabled) {
|
|
router.post('/graphql', graphqlApi);
|
|
}
|
|
|
|
router.use(consentHandler);
|
|
|
|
router.use((_req, res, next) => {
|
|
/* eslint-disable no-param-reassign */
|
|
res.set('Accept-CH', 'Sec-CH-Prefers-Color-Scheme');
|
|
res.set('Vary', 'Sec-CH-Prefers-Color-Scheme');
|
|
res.set('Critical-CH', 'Sec-CH-Prefers-Color-Scheme');
|
|
/* eslint-enable no-param-reassign */
|
|
|
|
next();
|
|
});
|
|
|
|
router.get('*', mainHandler);
|
|
|
|
router.use(errorHandler);
|
|
app.use(router);
|
|
|
|
const port = process.env.PORT || config.web.port || 3000;
|
|
// const port = Math.round(Math.random() * 10000);
|
|
|
|
app.listen(port, config.web.host);
|
|
|
|
logger.info(`Server running at http://${config.web.host}:${port}`);
|
|
}
|