/**
 * Minified by jsDelivr using Terser v5.39.0.
 * Original file: /npm/oils@12.3.0/core/Web.js
 *
 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
 */
"use strict";const extend=Object.assign,express=require("express"),domain=require("domain"),mongoose=require("mongoose"),Schema=mongoose.Schema,flash=require("connect-flash"),path=require("path"),fs=require("fs"),TokensCsrf=require("csrf"),routeUtils=require("./utils/routeUtils"),stringUtils=require("./utils/stringUtils.js"),callsites=require("callsites"),webExtender=require("./loaders/webExtender.js"),{customAlphabet:customAlphabet}=require("nanoid/non-secure"),nanoidInsecure=customAlphabet("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",10),_WebSetting={name:"_WebSetting",schema:{key:{type:String,unique:!0,index:!0},val:{type:String},updateDt:{type:Date,default:Date.now}}},wsCsrfKey="CSRF_SECRET";class Web{constructor(e={}){const t=this;t.lib=t.lib||{};let n=nanoidInsecure();t.id=n,Object.defineProperty(t.lib,"mongoose",{get:function(){let e=(new Error).stack;return console.warn("Use web.require('mongoose') instead of calling web.lib..",e),mongoose}}),global._web||(global._web={});let o={},r=e.baseDir||getBaseDirFromNodeModules(callsites()[0].getFileName());if(r||(console.warn("Cannot get base dir from callsites, trying dirname"),r=getBaseDirFromNodeModules(__dirname)),r||(console.warn("Cannot get base dir. Last resort: process dir"),r=process.cwd()),!r)throw new Error("Web's baseDir should not be empty");if(console.debug("Setting base dir to ",r),o.baseDir||(o.baseDir=r),global._web[o.baseDir])throw new Error("Web has been redefined: "+o.baseDir+" vs "+r);if(global._web[o.baseDir]=t,global._webLength=Object.keys(global._web).length,global.hasOwnProperty("web")||Object.defineProperty(global,"web",{get:function(){if(1===global._webLength)return t;let e=callsites()[1].getFileName();for(let t in global._web)if(stringUtils.startsWith(e,t))return global._web[t];throw new Error(`Web cache not found: ${o.baseDir}.`)}}),t.conf=require("./conf/conf-default.js")(),t.conf=extend(t.conf,o),t.conf.customConfigFile){let e=requireNvm(path.join(t.conf.baseDir,t.conf.customConfigFile));e&&(t.conf=extend(t.conf,e))}if(t.conf.pluginsConfPath&&(console.log("Reading plugins conf",t.conf.pluginsConfPath),t.conf.plugins=t.conf.plugins||{},t.conf.plugins=extend(t.conf.plugins,t.includeNvm(t.conf.pluginsConfPath))),!0===t.conf.zconf){let e=requireNvm(path.join(t.conf.baseDir,"conf","zconf.js"));e&&(console.info("Found zconf... extending."),t.conf=extend(t.conf,e))}else if(t.conf.zconf){let e=requireNvm(t.conf.zconf);e?(t.conf=extend(t.conf,e),console.info("Found zconf.. extending.")):console.warn(t.conf.zconf,"not found. Ignoring.")}if(e&&(t.conf=extend(t.conf,e)),t.conf.webId=t.id,Object.keys(global._web).length<=1)t.logger=require("./utils/logger.js")(t.conf);else for(let e in global._web)if(global._web[e].logger){t.logger=global._web[e].logger;break}console.isDebug=t.conf.isDebug,console.isDebug&&console.debug("Oils config: "+JSON.stringify(t.conf,null,2)),t.app=express(),fixOpenRedirect(t),t.events={},t.modelCache=new Object,t.plugins=[],t.overrideResponse(),t.conf.extendWeb&&t.conf.extendWeb.enabled&&webExtender.load(t,t.conf.extendWeb.path,t.conf.extendWeb.context),console.log("Done with web constructor")}require(e){try{return require(e)}catch(t){throw new Error("Error web.require path: "+e,{cause:t})}}overrideResponse(){const e=this,t=express.response.render;e.on("beforeRender",e.initBeforeRender),express.response.render=function(n,o={},r){const s=this.req;e.callEvent("beforeRender",[n,o,r,s,this]),t.apply(this,[n,o,r])},express.response.renderFile=express.response.render}initBeforeRender(e,t,n,o,r){const s=this;o.flash&&(t._errors=o.flash("error"),t._warns=o.flash("warn"),t._infos=o.flash("info")),t._conf=s.conf.viewConf,t._ext=o.ext,s._shouldEnableCsrf(o)&&(t._csrf=s.genCsrfToken())}_handleCsrf(e){let t=this;if(t.conf.enableCsrfToken&&"POST"===e.method){let n=t._shouldEnableCsrf(e),o=t.conf.enableCsrfToken.excludes;if(o&&o.length)for(let t of o)(t instanceof RegExp&&t.test(e.path)||e.path===t)&&(n=!1);if(n){if(!t.csrfTokens.verify(t._getSecretToken(),e.body._csrf))throw new Error("Please try to submit the form again. Token verification failed.");web.conf.isDebug&&console.debug("Successfully verified csrf:",e.body._csrf)}}}_shouldEnableCsrf(e){if(!this.conf.enableCsrfToken)return!1;if(e._oilsController){if(!1===e._oilsController.enableCsrfToken)return!1;if(!e._oilsController.post)return!1}return void 0===e.enableCsrfToken||e.enableCsrfToken}_getSecretToken(){return this.getWebSettingVal(wsCsrfKey)}async _initCsrfSecretToken(){if(!this.conf.enableCsrfToken)return;let e=this.getWebSettingObj(wsCsrfKey);if(e&&Math.abs((new Date).getTime()-e.updateDt.getTime())<this.conf.csrfSecretRefreshMs)return e.val;let t=this.csrfTokens.secretSync();return this.setWebSetting(wsCsrfKey,t),this.conf.isDebug&&console.debug("Refreshed csrf secret"),t}async _initWebSettingVals(){await this._initCsrfSecretToken()}async _initWebSettingRefresh(){this._getWebSettingModel();const e=this;this.syncedSetting||(e.syncedSetting={}),await this._refreshWebSettings(),await this._initWebSettingVals(),setInterval((()=>{e._refreshWebSettings()}),e.conf.refreshWebSettingInt)}async _refreshWebSettings(){const e=this._getWebSettingModel();let t=await e.find({}).lean().exec();for(let e of t)this.syncedSetting[e.key]=e;this.conf.isDebug&&console.debug("Web setting refreshed:",Object.keys(this.syncedSetting))}_getWebSettingModel(){return this.modelCache._WebSetting||this.includeModelObj(_WebSetting)}getWebSettingObj(e){if(!this.syncedSetting)throw new Error("Web setting not yet initialized. Only usable after connection has been initiated.");return this.syncedSetting[e]}getWebSettingVal(e){return this.getWebSettingObj(e).val}setWebSetting(e,t){let n=this.syncedSetting[e];t!==(n&&n.val)&&(this.syncedSetting[e]={key:e,val:t,updateDt:new Date},this._updateSettingToDb(e,t))}async _updateSettingToDb(e,t){const n=this._getWebSettingModel();if(!this.syncedSetting[e])throw new Error("Web setting not found: "+e);await n.findOneAndUpdate({key:e},{key:e,val:t,updateDt:new Date},{upsert:!0}).exec();this.conf.isDebug&&console.debug("Updated web setting to DB:",e)}genCsrfToken(){return this.conf.enableCsrfToken?this.csrfTokens.create(this._getSecretToken()):""}on(e,t){this.events[e]||(this.events[e]=[]),this.events[e].push(t)}callEvent(e,t){let n=this.events[e];if(n)for(let e of n)e.apply(this,t)}async call(e,t){let n=this.events[e];if(n)for(let o of n)try{await o.apply(this,t)}catch(t){console.error("Error loading one event",e,t)}}include(e){try{return require(this.includeFullPath(e))}catch(t){throw new Error("Error web.include path: "+e,{cause:t})}}includeNvm(e){return requireNvm(this.includeFullPath(e))}includeFullPath(e){this.conf.baseDir||process.cwd();return path.join(this.conf.baseDir,e)}includeModelObj(e){let t,n,o=this,r=e.name;if(!e.schema)throw new Error(r+".schema not found.");if(e.parentModel){let n=o.includeModel(e.parentModel),s=n.getModelDictionary();t=n.collection.name,e.schema=extend(s.schema,e.schema);let i=e.initSchema;e.initSchema=[],i&&e.initSchema.push(i),s.initSchema&&e.initSchema.push(s.initSchema),e.options=extend(n.options||{},e.options),console.isDebug&&console.debug("Model %s has a parent %s",r,e.parentModel)}let s=function(e){return e.connection?e.connection:e.parentModel?s(o.include(e.parentModel)):void 0},i=s(e);if(i)n=this.connections[i],o.conf.isDebug&&console.debug("Found model conn: ",e.name,i);else if(o.connections.mainDb)n=o.connections.mainDb;else for(let e in this.connections){n=this.connections[e];break}if(!n)return void console.warn("No defined DB. Check your configuration.");let c=new Schema(e.schema,e.options);if(e.initSchema)if(e.initSchema instanceof Array)for(let t in e.initSchema){(0,e.initSchema[t])(c)}else e.initSchema.execd||e.initSchema(c);let l=n.model(r,c,t);return console.isDebug&&console.debug("Loaded model for the first time: "+r),o.modelCache[r]=l,l.getModelDictionary=function(){return e},l}includeModel(e){let t=this,n=null;if(n=t.include(e),!n.name){if(!e)throw new Error("Model name must be defined.");n.name=path.basename(e,".js")}return t.modelCache[n.name]?(console.isDebug&&console.debug("Loading model %s from cache",n.name),t.modelCache[n.name]):t.includeModelObj(n)}models(e){if(!this.modelCache[e]){let t=this.conf.modelsDir+"/"+e;this.modelCache[e]=this.includeModel(t)}return this.modelCache[e]}addPlugin(e){this.plugins[e.id]=e}async loadPlugins(e){let t=this,n=function(){};for(let e in t.plugins){let o=t.plugins[e];try{await o.load(o.conf,t,n)}catch(t){console.error("Error loading plugin",e,t)}}e&&e()}applyRoutes(e){(new Error).stack;this._applyRoutes(e)}_applyRoutes(e){for(let t in e){let n=e[t];console.isDebug&&console.debug("[conf.route] "+t),routeUtils.applyRoute(web,t,n)}}addRoutes(e){this.conf.routes=this.conf.routes||{};for(let t in e)this.conf.routes[t]&&console.warn("Check conflicting routes:",t,confRoutes),this.conf.routes[t]=e[t]}async initServer(e){const t=this.app,n=this,o=this,r=require("body-parser"),s=require("method-override"),i=require("connect-mongo");if(n.conf.https&&n.conf.https.enabled||n.conf.httpsOpts.httpsEnabled){let e=require("./conf/conf-https-default.js")(n),t=e.letsEncrypt||{},o=n.conf.https&&n.conf.https.letsEncrypt;n.conf.https=extend(e,n.conf.https||{}),n.conf.https.letsEncrypt=extend(t,o||{},n.conf.httpsOpts.letsEncrypt)}let c=path.join(o.conf.baseDir,o.conf.viewsDir);o.conf.templateLoader?o.templateEngine=o.conf.templateLoader(n,c):o.templateEngine=require("./engines/nunjucks")(n,c);var l=function(e,t,o,r){n.conf.saveRawBody&&o&&o.length&&(e.rawBody=o.toString(r||"utf8"))};if(n.conf.trustProxy&&(console.log("Trusting proxy",n.conf.trustProxy),t.set("trust proxy",n.conf.trustProxy)),t.use(r.json({limit:n.conf.parserLimit,verify:l,parameterLimit:n.conf.parserParameterLimit})),t.use(r.urlencoded({extended:!0,limit:n.conf.parserLimit,verify:l,parameterLimit:n.conf.parserParameterLimit})),n.conf.saveRawBody){console.warn("conf.saveRawBody uses a raw parser that conflicts with multer. Better maybe to save raw data in controller level instead.");let e=r.raw({verify:l,type:"*/*",limit:n.conf.parserLimit,parameterLimit:n.conf.parserParameterLimit});t.use((function(t,o,r){!n.conf.saveRawBody.only||t.path&&n.conf.saveRawBody.only.includes(t.path)?e(t,o,r):r()}))}t.use(s());let a=n.conf.secretPassphrase;if("change-this-it-is-2019!"===a)throw new Error("Security error. Change conf.secretPassphrase.");if(n.conf.bypassSession)t.use((function(e,t,n){e.session={},n()})),console.warn("Skipping session handling due to bypassSession: true");else{const e=require("express-session");let o={name:"oils-session",secret:a,store:i.create({mongoUrl:n.conf.connections.mainDb.url,touchAfter:86400})};Object.assign(o,n.conf.sessionOpts),t.use(e(o))}t.use((function(e,t,n){e.csrfToken=function(){return o.genCsrfToken()},n()})),await o.call("afterWebMiddleware"),t.use(require("./middleware/custom-response.js")()),n.conf.bypassSession?(t.use((function(e,t,n){e.flash=function(){console.warn("req.flash is disabled due to config")},n()})),console.warn("Skipping flash handling due to bypassSession: true")):t.use(flash()),n.conf.validateNoSqlInject&&(console.log("Adding validation for nosql injection"),t.use((function(e,t,o){let r=!1;try{n.validateNoSqlInject(e.query),n.validateNoSqlInject(e.body),n.validateNoSqlInject(e.params),r=!0}catch(n){console.error("Error in validation nosql",n);var s=e.header("x-forwarded-for")||e.connection&&e.connection.remoteAddress;console.error("[ALERT] Possible NOSQL injection",e.url,e.query,e.body,e.params,s,e.user),t.status(400).send("Invalid Request")}r&&o()}))),await require("./loaders/connections.js")(o),o.conf.enableCsrfToken&&(o.csrfTokens=new TokensCsrf),await o._initWebSettingRefresh(),require("./loaders/plugins.js")(o),await o.loadPlugins(),await o.call("loadPlugins");let f=o.conf.routes||{};f=extend(o.includeNvm(o.conf.routesFile)||{},f),o.conf.routes=f,o._applyRoutes(o.conf.routes),await require("./loaders/controllers")(o),o.conf.enableCsrfToken&&o.conf.enableCsrfToken.universal&&t.use((function(e,t,r){try{o._handleCsrf(e),r()}catch(o){console.error("Error Web's _handleCsrf:",o),n.conf.handleCsrfFailure(o,e,t)}})),t.use(o.conf.publicContext,express.static(path.join(o.conf.baseDir,o.conf.publicDir),{maxAge:o.conf.staticMaxAge})),await o.call("initServer"),t.use((function(e,t,o,r){try{n.conf.handle500?n.conf.handle500(e,t,o,r):o.status(500).send("This is embarrassing."),console.error("General error",e)}catch(e){console.error("Critical error at error handling, please fix:",e)}})),e&&await e()}validateNoSqlInject(e){if(e)for(let t in e){if(t&&"$"===t[0])throw console.error("Invalid key found",t),new Error("Invalid request [999]");e[t]&&"object"==typeof e[t]&&this.validateNoSqlInject(e[t])}return e}getLetsEncryptLex(){let e=this;if(!e.lex){if(!e.conf.https.letsEncrypt.email)throw new Error("conf.https.letsEncrypt.email must not be nil.");let t=e.conf.https.letsEncrypt.testing?e.conf.https.letsEncrypt.stagingServer:e.conf.https.letsEncrypt.prodServer;if(e.conf.https.letsEncrypt.server=e.conf.https.letsEncrypt.server||t,e.stringUtils.isEmpty(e.conf.https.letsEncrypt.server))throw new Error("Cannot find encrypt server.");if(!e.conf.https.letsEncrypt.approveDomains)throw new Error("conf.https.letsEncrypt.approveDomains must not be nil. See wildcard.js example from greenlock-express");console.isDebug&&console.debug("Server:",t,"with https conf:",e.conf.https),e.lex=require("greenlock-express").create(e.conf.https.letsEncrypt)}return e.lex}start(e){let t=domain.create();t.on("error",(function(e){console.error("Server domain caught an exception:",e)}));let n=this;t.run((function(){n.initServer((function(){startServer(n,e)}))}))}}function _applyRoutes(e){for(let t in e){let n=e[t];console.isDebug&&console.debug("[conf.route] "+t),routeUtils.applyRoute(web,t,n)}}function requireNvm(e){try{return require(e)}catch(t){if("MODULE_NOT_FOUND"===t.code)return console.isDebug&&console.debug("Ignoring file not found through requireNvm",e),null;throw t}console.error("[requireNvm] Unexpected end")}async function sleep(e){return new Promise((function(t,n){return setTimeout(t,e)}))}function startListening(e,t={},n){const{port:o,ipAddress:r,addtlLog:s=""}=t;e.listen(o,r,(function(i,c){i?console.error("Error starting node server",i):console.log("%s: Node server started on %s:%d %s...",Date(Date.now()),r,o,s),n&&n(i,e,t)}))}function defaultRedirectToHttpsMiddleware(e,t){let n,o="",r=web.conf.httpsOpts.port||web.conf.https.port;443!==r&&(o=":"+r),n=e.headers.host?e.headers.host.split(":")[0]:e.hostname,t.writeHead(302,{Location:"https://"+n+o+e.url}),t.end()}function fixOpenRedirect(e){let t=e.app.response.redirect;e.app.response.redirectSafe=function(e){return t.call(this,e)};let n=!0,o=!0;e.app.response.redirect=function(r,s){let i,c;if(isNaN(r)?i=r:(c=r,i=s),i&&-1!=i.indexOf("://")){let t=this.req;if(n){let o=t.protocol+"://"+t.headers.host;e.conf.allowedRedirectHosts.push(o),n=!1,console.log("Added host once: "+o)}if(o&&t.subdomains&&!t.subdomains.length){let n=t.protocol+"://www."+t.headers.host;e.conf.allowedRedirectHosts.push(n),o=!1,console.log("Added www host once: "+n)}if(!e.conf.allowedRedirectHosts.find((e=>0==i.indexOf(e)))){var l=e.utils.getClientIp(t);throw console.warn("Open redirect vulnerability was triggered: ",i,t.method,t.user?t.user.email:"unsigned user",l,"accessed",t.url,t.headers["user-agent"]),new Error("Action not allowed.")}}return t.call(this,i)}}function getBaseDirFromNodeModules(e){return e.substr(0,e.indexOf("node_modules")-1)}function startServer(e,t){const n=require("http");let o=null,r=function(e){return e};if(e.conf.https&&e.conf.https.enabled||e.conf.httpsOpts.httpsEnabled){if(e.conf.https.letsEncrypt){let n=e.conf.https.getHttpsServer(),o=e.getLetsEncryptLex(),s=e.conf.https.port||443;r=o.middleware,startListening(n.createServer(o.httpsOptions,r(e.app)),{port:s,ipAddress:e.conf.ipAddress,addtLog:"(HTTPS)"},t)}else{let n=e.conf.https.getHttpsServer(),o={key:fs.readFileSync(e.conf.https.privateKey,"utf8"),cert:fs.readFileSync(e.conf.https.certificate,"utf8")};n.createServer(o,e.app);startListening(httpServer,{port:e.conf.port,ipAddress:e.conf.ipAddress,addtlLog:"(HTTPS)"},t)}o=e.conf.https.alwaysSecure}if(o&&o.enabled||e.conf.httpsOpts.alwaysSecure){let s=o.redirectHandler||defaultRedirectToHttpsMiddleware;startListening(n.createServer(r(s)),{port:e.conf.port,ipAddress:e.conf.ipAddress},t)}else{startListening(n.createServer(r(e.app)),{port:e.conf.port,ipAddress:e.conf.ipAddress},t)}}Web.prototype.utils=require("./utils/oilsUtils.js"),Web.prototype.fileUtils=require("./utils/fileUtils.js"),Web.prototype.dateUtils=require("./utils/dateUtils.js"),Web.prototype.stringUtils=stringUtils,Web.prototype.objectUtils=require("./utils/objectUtils.js"),Web.prototype.sleep=sleep,Web.prototype.Plugin=require("./Plugin.js"),module.exports=Web;
//# sourceMappingURL=/sm/33459289c0f71f578f9c2d1a41aadbd5e52e77dd6ca60b649b0708f71a6a3d60.map