-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
1 lines (1 loc) · 26.3 KB
/
index.js
1
(()=>{var e={372:(e,t,s)=>{const a=s(514),{knexSnakeCaseMappers:i}=s(419);e.exports=a({client:"mysql2",connection:{database:process.env.DB_NAME,host:process.env.DB_HOST,port:process.env.DB_PORT,user:process.env.DB_USER,password:process.env.DB_PASS,typeCast:(e,t)=>{if("TINY"===e.type){const t=e.string();return t?"1"===t:null}return t()}},migrations:{directory:"./database/migrations"},seeds:{directory:"./database/seeds"},acquireConnectionTimeout:3e4,...i()})},516:(e,t,s)=>{const{Model:a}=s(419);e.exports=class extends a{static get tableName(){return"answers"}static get modifiers(){return{defaultSelects(e){e.select("answer","correct")}}}}},427:(e,t,s)=>{const{Model:a}=s(419);e.exports=class extends a{static get tableName(){return"categories"}static get relationMappings(){const e=s(256);return{languages:{relation:a.ManyToManyRelation,modelClass:e,join:{from:"categories.id",through:{from:"category_languages.categoryId",to:"category_languages.languageId"},to:"languages.id"}}}}}},649:(e,t,s)=>{const{Model:a}=s(419);e.exports=class extends a{static get tableName(){return"category_languages"}}},268:(e,t,s)=>{const{Model:a}=s(419);e.exports=class extends a{static get tableName(){return"images"}static get modifiers(){return{defaultSelects(e){e.select("id","filename")},filenameOnly(e){e.select("filename")}}}}},256:(e,t,s)=>{const{Model:a}=s(419);e.exports=class extends a{static get tableName(){return"languages"}}},98:(e,t,s)=>{const{Model:a}=s(419);e.exports=class extends a{static get tableName(){return"questions"}static get relationMappings(){const e=s(268),t=s(516);return{image:{relation:a.BelongsToOneRelation,modelClass:e,join:{from:"questions.image_id",to:"images.id"}},answers:{relation:a.HasManyRelation,modelClass:t,join:{from:"questions.id",to:"answers.question_id"}}}}}},733:(e,t,s)=>{const{Model:a}=s(419);e.exports=class extends a{static get tableName(){return"users"}static get idColumn(){return"userid"}}},78:(e,t,s)=>{const a=s(421);e.exports={randomID:e=>a("?",e,{chars:123456789}),randomString:(e=21)=>a("*",e)}},758:(e,t,s)=>{const{createLogger:a,format:i,transports:n}=s(773),r=a({level:"info",format:i.combine(i.errors({stack:!0}),i.timestamp({format:"YYYY-MM-DD HH:mm:ss"}),i.printf((({level:e,message:t,timestamp:s,stack:a})=>a?`${s} ${e}: ${t}\n**STACK START**\n${a}\n**STACK END**`:`${s} ${e}: ${t}`))),defaultMeta:{service:"user-service"},transports:[new n.File({filename:"error.log",level:"error",maxsize:"50000000",maxFiles:"1"}),new n.File({filename:"combined.log",maxsize:"50000000",maxFiles:"1"})]});s.g.__logger=r},403:(e,t,s)=>{const a=s(372);e.exports={runAllMigrations:()=>a.migrate.latest(),runMigration:e=>a.migrate.up({name:e}),runSeed:e=>null!=e?a.seed.run({specific:e}):a.seed.run(),rollbackLastMigration:()=>a.migrate.down()}},247:(e,t)=>{t.incorrectCredentials={code:0,message:"Incorrect username or password"},t.setupAlreadyCompleted={code:0,message:"The application has already been set up"},t.dbAccessDenied={code:0,message:"Access denied. Check the database credentials then try again"},t.sessionExpired={code:22,message:"Session expired"},t.invalidImage={code:23,message:"The image is invalid or the image type is not allowed. Allowed types: png, jpg or jpeg"},t.imageTooBig=()=>({code:35,message:"The image is too big."})},547:e=>{e.exports={hasRole:function e(t){return e[t]||(e[t]=(e,s,a)=>{t!==e.role?s.sendStatus(403):a()})}}},134:(e,t,s)=>{const a=s(147),i=s(17).resolve(process.cwd(),"secrets.env");e.exports={secretsExist:()=>null!=process.env.DB_NAME||null!=process.env.DB_USER||null!=process.env.DB_USER||null!=process.env.DB_PASS||!!a.existsSync(i),createEnvFile:e=>{a.writeFileSync(i,e)}}},745:(e,t,s)=>{const a=s(17),i=new(s(242))({configName:"settings",cwd:a.resolve(process.cwd()),projectVersion:"1.0.0",clearInvalidConfig:!0,schema:{tokenDuration:{type:"number",maximum:12,minimum:1,default:1},imagesPerPage:{type:"number",maximum:100,minimum:1,default:24},imagesSearchResults:{type:"number",maximum:20,minimum:1,default:10},categoriesPerPage:{type:"number",maximum:100,minimum:1,default:24},categoriesSearchResults:{type:"number",maximum:20,minimum:1,default:5},iconFileMaxSize:{type:"number",maximum:1024,minimum:64,default:512},imageFileMaxSize:{type:"number",maximum:5120,minimum:64,default:1024},defaultQuestionLimit:{type:"number",maximum:1e3,minimum:1,default:50}}});e.exports={getAllSettings:()=>i.store,getSetting:(e,t=null)=>i.get(e,t),updateSetting:(e,t)=>{try{return i.set(e,t),!0}catch(e){return e}}}},23:(e,t,s)=>{const a=s(344),{sessionExpired:i}=s(247);e.exports={sign:(e,t)=>a.sign(e,process.env.JWT_SECRET,{expiresIn:t.toString()}),verify:(e,t,s)=>{let n=e.headers.authorization;if(null==n||""===n)return t.sendStatus(401);n=n.replace("Bearer ",""),a.verify(n,process.env.JWT_SECRET,((a,n)=>a?"TokenExpiredError"===a.name?t.status(401).send(i):"JsonWebTokenError"===a.name?t.sendStatus(401):(__logger.error(a),t.sendStatus(500)):null==n?t.sendStatus(401):(e.userid=n.userId,e.role=n.role,void s())))}}},320:(e,t,s)=>{const a=s(147),i=s(17),n=s(738),r=s(221),{randomID:o}=s(78),{getSetting:l}=s(745),{imageTooBig:d,invalidImage:u}=s(247),c=i.resolve(process.cwd(),"resources"),m=i.resolve(c,"images"),g=i.resolve(c,"icons"),p=n.diskStorage({destination:g,filename:(e,t,s)=>{s(null,e.body.id||o(5))}});e.exports={iconsFolder:()=>g,iconPath:e=>i.resolve(g,e),imagePath:e=>i.resolve(m,e),isValidFiletype:async e=>{const t=a.readFileSync(e),s=await r.fromBuffer(t);return null!=s&&("image/png"===s.mime||"image/jpeg"===s.mime)},uploadIcon:async(e,t,s)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");a.existsSync(g)||a.mkdirSync(g);const i=await l("iconFileMaxSize",512);n({storage:p,limits:{fileSize:1024*i}}).single("icon")(e,t,(async o=>{if(o)return o instanceof n.MulterError?void("LIMIT_FILE_SIZE"===o.code?t.status(400).send(d(i)):t.sendStatus(400)):(__logger.error(o),t.sendStatus(400));if(null!=e.file){const s=await async function(e){const t=a.readFileSync(e),s=await r.fromBuffer(t);return null!=s&&("image/png"===s.mime||"image/jpeg"===s.mime)}(e.file.path);if(!s)return a.rmSync(e.file.path,{force:!0}),t.status(400).send(u);e.body.id=e.file.filename}s()}))},uploadImage:async(e,t,s)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");a.existsSync(m)||a.mkdirSync(m);const i=await l("imageFileMaxSize",1024);n({dest:m,limits:{fileSize:1024*i}}).single("img")(e,t,(e=>{if(e)return e instanceof n.MulterError?void("LIMIT_FILE_SIZE"===e.code?t.status(400).send(d(i)):t.sendStatus(400)):(__logger.error(e),t.sendStatus(400));s()}))}}},315:(e,t,s)=>{const a=s(147),i=s(137),{matchedData:n,validationResult:r}=s(553),o=s(630);e.exports={rules:o,validate:(e,t,s)=>{const o=r(e);if(o.isEmpty())return e.matchedData=n(e,{includeOptionals:!0}),s();null!=e.file&&a.rmSync(e.file.path,{force:!0});const l=o.array({onlyFirstError:!0})[0],d=i(l.nestedErrors)?.msg??l.msg;t.status(422).send(d)}}},630:(e,t,s)=>{const{boolean:a}=s(75),{body:i,oneOf:n}=s(553),{getSetting:r}=s(745),o=/^[a-z][a-z0-9]+$/,l=/^[a-z][a-z_]+$/;e.exports={loginValidation:()=>[n([i("username","Invalid Username").notEmpty({ignore_whitespace:!0}),i("username","Invalid Email").isEmail().normalizeEmail()]),i("password","Invalid Password").notEmpty({ignore_whitespace:!0})],applicationSetupValidation:()=>[i("dbName","Invalid Database Name").notEmpty({ignore_whitespace:!0}).trim().toLowerCase().isLength({max:100}).withMessage("Database Name Too Long").matches(l),i("host","Invalid Host").notEmpty({ignore_whitespace:!0}),i("port","Invalid Port").isInt(),i("dbUser","Invalid Username").notEmpty({ignore_whitespace:!0}),i("dbPass","Invalid Password").customSanitizer((e=>null==e?"":e))],newUserValidation:()=>[i("email","Invalid Email").isEmail().normalizeEmail(),i("username","Invalid Username").toLowerCase().matches(o).isLength({min:3,max:100}).withMessage("The username should be 3 to 100 characters long"),i("password","Invalid Password").notEmpty({ignore_whitespace:!0}).isStrongPassword({minUppercase:0}).withMessage("The password is too weak. It should be at least 8 characters long and contain at least 1 number and symbol")],createCategoryValidation:()=>{const e=r("defaultQuestionLimit");return[i("id","Invalid ID").if(i("id").exists()).isInt().isLength({min:5,max:5}),i("name","Invalid Category Name").trim().notEmpty(),i("languages","Invalid Language IDs").notEmpty({ignore_whitespace:!0}).bail().customSanitizer((e=>e.split(","))).isArray({min:1}).custom((e=>{if(!e.every((e=>!isNaN(e))))throw new Error;return!0})).bail().customSanitizer((e=>e.map(Number))),i("active","Invalid Active Value").isBoolean().customSanitizer((e=>a(e))),i("enableTimer","Invalid Enable Timer Value").isBoolean().customSanitizer((e=>a(e))),i("timerAmount","Invalid Timer Amount").default(0).if(i("enableTimer").customSanitizer((e=>a(e))).matches(/true/)).isInt(),i("enableLives","Invalid Enable Lives Value").isBoolean().customSanitizer((e=>a(e))),i("livesAmount","Invalid Lives Amount").default(0).if(i("enableLives").customSanitizer((e=>a(e))).matches(/true/)).isInt(),i("limitQuestions","Invalid Limit Questions Value").isBoolean().customSanitizer((e=>a(e))),i("questionLimit","Invalid Question Limit").default(0).if(i("limitQuestions").customSanitizer((e=>a(e))).matches(/true/)).isInt({min:1,max:e}).withMessage(`Invalid Question Limit. Default limit: ${e}`)]},createQuestionValidation:()=>[i("id","Invalid ID").if(i("id").exists()).isInt().isLength({min:8,max:8}),i("categoryId","Invalid Category ID").isInt().isLength({min:5,max:5}),i("question","Invalid Question").trim().notEmpty({ignore_whitespace:!0}),i("explanation").if(i("explanation").isEmpty()).default(null),i("explanation","Invalid Explanation").if(i("explanation").notEmpty({ignore_whitespace:!0})).trim(),i("active","Invalid Active Value").isBoolean().customSanitizer((e=>a(e))),i("imageId").if(i("imageId").isEmpty()).default(null),i("imageId","Invalid Image ID").if(i("imageId").notEmpty({ignore_whitespace:!0})).isInt().isLength({min:8,max:8}),i("type","Invalid Question Type").isString().matches(/multi|tof/),i("tofAnswer","Invalid True or False Answer").if(i("type").matches(/tof/)).isBoolean().customSanitizer((e=>a(e))),i("tofAnswer").if(i("type").matches(/multi/)).customSanitizer((()=>!0)),i("answers").if(i("type").matches(/tof/)).customSanitizer((()=>null)),i("answers","Invalid Answers").if(i("type").matches(/multi/)).trim().notEmpty({ignore_whitespace:!0}).isJSON().bail().customSanitizer((e=>JSON.parse(e))).isArray({min:2,max:4}),i("answers.*.answer","Invalid Answer").if(i("type").matches(/multi/)).trim().notEmpty({ignore_whitespace:!0}),i("answers.*.correct","Invalid Answer").if(i("type").matches(/multi/)).isBoolean()],filtersValidation:()=>[i("filters","Invalid Filter Options").trim().notEmpty({ignore_whitespace:!0}).isJSON().bail().customSanitizer((e=>JSON.parse(e))),i("filters.sort","Invalid Sort Value").trim().matches(/^\w+\.((asc)|(desc))$/).bail().customSanitizer((e=>{const t=e.split(".");return{field:t[0],order:t[1]}})),i("filters.activeState","Invalid Active Value").if((e=>null!=e)).toLowerCase().isBoolean().customSanitizer((e=>"true"===e?1:0)),i("filters.enableTimer","Invalid Enable Timer Value").if((e=>null!=e)).toLowerCase().isBoolean().customSanitizer((e=>"true"===e?1:0)),i("filters.enableLives","Invalid Enable Lives Value").if((e=>null!=e)).toLowerCase().isBoolean().customSanitizer((e=>"true"===e?1:0)),i("filters.limitQuestions","Invalid Limit Questions Value").if((e=>null!=e)).toLowerCase().isBoolean().customSanitizer((e=>"true"===e?1:0))],settingsValidation:()=>[i("settings","Invalid Settings").trim().notEmpty({ignore_whitespace:!0}).isJSON().bail().customSanitizer((e=>JSON.parse(e)))],intValidation:(e="id",t="Invalid ID")=>[i(e,t).isInt()],stringValidation:(e="name",t="Invalid Name")=>[i(e,t).trim().notEmpty({ignore_whitespace:!0})],booleanValidation:(e="active",t="Invalid Active Value")=>[i(e,t).isBoolean().customSanitizer((e=>a(e)))]}},873:(e,t,s)=>{const a=s(860).Router();a.use("/login",s(593)),a.use("/setup",s(81)),e.exports=a},593:(e,t,s)=>{const a=s(860),i=a.Router(),n=s(432),{sign:r}=s(23),{incorrectCredentials:o}=s(247),{rules:l,validate:d}=s(315),u=s(372),{getSetting:c}=s(745);i.use(a.urlencoded({extended:!1})),i.post("/",l.loginValidation(),d,((e,t)=>{const s=e.matchedData.username,a=e.matchedData.password,i=s.indexOf("@")>0?{email:s}:{username:s};u("users").where(i).first().then((e=>{if(e){const s=e.password;n.compare(a,s,(async(s,a)=>{if(s)return t.sendStatus(500);if(!a)return t.status(401).send(o);const i=60*await c("tokenDuration",1)*60*1e3,n=r({userId:e.userid,role:e.role},i);t.send({access_token:n,expires_in:i})}))}else t.status(401).send(o)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),e.exports=i},81:(e,t,s)=>{const a=s(860),i=a.Router(),n=s(432),r=s(993),{v4:o}=s(828),{randomString:l}=s(78),{runMigration:d}=s(403),{rules:u,validate:c}=s(315),{secretsExist:m,createEnvFile:g}=s(134),{setupAlreadyCompleted:p,dbAccessDenied:h}=s(247),f=s(733);i.use(a.urlencoded({extended:!1})),i.post("/",u.applicationSetupValidation(),c,((e,t)=>{if(m())return t.status(403).send(p);const s=e.matchedData.dbName,a=e.matchedData.host,i=e.matchedData.port,n=e.matchedData.dbUser,o=e.matchedData.dbPass,d=l(40),u=r.createConnection({host:a,port:i,user:n,password:o}),c=`CREATE DATABASE IF NOT EXISTS \`${u.escape(s)}\``.replace(/'/g,"");u.query(c,(e=>{if(u.destroy(),e)return __logger.error(e),1045===e.errno?t.status(401).send(h):t.sendStatus(500);try{g(`DB_HOST="${a}"\nDB_PORT="${i}"\nDB_NAME="${s}"\nDB_USER="${n}"\nDB_PASS="${o}"\nJWT_SECRET="${d}"`)}catch(e){return __logger.error(e),t.sendStatus(500)}t.sendStatus(200)}))})),i.post("/user",u.newUserValidation(),c,(async(e,t)=>{const s=e.matchedData.email,a=e.matchedData.username,i=e.matchedData.password;try{await d("initial_schema.js")}catch(e){return __logger.error(e),t.sendStatus(500)}f.query().findOne({role:"superuser"}).then((e=>{if(e)t.sendStatus(403);else{const e=n.hashSync(i,12);f.query().insert({userid:o(),username:a,email:s,password:e,active:1,role:"superuser"}).then((()=>{t.sendStatus(200)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))}})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),e.exports=i},224:(e,t,s)=>{const a=s(147),i=s(860),n=i.Router(),{verify:r}=s(23),{hasRole:o}=s(547),{getSetting:l}=s(745),{iconPath:d,uploadIcon:u}=s(320),{rules:c,validate:m}=s(315),g=s(427),p=s(649),h=s(256);n.use(i.urlencoded({extended:!1})),n.get("/all/:lang_id",((e,t)=>{const s=e.params.lang_id;g.query().columns("id","name","enable_timer","timer_amount","enable_lives","lives_amount","limit_questions","question_limit","modified").orderBy("name","ASC").where({"categories.active":!0}).whereExists(g.relatedQuery("languages").where({"languages.id":s})).then((e=>{t.send(e)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),n.use(r,o("superuser")),n.post("/all",c.filtersValidation(),m,(async(e,t)=>{const s=e.matchedData.filters,a=e.query.page||0,i=null!=e.query.lang,n=await l("categoriesPerPage",24);try{const e=s?.languages.length>0?await g.query().orderBy(s.sort.field,s.sort.order).whereIn("categories.active",null==s.activeState?[0,1]:[s.activeState]).whereIn("categories.enable_timer",null==s.enableTimer?[0,1]:[s.enableTimer]).whereIn("categories.enable_lives",null==s.enableLives?[0,1]:[s.enableLives]).whereIn("categories.limit_questions",null==s.limitQuestions?[0,1]:[s.limitQuestions]).withGraphJoined("languages").whereIn("languages.id",s.languages):await g.query().orderBy(s.sort.field,s.sort.order).whereIn("active",null==s.activeState?[0,1]:[s.activeState]).whereIn("enable_timer",null==s.enableTimer?[0,1]:[s.enableTimer]).whereIn("enable_lives",null==s.enableLives?[0,1]:[s.enableLives]).whereIn("limit_questions",null==s.limitQuestions?[0,1]:[s.limitQuestions]).page(a,n).withGraphFetched("languages");let r=[];i&&(r=await h.query().orderBy("name")),(e?.results||e).forEach((e=>{e.languages=e.languages.flatMap((e=>e.id))}));const o=e?.results||e;t.send(i?{categories:o,languages:r,total:e.total||0,pageSize:n}:{categories:o,total:e.total||0,pageSize:n})}catch(e){__logger.error(e),t.sendStatus(500)}})),n.post("/search",(async(e,t)=>{const s=e.body.term,a=await l("categoriesSearchResults",5);g.query().orderBy("name").where("name","like",`%${s}%`).limit(a).withGraphFetched("languages").then((e=>{e.forEach((e=>{e.languages=e.languages.flatMap((e=>e.id))})),t.send(e)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),n.post("/create",u,c.createCategoryValidation(),m,(async(e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id,i=e.matchedData.name,n=e.matchedData.languages,r=e.matchedData.active,o=e.matchedData.enableTimer,l=e.matchedData.timerAmount,d=e.matchedData.enableLives,u=e.matchedData.livesAmount,c=e.matchedData.limitQuestions,m=e.matchedData.questionLimit;try{const e=await g.transaction((async e=>{await p.query(e).delete().where({categoryId:s});const t=await g.query(e).insertAndFetch({id:s,name:i,active:r,enableTimer:o,timerAmount:l,enableLives:d,livesAmount:u,limitQuestions:c,questionLimit:m,modified:g.fn.now()}).onConflict().merge(),a=[];return n.forEach((t=>{a.push(p.query(e).insert({categoryId:s,languageId:t}))})),await Promise.all(a),t.languages=n,t}));t.send(e)}catch(s){null!=e.file&&a.rmSync(e.file.path,{force:!0}),__logger.error(s),t.sendStatus(500)}})),n.post("/delete",c.intValidation(),m,(async(e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id;try{await g.query().deleteById(s),a.rmSync(d(s),{force:!0}),t.sendStatus(200)}catch(e){__logger.error(e),t.sendStatus(500)}})),e.exports=n},546:(e,t,s)=>{const a=s(860),i=a.Router(),n=s(147),r=s(17),{verify:o}=s(23),{hasRole:l}=s(547),{getSetting:d}=s(745),{randomID:u}=s(78),{invalidImage:c}=s(247),{rules:m,validate:g}=s(315),{imagePath:p,uploadImage:h,isValidFiletype:f}=s(320),y=s(268);i.use(a.urlencoded({extended:!1})),i.use(o,l("superuser")),i.get("/",(async(e,t)=>{const s=e.query.page||0,a=await d("imagesPerPage",24);y.query().columns("id","name","filename").orderBy("name").page(s,a).then((e=>{t.send({images:e.results,total:e.total,pageSize:a})})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.post("/search",m.stringValidation("term","Invalid Term"),g,(async(e,t)=>{const s=e.body.term,a=await d("imagesSearchResults",10);y.query().columns("id","name","filename").orderBy("name").where("name","like",`%${s}%`).limit(a).then((e=>{t.send(e)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.post("/upload",h,(async(e,t)=>process.env.DEMO_MODE?t.status(403).send("This feature is disabled in demo mode."):null==e.file?t.sendStatus(400):await f(e.file.path)?void y.query().columns("id","name","filename").insertAndFetch({id:u(8),name:r.parse(e.file.originalname).name,filename:e.file.filename}).then((e=>{t.send(e)})).catch((e=>{__logger.error(e),t.sendStatus(500)})):(n.rmSync(e.file.path,{force:!0}),t.status(400).send(c)))),i.post("/rename",m.intValidation(),m.stringValidation(),g,((e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id,a=e.matchedData.name;y.query().update({name:a,modified:y.fn.now()}).where({id:s}).then((()=>{t.sendStatus(200)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.post("/delete",m.intValidation(),g,(async(e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id;y.query().findById(s).first().then((async e=>{try{n.rmSync(p(e.filename),{force:!0}),await y.query().deleteById(s),t.sendStatus(200)}catch(e){__logger.error(e),t.sendStatus(500)}})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),e.exports=i},310:(e,t,s)=>{const a=s(860).Router();a.get("/",((e,t)=>{t.sendStatus(200)})),a.use("/admin",s(873)),a.use("/categories",s(224)),a.use("/languages",s(969)),a.use("/images",s(546)),a.use("/questions",s(959)),a.use("/settings",s(486)),a.use("*",((e,t)=>t.sendStatus(404))),e.exports=a},969:(e,t,s)=>{const a=s(860),i=a.Router(),{verify:n}=s(23),{hasRole:r}=s(547),{randomID:o}=s(78),{rules:l,validate:d}=s(315),u=s(256);i.use(a.urlencoded({extended:!1})),i.get("/all",((e,t)=>{u.query().columns("id","name").where({active:!0}).orderBy("name","ASC").then((e=>{t.send(e)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.use(n,r("superuser")),i.post("/create",l.stringValidation(),d,((e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.name,a=o(5);u.query().insert({id:a,name:s}).then((()=>{t.send({id:a})})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.post("/update",l.intValidation(),l.stringValidation(),l.booleanValidation(),d,((e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id,a=e.matchedData.name,i=e.matchedData.active;u.query().update({name:a,active:i}).where({id:s}).then((()=>{t.sendStatus(200)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.post("/delete",l.intValidation(),d,((e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id;u.query().deleteById(s).then((()=>{t.sendStatus(200)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),e.exports=i},959:(e,t,s)=>{const a=s(860),i=a.Router(),{verify:n}=s(23),{hasRole:r}=s(547),{randomID:o}=s(78),{getSetting:l}=s(745),{rules:d,validate:u}=s(315),c=s(98),m=s(516);i.use(a.urlencoded({extended:!1})),i.get("/category/:category_id/:limit",(async(e,t)=>{const s=e.params.category_id,a=e.params.limit,i=l("defaultQuestionLimit");let n=null;n=isNaN(a)||a<=0||a>i?i:a;try{const e=(await c.query().column("id").orderByRaw("RAND()").limit(n).where({categoryId:s,active:!0})).map((e=>e.id)),a=await c.query().column("questions.id","question","explanation","type","tof_answer").whereIn("questions.id",e).withGraphJoined("image(filenameOnly)").withGraphJoined("answers(defaultSelects)");t.send(a)}catch(e){__logger.error(e),t.sendStatus(500)}})),i.use(n,r("superuser")),i.get("/list/:category_id",((e,t)=>{const s=e.params.category_id;c.query().column("id","category_id","question").where({categoryId:s}).then((e=>{t.send(e)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.get("/:id",((e,t)=>{const s=e.params.id;c.query().findById(s).first().withGraphJoined("image(defaultSelects)").withGraphJoined("answers(defaultSelects)").then((e=>{t.send(e)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.post("/create",d.createQuestionValidation(),u,(async(e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id||o(8),a=e.matchedData.categoryId,i=e.matchedData.question,n=e.matchedData.explanation,r=e.matchedData.active,l=e.matchedData.imageId,d=e.matchedData.type,u=e.matchedData.tofAnswer,g=e.matchedData.answers;try{const e=await c.transaction((async e=>{await m.query(e).delete().where({questionId:s});const t=await c.query(e).insertAndFetch({id:s,categoryId:a,question:i,explanation:n,active:r,imageId:l,type:d,tofAnswer:u}).onConflict().merge();if("multi"===d){const t=[];g.forEach((a=>{t.push(m.query(e).insert({questionId:s,answer:a.answer,correct:a.correct}))})),await Promise.all(t)}return t}));t.send(e)}catch(e){__logger.error(e),t.sendStatus(500)}})),i.post("/delete",d.intValidation(),u,((e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id;c.query().deleteById(s).then((()=>{t.sendStatus(200)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),i.post("/delete/all",d.intValidation(),u,((e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.id;c.query().delete().where({categoryId:s}).then((()=>{t.sendStatus(200)})).catch((e=>{__logger.error(e),t.sendStatus(500)}))})),e.exports=i},486:(e,t,s)=>{const a=s(860),i=a.Router(),{verify:n}=s(23),{hasRole:r}=s(547),{getSetting:o,getAllSettings:l,updateSetting:d}=s(745),{rules:u,validate:c}=s(315);i.use(a.urlencoded({extended:!1})),i.use(n,r("superuser")),i.get("/",u.stringValidation("key","Invalid Key"),c,((e,t)=>{const s=e.matchedData.key,a=o(s);t.send(a)})),i.get("/all",((e,t)=>{const s=l();t.send(s)})),i.post("/update",u.settingsValidation(),c,(async(e,t)=>{if(process.env.DEMO_MODE)return t.status(403).send("This feature is disabled in demo mode.");const s=e.matchedData.settings;for(const e of s){const s=d(e.key,e.value);if(s instanceof Error)return void t.status(422).send(s.message)}t.sendStatus(200)})),e.exports=i},432:e=>{"use strict";e.exports=require("bcryptjs")},75:e=>{"use strict";e.exports=require("boolean")},455:e=>{"use strict";e.exports=require("compression")},242:e=>{"use strict";e.exports=require("conf")},554:e=>{"use strict";e.exports=require("connect-history-api-fallback")},582:e=>{"use strict";e.exports=require("cors")},142:e=>{"use strict";e.exports=require("dotenv")},860:e=>{"use strict";e.exports=require("express")},553:e=>{"use strict";e.exports=require("express-validator")},221:e=>{"use strict";e.exports=require("file-type")},344:e=>{"use strict";e.exports=require("jsonwebtoken")},514:e=>{"use strict";e.exports=require("knex")},137:e=>{"use strict";e.exports=require("lodash.head")},738:e=>{"use strict";e.exports=require("multer")},993:e=>{"use strict";e.exports=require("mysql2")},419:e=>{"use strict";e.exports=require("objection")},421:e=>{"use strict";e.exports=require("randomatic")},828:e=>{"use strict";e.exports=require("uuid")},773:e=>{"use strict";e.exports=require("winston")},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")}},t={};function s(a){var i=t[a];if(void 0!==i)return i.exports;var n=t[a]={exports:{}};return e[a](n,n.exports,s),n.exports}s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),(()=>{s(758),s(142).config({path:"./secrets.env"});const e=s(455),t=s(860),a=t(),i=s(147),n=s(17),r=s(582),o=s(554),{Model:l}=s(419),d=s(372);l.knex(d),a.disable("x-powered-by"),a.use(e());const u={origin:[/https?:\/\/localhost:(\d{4,5})/,/https?:\/\/192\.168\.\d{2,3}.\d{2,3}:(\d{4,5})/,process.env.WHITELIST_URL_A,process.env.WHITELIST_URL_B,process.env.WHITELIST_URL_C]};a.use("/api",r(u),s(310));const c=n.join(process.cwd(),"resources","broken.png");a.use("/resources",((e,t)=>{const s=n.join(process.cwd(),"resources",e.path);t.sendFile(i.existsSync(s)?s:c)})),a.use("/",o(),t.static("public",{maxAge:"1y",immutable:!0}));const m=process.env.PORT||5e3;a.listen(m,__logger.info(`Server started on port ${m}`))})()})();