Moved backend to a separate directory

This commit is contained in:
Sebastian Seedorf
2020-11-24 00:39:20 +01:00
parent f7d790818a
commit ef3af370fd
16 changed files with 9 additions and 17 deletions

81
backend/src/app.ts Normal file
View File

@@ -0,0 +1,81 @@
import * as createError from 'http-errors';
import * as express from 'express';
import {NextFunction, Request, Response} from 'express';
import * as path from 'path';
import * as sassMiddleware from 'node-sass-middleware';
import * as compression from 'compression';
import indexRouter from './routes';
import {AuthProxy, AutoReloader, DefaultConfig, HttpLogger, Polyfill, PermManager} from 'pkg-express-utils';
export const app = express();
// Permissions
PermManager
.grant('user')
.execute('read').on('userinfo')
.grant('coe_bs')
.extend('user')
.execute('write').on('userinfo');
// view engine setup
app.set('views', path.join(__dirname, '../views'));
app.set('view engine', 'pug');
app.use((req, res, next) => {
res.locals.DefaultConfig = DefaultConfig;
next();
});
// http logger
app.use(HttpLogger);
app.use(express.json());
app.use(express.urlencoded({extended: false}));
// compression
app.use(compression());
const router = express.Router();
// auth proxy middleware
router.use(AuthProxy.router);
// auto reloader (when running in debug mode)
router.use(AutoReloader.getRouter({
frontendDirs: './public',
}));
// session
//router.use(Session.getRouter());
// static config
router.use('/js/polyfill.js', Polyfill.getRouter('./public/js/bundle.js'));
router.use(sassMiddleware({
src: path.join(__dirname, '../../public'),
dest: path.join(__dirname, '../../public'),
indentedSyntax: true, // true = .sass and false = .scss
sourceMap: true,
}));
router.use(express.static(path.join(__dirname, '../../public')));
router.use(indexRouter);
app.use(DefaultConfig.BASE_PATH, router);
// catch 404 and forward to error handler
app.use((req, res, next) => {
next(createError(404));
});
// error handler
app.use((err: Error&{status?: number}, req: Request, res: Response, next: NextFunction) => {
if (res.headersSent) {
return next(err);
}
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = !DefaultConfig.isProduction ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
return undefined;
});

View File

@@ -0,0 +1,21 @@
/* eslint-disable no-process-exit,no-console */
import * as http from 'http';
import {DefaultConfig, urlJoin} from 'pkg-express-utils';
const options = {
host: DefaultConfig.HOSTNAME,
port: DefaultConfig.PORT,
path: urlJoin(DefaultConfig.BASE_PATH, '/health'),
timeout: 2000,
};
const healthCheck = http.request(options, (res) => {
process.exit(res.statusCode == 200 ? 0 : 1);
});
healthCheck.on('error', (err) => {
console.error('HEALTHCHECK ERROR', err);
process.exit(1);
});
healthCheck.end();

42
backend/src/index.ts Normal file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/env node
/* eslint-disable no-process-exit */
import * as http from 'http';
import {app} from './app';
import {HttpError} from 'http-errors';
import {DefaultConfig, Logger} from 'pkg-express-utils';
app.set('port', DefaultConfig.PORT);
const server = http.createServer(app);
server.on('error', onError);
server.on('listening', onListening);
server.listen(DefaultConfig.PORT);
function onError(error: HttpError): void {
if (error.syscall !== 'listen') {
Logger.error(error);
}
switch (error.code) {
case 'EACCES':
Logger.error(DefaultConfig.PORT + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
Logger.error(DefaultConfig.PORT + ' is already in use');
process.exit(2);
break;
default:
Logger.error(error);
process.exit(3);
}
}
function onListening(): void {
const addr = server.address();
const bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + (addr ?? {port: undefined}).port;
Logger.debug('Listening on ' + bind);
}

View File

@@ -0,0 +1,11 @@
import * as express from 'express';
import {PermManager} from 'pkg-express-utils';
const userRouter = express.Router();
/* GET user info. */
userRouter.get('/', PermManager.getRouter('userinfo', {action: 'read'}), async (req, res) => {
res.json(await req.getUserInfo() || {});
});
export default userRouter;

View File

@@ -0,0 +1,10 @@
import * as express from 'express';
const healthRouter = express.Router();
healthRouter.get('/', async (req, res) => {
req.noHttpLogging = true;
res.sendStatus(200);
});
export default healthRouter;

View File

@@ -0,0 +1,19 @@
import * as express from 'express';
import userRouter from './api/user';
import healthRouter from './healthcheck';
const router = express.Router();
export default router;
router.use('/api/user', userRouter);
router.use('/health', healthRouter);
/* GET home page. */
router.get('/', async (req, res) => {
const email = (await req.getUserInfo())?.email ?? 'No email found!';
res.render('index', {title: 'Express', email});
});
router.get('/logout', (req, res) => {
res.initLogout();
});

23
backend/src/types/extend-request.d.ts vendored Normal file
View File

@@ -0,0 +1,23 @@
// extend-request.d.ts
declare global {
namespace Express {
interface Request {
// fetch user info (needs AuthProxy and some headers)
getUserInfo(): Promise<import('pkg-express-utils').UserInfo|undefined>;
// fetch user info (needed for HttpLogger)
noHttpLogging: boolean|undefined;
// permission details (after a Permission route)
permissionDetails: import('role-acl').Permission;
// switch session to another user;does not close old session (after Session router)
setSessionById(sessionId: string): Promise<boolean>;
}
interface Response {
// initialize a logout (needs AuthProxy and some headers)
initLogout(): boolean;
}
}
}
export {};