import express,{Request,Response} from "express"; import compression from "compression"; import path from "path"; import morgan from "morgan"; import cors,{CorsOptions} from "cors"; import cookieParser from "cookie-parser"; import session,{SessionOptions} from "express-session"; import mongo from "connect-mongo"; import helmet from "helmet"; import csrf from "csurf"; import lusca from "lusca"; import bodyParser from "body-parser"; import flash from "express-flash"; import passport from "passport"; import errorhandler from "errorhandler"; import {AppMasterMiddlewareType} from "./types"; import {Handler,ErrorHandler} from "@onebro/oba-common"; import {morganMsgFormats,morganMsgTokens,checkWhitelist} from "./utils"; import * as ob from "@onebro/oba-common"; const MongoStore = mongo(session); export const amMiddlewares:AppMasterMiddlewareType = { public:(a,o) => { const publicPath = path.join(o.dirname,"public"); a.use(express.static(publicPath,o));}, views:(a,o) => { a.set("views",path.join(o.dirname,"../views")); a.set("view engine",o.engine);}, compression:(a) => {a.use(compression());}, morgan:(a,o,m) => { const {useDev,useLogger} = o; const {logger} = m; const formats = morganMsgFormats; for(const k in morganMsgTokens) morgan.token(k,morganMsgTokens[k]); if(useDev) a.use(morgan("dev")); if(useLogger && logger && logger.access){ for(const k in formats){ let o = {}; switch(k){ case "access":o = {stream:{write:logger.access.bind(logger)}};break; case "warn":o = {skip:(req:Request) => !req.warning,stream:{write:logger.warn.bind(logger)}};break; case "error":o = {skip:(req:Request) => !req.error,stream:{write:logger.error.bind(logger)}};break;} a.use(morgan(formats[k],o));}}}, cors:(a,o,m) => { const {origins,preflightContinue,credentials} = o; const opts:CorsOptions = Object.assign({},{ preflightContinue, credentials, origin:(origin:string,done:Function) => { const whitelist = [...origins,...m.vars.whitelist]; return checkWhitelist(origin,whitelist)? done():done(m.e.cors());}}); a.use(cors(opts));}, cookieParser:(a,o) => {a.use(cookieParser(o.secret));}, bodyParser:(a,o) => { const {json,urlencoded,raw} = o; if(json) a.use(bodyParser.json(json)); if(urlencoded) a.use(bodyParser.urlencoded(urlencoded)); if(raw) a.use(bodyParser.raw(raw));}, session:(a,o) => { const mongoStore = o.store?{store:new MongoStore(o.store)}:null; const opts:SessionOptions = Object.assign({},o,mongoStore); a.use(session(opts));}, lusca:(a,o) => { const csrfCookie = o.csrf&&(o.csrf).cookie?(o.csrf).cookie:null; const cookieName = ob.str(csrfCookie)?csrfCookie:csrfCookie.name; const handler:Handler = async (req,res,next) => { const csrf = req.cookies[cookieName]; if(csrf) req.body && csrf?(req.body._csrf = csrf):null && ob.trace({csrf}); return next();}; ob.trace({csrfCookie}); csrfCookie?a.use(handler):null; a.use(lusca(o));}, csrf:(a,o) => { const handler:Handler = async (req,res,next) => { res.cookie("XSRF-TOKEN",req.csrfToken()); return next();}; a.use(csrf(o)); a.use(handler);}, flash:(a) => {a.use(flash());}, errorhandler:(a) => {a.use(errorhandler());}, passport:(a) => {a.use(passport.initialize());}, pageNotFound:(a,o,m) => { const handler:Handler = async (req,res,next) => next(m.e.notfound()); a.use(handler);}, finalHandler:(a,o,m) => { const handler:ErrorHandler = (e,req,res,next) => { let _e:ob.AppError; switch(true){ case e instanceof ob.AppError:_e = e as ob.AppError;break; case !!(e as ob.ValidationErrors).errors:_e = Object.assign(m.e.validation(),e);break; default: _e = m.e.map(e);break;} if(_e.status >= 500) ob.traceError(_e); req.error = _e; if(res.headersSent){ob.warn("response already sent",_e.message);return;} res.status(_e.status).json({ name:_e.name, message:_e.message, errors:_e.errors, status:_e.status, code:_e.code, info:_e.info});}; a.use(handler);}, }; /* "lusca":{ "csrf": {"cookie":"_ckey"}, "xframe":"SAMEORIGIN", "p3p":"ABCDEF", "hsts":{ "maxAge":31536000, "includeSubDomains":true, "preload":true}, "xssProtection":true, "nosniff":true, "referrerPolicy":"same-origin"}, helment:MiddlewareSetter<"helmet"> = (a,o) => { const csrfCookie = o.csrf&&(o.csrf).cookie?(o.csrf).cookie:null; const cookieName = str(csrfCookie)?csrfCookie:csrfCookie.name; const handler:Handler = (req,res,next) => { const csrf = req.cookies[cookieName]; if(csrf) req.body && csrf?(req.body._csrf = csrf):null && trace({csrf}); return next();}; trace({csrfCookie}); csrfCookie?a.use(handler):null; a.use(helmet(o));}; */