Files
Jellystat/backend/server.js
Thegan Govender e63f52e2fb Added .dockerignore file to speed up local image builds
Changed Dockerfile as previos file was failing to build consistently
removed some unused packages
added compression to json payloads
changed vite ports to 3000 to not break existing builds
backend and frontend both use port 3000 now
2023-11-11 17:06:44 +02:00

166 lines
4.9 KiB
JavaScript

// core
require('dotenv').config();
const http = require('http');
const path = require('path');
const express = require('express');
const compression = require('compression');
const cors = require('cors');
const jwt = require('jsonwebtoken');
const knex = require('knex');
const swaggerUi = require('swagger-ui-express');
const swaggerDocument = require('./swagger.json');
// db
const dbInstance = require('./db');
const createdb = require('./create_database');
const knexConfig = require('./migrations');
// routes
const authRouter = require('./routes/auth');
const apiRouter = require('./routes/api');
const proxyRouter = require('./routes/proxy');
const syncRouter = require('./routes/sync');
const statsRouter = require('./routes/stats');
const backupRouter = require('./routes/backup');
const logRouter = require('./routes/logging');
const utilsRouter = require('./routes/utils');
// tasks
const ActivityMonitor = require('./tasks/ActivityMonitor');
const SyncTask = require('./tasks/SyncTask');
const BackupTask = require('./tasks/BackupTask');
// websocket
const { setupWebSocketServer } = require('./ws');
const app = express();
const db = knex(knexConfig.development);
const PORT = 3000;
const LISTEN_IP = '127.0.0.1';
const JWT_SECRET = process.env.JWT_SECRET;
if (JWT_SECRET === undefined) {
console.log('JWT Secret cannot be undefined');
process.exit(1); // end the program with error status code
}
// middlewares
app.use(express.json()); // middleware to parse JSON request bodies
app.use(cors());
app.set('trust proxy', 1);
app.disable('x-powered-by');
app.use(compression());
// initiate routes
app.use('/auth', authRouter, () => {
/* #swagger.tags = ['Auth'] */
}); // mount the API router at /auth
app.use('/proxy', proxyRouter, () => {
/* #swagger.tags = ['Proxy']*/
}); // mount the API router at /proxy
app.use('/api', authenticate, apiRouter, () => {
/* #swagger.tags = ['API']*/
}); // mount the API router at /api, with JWT middleware
app.use('/sync', authenticate, syncRouter.router, () => {
/* #swagger.tags = ['Sync']*/
}); // mount the API router at /sync, with JWT middleware
app.use('/stats', authenticate, statsRouter, () => {
/* #swagger.tags = ['Stats']*/
}); // mount the API router at /stats, with JWT middleware
app.use('/backup', authenticate, backupRouter.router, () => {
/* #swagger.tags = ['Backup']*/
}); // mount the API router at /backup, with JWT middleware
app.use('/logs', authenticate, logRouter.router, () => {
/* #swagger.tags = ['Logs']*/
}); // mount the API router at /logs, with JWT middleware
app.use('/utils', authenticate, utilsRouter, () => {
/* #swagger.tags = ['Utils']*/
}); // mount the API router at /utils, with JWT middleware
// Swagger
app.use('/swagger', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
// for deployment of static page
const root = path.join(__dirname, '..', 'dist');
app.use(express.static(root));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '..', 'dist', 'index.html'));
});
const server = http.createServer(app);
setupWebSocketServer(server);
// JWT middleware
async function authenticate(req, res, next) {
const token = req.headers.authorization;
const apiKey = req.headers['x-api-token'] || req.query.apiKey;
if (!token && !apiKey) {
return res.status(401).json({
message: 'Authentication failed. No token or API key provided.',
});
}
if (token) {
const extracted_token = token.split(' ')[1];
if (!extracted_token || extracted_token === 'null') {
return res.sendStatus(403);
}
try {
const decoded = jwt.verify(extracted_token, JWT_SECRET);
req.user = decoded.user;
next();
} catch (error) {
console.log(error);
return res.status(401).json({ message: 'Invalid token' });
}
} else {
if (apiKey) {
const keysjson = await dbInstance
.query('SELECT api_keys FROM app_config where "ID"=1')
.then((res) => res.rows[0].api_keys);
if (!keysjson || Object.keys(keysjson).length === 0) {
return res.status(404).json({ message: 'No API keys configured' });
}
const keys = keysjson || [];
const keyExists = keys.some((obj) => obj.key === apiKey);
if (keyExists) {
next();
} else {
return res.status(403).json({ message: 'Invalid API key' });
}
}
}
}
// start server
try {
createdb.createDatabase().then((result) => {
if (result) {
console.log('[JELLYSTAT] Database created');
} else {
console.log('[JELLYSTAT] Database exists. Skipping creation');
}
db.migrate.latest().then(() => {
server.listen(PORT, async () => {
console.log(
`[JELLYSTAT] Server listening on http://${LISTEN_IP}:${PORT}`
);
ActivityMonitor.ActivityMonitor(1000);
SyncTask.SyncTask();
BackupTask.BackupTask();
});
});
});
} catch (error) {
console.log('[JELLYSTAT] An error has occured on startup: ' + error);
}