Next.js+React web interface for controlling HAProxy clusters (groups of servers), in conjunction with with https://gitgud.io/fatchan/haproxy-protection.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
5.2 KiB
127 lines
5.2 KiB
const HAProxy = require('@fatchan/haproxy-sdk')
|
|
, express = require('express')
|
|
, dev = process.env.NODE_ENV !== 'production'
|
|
, session = require('express-session')
|
|
, MongoStore = require('connect-mongo')
|
|
, db = require('./db.js')
|
|
, csrf = require('csurf')
|
|
, { dynamicResponse } = require('./util.js');
|
|
|
|
const testRouter = (server, app) => {
|
|
|
|
const sessionStore = session({
|
|
secret: process.env.COOKIE_SECRET,
|
|
store: MongoStore.create({ mongoUrl: process.env.DB_URL }),
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
rolling: true,
|
|
cookie: {
|
|
httpOnly: true,
|
|
secure: true, //!dev, //TODO: check https
|
|
sameSite: 'strict',
|
|
maxAge: 1000 * 60 * 60 * 24 * 30, //month
|
|
}
|
|
});
|
|
|
|
const useSession = (req, res, next) => {
|
|
sessionStore(req, res, next);
|
|
};
|
|
|
|
const fetchSession = async (req, res, next) => {
|
|
if (req.session.user) {
|
|
const account = await db.db.collection('accounts').findOne({_id:req.session.user});
|
|
if (account) {
|
|
res.locals.user = {
|
|
username: account._id,
|
|
domains: account.domains,
|
|
clusters: account.clusters,
|
|
activeCluster: account.activeCluster,
|
|
};
|
|
return next();
|
|
}
|
|
req.session.destroy();
|
|
}
|
|
next();
|
|
};
|
|
|
|
const checkSession = (req, res, next) => {
|
|
if (!res.locals.user) {
|
|
return dynamicResponse(req, res, 302, { redirect: '/login' });
|
|
}
|
|
next();
|
|
};
|
|
|
|
const csrfMiddleware = csrf();
|
|
|
|
//HAProxy-sdk middleware
|
|
const useHaproxy = (req, res, next) => {
|
|
if (res.locals.user.clusters.length === 0) {
|
|
return next();
|
|
}
|
|
try {
|
|
//uses cluster from account
|
|
res.locals.haproxy = new HAProxy(res.locals.user.clusters[res.locals.user.activeCluster]);
|
|
res.locals.fMap = server.locals.fMap;
|
|
res.locals.mapValueNames = server.locals.mapValueNames;
|
|
next();
|
|
} catch (e) {
|
|
return dynamicResponse(req, res, 500, { error: e });
|
|
}
|
|
};
|
|
|
|
const hasCluster = (req, res, next) => {
|
|
console.log(req.path)
|
|
if (res.locals.user.clusters.length > 0 || (req.baseUrl+req.path) === '/forms/cluster/add') {
|
|
return next();
|
|
}
|
|
return dynamicResponse(req, res, 302, { redirect: '/clusters' });
|
|
};
|
|
|
|
//Controllers
|
|
const accountController = require('./controllers/account')
|
|
, mapsController = require('./controllers/maps')
|
|
, clustersController = require('./controllers/clusters')
|
|
, domainsController = require('./controllers/domains');
|
|
|
|
//unauthed pages
|
|
server.get('/', useSession, fetchSession, (req, res, next) => { return app.render(req, res, '/index') });
|
|
server.get('/login', useSession, fetchSession, (req, res, next) => { return app.render(req, res, '/login') });
|
|
server.get('/register', useSession, fetchSession, (req, res, next) => { return app.render(req, res, '/register') });
|
|
|
|
//register/login/logout forms
|
|
server.post('/forms/login', useSession, accountController.login);
|
|
server.post('/forms/logout', useSession, accountController.logout);
|
|
server.post('/forms/register', useSession, accountController.register);
|
|
|
|
const mapNames = [process.env.BLOCKED_MAP_NAME, process.env.MAINTENANCE_MAP_NAME, process.env.WHITELIST_MAP_NAME,
|
|
process.env.BACKENDS_MAP_NAME, process.env.DDOS_MAP_NAME, process.env.HOSTS_MAP_NAME]
|
|
, mapNamesOrString = mapNames.join('|');
|
|
|
|
//authed pages that dont require a cluster
|
|
server.get('/account', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, accountController.accountPage.bind(null, app));
|
|
server.get('/account.json', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, accountController.accountJson);
|
|
|
|
server.get(`/map/:name(${mapNamesOrString})`, useSession, fetchSession, checkSession, useHaproxy, hasCluster, csrfMiddleware, mapsController.mapPage.bind(null, app));
|
|
server.get(`/map/:name(${mapNamesOrString}).json`, useSession, fetchSession, checkSession, useHaproxy, hasCluster, csrfMiddleware, mapsController.mapJson);
|
|
|
|
server.get('/clusters', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, clustersController.clustersPage.bind(null, app));
|
|
server.get('/clusters.json', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, clustersController.clustersJson);
|
|
|
|
server.get('/domains', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, domainsController.domainsPage.bind(null, app));
|
|
server.get('/domains.json', useSession, fetchSession, checkSession, useHaproxy, csrfMiddleware, domainsController.domainsJson);
|
|
|
|
//authed pages that useHaproxy
|
|
const clusterRouter = express.Router({ caseSensitive: true });
|
|
clusterRouter.post('/global/toggle', accountController.globalToggle);
|
|
clusterRouter.post('/cluster', clustersController.setCluster);
|
|
clusterRouter.post('/cluster/add', clustersController.addCluster);
|
|
clusterRouter.post('/cluster/delete', clustersController.deleteClusters);
|
|
clusterRouter.post('/domain/add', domainsController.addDomain);
|
|
clusterRouter.post('/domain/delete', domainsController.deleteDomain);
|
|
clusterRouter.post(`/map/:name(${mapNamesOrString})/add`, mapsController.patchMapForm); //add to MAP
|
|
clusterRouter.post(`/map/:name(${mapNamesOrString})/delete`, mapsController.deleteMapForm); //delete from MAP
|
|
server.use('/forms', useSession, fetchSession, checkSession, useHaproxy, hasCluster, csrfMiddleware, clusterRouter);
|
|
|
|
};
|
|
|
|
module.exports = testRouter;
|
|
|