Initial
This commit is contained in:
1
resources/app/dist/server/views/api.mjs
vendored
Normal file
1
resources/app/dist/server/views/api.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";import*as util from"../../../common/utils/helpers.mjs";export default class APIView extends View{route="/api/status";_methods=["get"];async handleGet(e,s){const{game:t,release:i}=globalThis,r={active:!1,version:i?.version};t.ready&&util.mergeObject(r,{active:!0,world:t.world.id,system:t.system.id,systemVersion:t.system.version,users:Object.values(t.activity.users).length,uptime:t.activity.serverTime}),s.json(r)}}
|
||||
1
resources/app/dist/server/views/auth.mjs
vendored
Normal file
1
resources/app/dist/server/views/auth.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import Express from"../express.mjs";import sessions from"../../sessions.mjs";import*as util from"../../../common/utils/helpers.mjs";import{Module}from"../../packages/_module.mjs";import View from"./view.mjs";export default class AuthView extends View{route="/auth";socket="getAuthData";_template="auth";_methods=["get","post"];async handleGet(e,s){if(config.license.needsSignature)return s.redirect(`${e.baseUrl}/license`);if(global.game.world)return s.redirect(`${e.baseUrl}/join`);const t=View._getStaticContent({setup:!0}),o={bodyClass:`auth flexcol theme-${config.options.cssTheme}`,messages:sessions.getMessages(e,{clear:!1}),layout:"setup",scripts:t.scripts,styles:t.styles};s.render(this._template,o)}async handlePost(e,s){const{game:t}=global,o=sessions.authenticateAdmin(e,s),a=!t.world&&o.success;return s.redirect(e.baseUrl+util.getRoute(a?"setup":"auth"))}async handleSocket(e,s){return s({release:global.release,worlds:[],systems:[],modules:Module.getPackages({coreTranslation:!0}).map((e=>e.vend())),options:{language:global.config.options.language}})}}
|
||||
1
resources/app/dist/server/views/error.mjs
vendored
Normal file
1
resources/app/dist/server/views/error.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";export default class ErrorView extends View{route="/no";_methods=["get"];async handleGet(e,r,...o){View.error(e,r,...o)}}
|
||||
1
resources/app/dist/server/views/game.mjs
vendored
Normal file
1
resources/app/dist/server/views/game.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";export default class GameView extends View{route="/game";_template="game";_methods=["get"];async handleGet(e,r){const{db:t,game:o,logger:s}=global;if(!o.world)return this._noWorld(e,r);if(!e.user)return r.redirect(`${e.baseUrl}/join`);if(!await t.User.get(e.user))return s.error(Error(`User ${e.user} not found!`)),r.redirect(`${e.baseUrl}/join`);const i=await t.Setting.getValue("core.moduleConfiguration")||{},a=View._getStaticContent({world:!0,moduleConfig:i});r.render(this._template,{scripts:a.scripts,styles:a.styles,watermark:null})}}
|
||||
1
resources/app/dist/server/views/join.mjs
vendored
Normal file
1
resources/app/dist/server/views/join.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";import sessions from"../../sessions.mjs";import{Module}from"../../packages/_module.mjs";import{PASSWORD_SAFE_STRING}from"../../../common/constants.mjs";import Express from"../express.mjs";export default class JoinView extends View{route="/join";socket="getJoinData";_template="join";_methods=["get","post"];async handleGet(e,s){const{game:o}=global;if(!o.world)return this._noWorld(e,s);if(!o.ready)return setTimeout((()=>this.handleGet(e,s)),1e3);await sessions.logoutWorld(e,s);const t=o.world.background,a=t?`body.background {\n --background-url: url("${URL.parseSafe(t)?t:foundry.utils.getRoute(t,{prefix:express.routePrefix})}");\n }`:"",n=View._getStaticContent({setup:!0});return s.render(this._template,{bodyClass:["auth","join","flexcol",t?"background":"",`theme-${config.options.cssTheme}`,`join-theme-${o.world.joinTheme??"default"}`].filterJoin(" "),messages:sessions.getMessages(e,{clear:!1}),pageTitle:o.world.title,layout:"setup",scripts:n.scripts,styles:n.styles,inlineStyles:a})}async handlePost(e,s){const{config:o,game:t}=global;if(!t.world)return this._noWorld(e,s);let a={};switch(e.body.action){case"shutdown":if(o.options.demoMode)return s.status(401),s.send("This option is not available for servers running in demo mode"),s;if(!o.adminPassword)return s.status(403),s.send("ERROR.InvalidAdminKey"),s;if(!sessions.authenticateAdmin(e,s).success)return s.send(e.session.messages.pop()?.message),e.session.messages=[],s;a=await t.world.deactivate(e,{asAdmin:!0}),a.status="success",a.message="The game world has been successfully deactivated";break;case"join":if(await sessions.logoutWorld(e,s),a=await sessions.authenticateUser(e,s),"failed"===a.status)return s}return s.json(a)}async handleSocket(e,s){const{game:o}=global;return o.world?s({release:global.release,world:o.world.vend(),modules:Module.getPackages({coreTranslation:!0}).map((e=>e.vend())),passwordString:PASSWORD_SAFE_STRING,isAdmin:e.admin,users:await db.User.dump(),activeUsers:Array.from(Object.keys(o.activity.users)),userId:e.worlds[o.world.id]||null,options:{language:global.config.options.language}}):s({})}}
|
||||
1
resources/app/dist/server/views/license.mjs
vendored
Normal file
1
resources/app/dist/server/views/license.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";import sessions from"../../sessions.mjs";export default class LicenseView extends View{route="/license";_template="license";_methods=["get","post"];async handleGet(e,s){const t=global.config.license;if(!t.needsSignature)return s.redirect("/");const n=t.license?"eula":"key";return this.#e(e,s,n)}async handlePost(e,s){const{config:t}=global,n=t.license;if(!n.needsSignature)return s.redirect("/");let i=n.license?"eula":"key";if("key"===i)try{n.applyLicense(e.body.licenseKey),sessions.setMessage(e,s,"info","License key entered, please sign the End User License Agreement."),i="eula"}catch(t){sessions.setMessage(e,s,"error",t.message)}else{"decline"in e.body&&(n.applyLicense(null),t.app?t.app.quit():process.exit());const i=await n.sign();if("success"===i.status)return sessions.setMessage(e,s,"info",i.message),s.redirect(`${e.baseUrl}/setup`);if("error"===i.status)return sessions.setMessage(e,s,"error",i.message),n.applyLicense(null),s.redirect(`${e.baseUrl}/license`)}return this.#e(e,s,i)}#e(e,s,t){const n=View._getStaticContent({setup:!0});return s.render(this._template,{layout:"setup",bodyClass:"auth flexcol",scripts:n.scripts,styles:n.styles,isEULA:"eula"===t,licenseKey:e.body.licenseKey,messages:sessions.getMessages(e,{clear:!1}),step:t})}}
|
||||
1
resources/app/dist/server/views/players.mjs
vendored
Normal file
1
resources/app/dist/server/views/players.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import sessions from"../../sessions.mjs";import{Module}from"../../packages/_module.mjs";import{PASSWORD_SAFE_STRING,USER_ROLES}from"../../../common/constants.mjs";import View from"./view.mjs";export default class PlayersView extends View{route="/players";socket="getPlayersData";_template="players";_methods=["get"];async handleGet(e,s){const{db:t,game:r}=global;if(!r.world)return s.redirect(`${e.baseUrl}/setup`),!1;const a=await t.User.getUsers();if(!PlayersView.#e(a,e.user))return s.redirect(`${e.baseUrl}/join`),!1;const o=r.world.background,i=o?`body.background {\n --background-url: url("${URL.parseSafe(o)?o:foundry.utils.getRoute(o,{prefix:express.routePrefix})}");\n }`:"",l=View._getStaticContent({setup:!0});s.render(this._template,{layout:"setup",bodyClass:["auth","players","flexcol",o?"background":"",`theme-${config.options.cssTheme}`].filterJoin(" "),pageTitle:r.world.title,messages:sessions.getMessages(e,{clear:!1}),scripts:l.scripts,styles:l.styles,inlineStyles:i})}async handleSocket(e,s){if(!game.world||!game.ready)return s({});const t=e.worlds[game.world.id]||null;return e.admin||PlayersView.#e(game.users,t)?s({modules:Module.getPackages({coreTranslation:!0}).map((e=>e.vend())),options:{language:global.config.options.language},passwordString:PASSWORD_SAFE_STRING,release:global.release,settings:await db.Setting.dump(),userId:t,users:await db.User.dump()}):s({})}static#e(e,s){return!e.some((e=>e.hasRole(USER_ROLES.GAMEMASTER)))||!!s&&(e.find((e=>e._id===s))?.isGM??!1)}}
|
||||
1
resources/app/dist/server/views/quit.mjs
vendored
Normal file
1
resources/app/dist/server/views/quit.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";import sessions from"../../sessions.mjs";export default class QuitView extends View{route="/quit";_methods=["post"];async handlePost(s,e){const{config:t}=global;if(!sessions.authenticateAdmin(s,e).success)return e.send({status:"failed"});e.send({status:"failed"}),t.app?t.app.quit():process.exit()}}
|
||||
1
resources/app/dist/server/views/setup.mjs
vendored
Normal file
1
resources/app/dist/server/views/setup.mjs
vendored
Normal file
File diff suppressed because one or more lines are too long
1
resources/app/dist/server/views/stream.mjs
vendored
Normal file
1
resources/app/dist/server/views/stream.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import GameView from"./game.mjs";export default class StreamView extends GameView{route="/stream";_template="stream"}
|
||||
1
resources/app/dist/server/views/update.mjs
vendored
Normal file
1
resources/app/dist/server/views/update.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";import sessions from"../../sessions.mjs";import{Module}from"../../packages/_module.mjs";import*as packages from"../../packages/views.mjs";export default class ApplicationUpdateView extends View{route="/update";socket="getUpdateData";_template="update";_methods=["get","post"];async handleGet(e,s){if(config.license.needsSignature)return s.redirect(`${e.baseUrl}/license`);if(global.game.world)return e.user?s.redirect(`${e.baseUrl}/game`):s.redirect(`${e.baseUrl}/join`);if(!sessions.authenticateAdmin(e,s).success)return s.redirect(`${e.baseUrl}/auth`);const a=View._getStaticContent({setup:!0}),t={layout:"setup",bodyClass:`update auth flexcol theme-${config.options.cssTheme}`,messages:sessions.getMessages(e,{clear:!1}),requireAuth:!1,scripts:a.scripts,styles:a.styles};s.render(this._template,t)}async handlePost(e,s){let a={};const{config:t,game:r}=global,{action:o,...i}=e.body,c=sessions.authenticateAdmin(e,s);if(!(!r.world&&c.success))return s.status(403),s.json({error:"You lack server administrator permission to submit this request."});switch(o){case"updateCheck":try{a=await t.updater.check(i),a||(a={info:"SETUP.UpdateNotAvailable"})}catch(e){const{message:s,stack:t,messageCode:r}=e;a={error:s,stack:t,messageCode:r}}break;case"updateDownload":try{a=await t.updater.update()}catch(e){a={error:e.message,stack:e.stack}}break;case"createSnapshot":a=packages.handleCreateSnapshot(e.body);break;case"checkCreateSnapshotDiskSpace":a=await global.packages.backups.checkCreateSnapshotDiskSpace();break;case"previewCompatibility":a=await packages.handlePreviewCompatibility(e.body);break;default:a={error:`Unsupported ApplicationUpdateView action "${o}" submitted`}}return s.json(a)}async handleSocket(e,s){const a=global.config;if(a.adminPassword&&!e.admin||game.world)return s({});return s({options:a.options.vend(),release:global.release,addresses:a.express.getInvitationLinks(),coreUpdate:await a.updater.checkCoreUpdateAvailability(),worlds:[],systems:[],modules:Module.getPackages({coreTranslation:!0}).map((e=>e.vend()))})}}
|
||||
1
resources/app/dist/server/views/upload.mjs
vendored
Normal file
1
resources/app/dist/server/views/upload.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import View from"./view.mjs";import Files from"../../files/files.mjs";import{hasFileExtension}from"../../../common/data/validators.mjs";import{handleDocumentAssetUpload}from"../../database/sanitization.mjs";export default class FileUploadView extends View{route="/upload";_methods=["post"];async handlePost(e,s){const{game:o,config:a}=global;let t=null;if(!(e.session.admin||!o.ready&&!a.adminPassword)&&(o.ready&&(t=await db.User.get(e.user)),!t||!t.hasPermission("FILES_UPLOAD")))throw new Error(`User ${n.userId} does not have permission to upload files.`);let i=e.body.source;const r=e.files.upload,n={...e.body};if(n.uuid){if(!hasFileExtension(r.name,Object.keys(CONST.IMAGE_FILE_EXTENSIONS)))return s.json({error:"Not an image file."});i="data",n.target=await handleDocumentAssetUpload(n.uuid,r)}const d=await Files.upload(i,r,n).catch((e=>({error:e.message||e})));return s.json(d)}}
|
||||
1
resources/app/dist/server/views/view.mjs
vendored
Normal file
1
resources/app/dist/server/views/view.mjs
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import Express from"../express.mjs";import{Module}from"../../packages/_module.mjs";export default class View{route;socket=!1;_template;_methods=[];get hasGet(){return this._methods.includes("get")}get hasPost(){return this._methods.includes("post")}async handleGet(e,s){}async handlePost(e,s){}async handleSocket(e,s){}_noWorld(e,s){return View.error(e,s,{pageTitle:"No Active Game",message:"There is currently no active game session. Please wait for the host to configure the world and then refresh this page."})}static error(e,s,...t){const r=t.pop()||global.fatalError,o=this._getStaticContent({setup:!0});s.render("error",{layout:"setup",bodyClass:["auth","error","flexcol",`theme-${config.options.cssTheme}`].join(" "),pageTitle:r.title||"Critical Failure!",message:r.message||"Something went wrong with the Foundry Virtual Tabletop server.",setupUrl:foundry.utils.getRoute("setup",{prefix:express.routePrefix}),stack:r.stack||null,styles:o.styles})}static home(e,s){const{config:t,game:r}=global;return t.license.needsSignature?s.redirect(`${e.baseUrl}/license`):r.world?e.user?s.redirect(`${e.baseUrl}/game`):s.redirect(`${e.baseUrl}/join`):s.redirect(`${e.baseUrl}/setup`)}static _getStaticContent({world:e=!1,setup:s=!1,moduleConfig:t={}}){const r=[];let o=[];const i=new Set,c=(e,s,t)=>{const c="style"===s?o:r;i.has(e)||c.push({src:e,type:s,priority:t,isModule:"module"===s})},l=0,a=1,n=2,p=3,u=4,d=5,h=6,m=7,f=8,y=9,g=10,E=0,_=1,S=2,w=3,b=4;if(Express.CORE_VIEW_SCRIPTS.forEach((e=>c(e,"script",l))),e&&c("scripts/simplepeer.min.js","script",l),Express.CORE_VIEW_MODULES.forEach((e=>c(e,"module",a))),Express.CORE_VIEW_STYLES.forEach((e=>c(e,"style",_))),e){const e=global.game.world;e.system.esmodules.forEach((e=>c(e,"module",h))),e.system.scripts.forEach((e=>c(e,"script",d))),e.system.styles.forEach((e=>c(e,"style",S)));for(let s of e.modules){if(!0!==t[s.id])continue;const e=s.library??!1;s.esmodules.forEach((s=>c(s,"module",e?u:f))),s.scripts.forEach((s=>c(s,"script",e?p:m))),s.styles.forEach((s=>c(s,"style",e?E:w)))}e.esmodules.forEach((e=>c(e,"module",g))),e.scripts.forEach((e=>c(e,"script",y))),e.styles.forEach((e=>c(e,"style",b)))}if(c("scripts/foundry-esm.js","script",n),c("scripts/foundry.js","script",n),s){o.find((e=>"css/style.css"===e.src)).src="css/foundry2.css",c("scripts/setup.js","script",n);Module.getCoreTranslationStyles().forEach((e=>c(e,"style",w)))}const x=(e,s)=>e.priority-s.priority;return r.sort(x),o.sort(x),{scripts:r,styles:o}}}
|
||||
Reference in New Issue
Block a user