diff --git a/.gitignore b/.gitignore index 4e653a6479..d497b6eab9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .data/ .temp/ +packages/server/runtime_apps/ # Logs logs diff --git a/et 04eef6ab4d291621114949c14097987ec1804274q b/et 04eef6ab4d291621114949c14097987ec1804274q deleted file mode 100644 index 0359714f20..0000000000 --- a/et 04eef6ab4d291621114949c14097987ec1804274q +++ /dev/null @@ -1,35 +0,0 @@ -commit 78a241d11c55ae717ba844c3d853e594d805e0a2 (HEAD -> master) -Author: michael shanks -Date: Fri Jun 7 14:11:23 2019 +0100 - - mono-repo - -commit 04eef6ab4d291621114949c14097987ec1804274 (bb/master) -Author: michael shanks -Date: Fri Jun 7 12:22:23 2019 +0100 - - license AGPL - -commit 5bcf5157e0010aea34be4bc338057a75ae0befec -Author: michael shanks -Date: Fri Jun 7 12:09:06 2019 +0100 - - making OS friendly :) - -commit d5129fbda3c0fbb35e7275420aee0b2e8a4f6c2b -Author: michael shanks -Date: Fri Jun 7 12:02:48 2019 +0100 - - initialise master database working - -commit 36f9e7c64faf9c1ce27a1586337b4bd168fe88ec (origin/master, origin/HEAD) -Author: Michael Shanks -Date: Fri Apr 5 16:30:29 2019 +0100 - - backup.. - -commit a8aa18d01d0640db6fb0f7bcb20e713b38b5610b -Author: Michael Shanks -Date: Tue Mar 19 21:45:21 2019 +0000 - - initial commit diff --git a/lerna.json b/lerna.json index d6707ca0cd..cd82d7703d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,5 @@ { + "npmClient": "npm", "packages": [ "packages/*" ], diff --git a/packages/server/appPackages/master/appDefinition.json b/packages/server/appPackages/master/appDefinition.json index 244e9f87ef..e9399f759a 100644 --- a/packages/server/appPackages/master/appDefinition.json +++ b/packages/server/appPackages/master/appDefinition.json @@ -45,6 +45,20 @@ "label": "Resolve Application By", "getInitialValue": "default", "getUndefinedValue": "default" + }, + { + "name": "defaultVersion", + "type": "reference", + "typeOptions": { + "indexNodeKey": "/applications/1-{id}/all_versions", + "reverseIndexNodeKeys": [ + "/applications/1-{id}/versions/3-{id}/isdefault" + ], + "displayValue": "name" + }, + "label": "Default Version", + "getInitialValue": "default", + "getUndefinedValue": "default" } ], "children": [ @@ -237,6 +251,18 @@ "aggregateGroups": [], "allowedRecordNodeIds": [], "nodeId": 10 + }, + { + "name": "isdefault", + "type": "index", + "map": "return {};", + "filter": "", + "indexType": "reference", + "getShardName": "", + "getSortKey": "record.id", + "aggregateGroups": [], + "allowedRecordNodeIds": [], + "nodeId": 28 } ], "allidsShardFactor": 1, diff --git a/packages/server/appPackages/testApp/dist/package.tar.gz b/packages/server/appPackages/testApp/dist/package.tar.gz index 26e2b97a8d..8cd74900b6 100644 Binary files a/packages/server/appPackages/testApp/dist/package.tar.gz and b/packages/server/appPackages/testApp/dist/package.tar.gz differ diff --git a/packages/server/middleware/routers.js b/packages/server/middleware/routers.js index 64a8bd9bb3..583b0c694c 100644 --- a/packages/server/middleware/routers.js +++ b/packages/server/middleware/routers.js @@ -8,6 +8,9 @@ const { getPackageForBuilder, savePackage, getApps } = require("../utilities/builder"); const builderPath = resolve(__dirname, "../builder"); +const appUiPath = appname => { + +} module.exports = (config, app) => { @@ -23,6 +26,22 @@ module.exports = (config, app) => { .use(async (ctx, next) => { ctx.sessionId = ctx.session._sessCtx.externalKey; ctx.session.accessed = true; + + const pathParts = ctx.path.split("/"); + + if(pathParts.length < 2) { + ctx.throw(StatusCodes.NOT_FOUND, "App Name not declared"); + } + + const instance = await ctx.master.getInstanceApiForSession( + pathParts[1], + ctx.sessionId); + + + ctx.instance = instance.instance; + ctx.publicPath = instance.publicPath; + ctx.isAuthenticated = !!instance.instance; + await next(); }) .get("/_builder", async (ctx) => { @@ -46,11 +65,9 @@ module.exports = (config, app) => { if(path.startsWith("/api/")) { await next(); - return; + } else { + await send(ctx, path, { root: builderPath }); } - - await send(ctx, path, { root: builderPath }); - }) .get("/:appname", async (ctx) => { ctx.response.status = StatusCodes.OK; @@ -139,22 +156,23 @@ module.exports = (config, app) => { ctx.request.body); ctx.response.status = StatusCodes.OK; }) - .use(async (ctx, next) => { + .get("/:appname", async (ctx) => { + await send(ctx, "/index.html", { root: ctx.publicPath }); + }) + .get("/:appname/*", async (ctx, next) => { + const path = ctx.path.replace(`/${ctx.params.appname}`, ""); - const pathParts = ctx.path.split("/"); - - if(pathParts.length < 2) { - ctx.throw(StatusCodes.NOT_FOUND, "App Name not declared"); - } - - ctx.instance = await ctx.master.getInstanceApiForSession( - pathParts[1], - ctx.sessionId); - - if(ctx.instance === null) { - ctx.response.status = StatusCodes.UNAUTHORIZED; - } else { + if(path.startsWith("/api/")) { await next(); + } else { + await send(ctx, path, { root: ctx.publicPath }); + } + }) + .use(async (ctx, next) => { + if(ctx.isAuthenticated) { + await next(); + } else { + ctx.response.status = StatusCodes.UNAUTHORIZED; } }) .post("/:appname/api/changeMyPassword", async (ctx) => { diff --git a/packages/server/package.json b/packages/server/package.json index f09a464618..834c3f0779 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "budibase", "version": "0.0.1", - "description": "budibase wrapper repo for development", + "description": "Budibase Web Server", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" @@ -18,6 +18,8 @@ "koa": "^2.7.0", "koa-body": "^4.1.0", "koa-session": "^5.12.0", + "koa-send": "^5.0.0", + "koa-static": "^5.0.0", "ncp": "^2.0.0", "rimraf": "^2.6.3", "tar-fs": "^2.0.0", @@ -27,8 +29,6 @@ "devDependencies": { "@jest/test-sequencer": "^24.8.0", "jest": "^24.8.0", - "koa-send": "^5.0.0", - "koa-static": "^5.0.0", "server-destroy": "^1.0.1", "supertest": "^4.0.2" }, diff --git a/packages/server/utilities/createAppPackage.js b/packages/server/utilities/createAppPackage.js index 4efa10ea69..cdea3d90f0 100644 --- a/packages/server/utilities/createAppPackage.js +++ b/packages/server/utilities/createAppPackage.js @@ -21,8 +21,9 @@ const createAppPackage = (context, appPath) => { appDefinition: appDefModule, behaviourSources: pluginsModule(context), appPath, - accessLevels - }) + accessLevels, + ...publicPaths(appPath) + }); } const appPackageFolder = (config, appname) => @@ -53,15 +54,34 @@ module.exports.masterAppPackage = (context) => { behaviourSources: config && config.extraMasterPlugins ? {...plugins, ...config.extraMasterPlugins} : plugins, - appPath: standardPackage.appPath + appPath: standardPackage.appPath, + unauthenticatedUiPath: standardPackage.unauthenticatedUiPath, + mainUiPath: standardPackage.mainUiPath }); } - + +const applictionVersionPath = (appname, versionId) => + join("..", getRuntimePackageDirectory(appname, versionId)) + +const publicPaths = (appPath) => ({ + mainUiPath: join( + appPath, "ui", "main", "public"), + unauthenticatedUiPath: join( + appPath, "ui", "unauthenticated", "public") + + }); + +module.exports.applictionVersionPublicPaths = (appname, versionId) => { + const appPath = applictionVersionPath(appname, versionId); + return publicPaths(appPath); +} + module.exports.applictionVersionPackage = async (context, appname, versionId, instanceKey) => { const pkg = createAppPackage( context, - join("..", getRuntimePackageDirectory(appname, versionId)) + applictionVersionPath(appname, versionId) ); + pkg.appDefinition = constructHierarchy(pkg.appDefinition); await injectPlugins( pkg, diff --git a/packages/server/utilities/masterAppInternal.js b/packages/server/utilities/masterAppInternal.js index 18f0506a57..c77d632444 100644 --- a/packages/server/utilities/masterAppInternal.js +++ b/packages/server/utilities/masterAppInternal.js @@ -7,7 +7,11 @@ const getDatastore = require("./datastore"); const getDatabaseManager = require("./databaseManager"); const {$, splitKey} = require("budibase-core").common; const { keyBy, last } = require("lodash/fp"); -const { masterAppPackage, applictionVersionPackage } = require("../utilities/createAppPackage"); +const { + masterAppPackage, + applictionVersionPackage, + applictionVersionPublicPaths + } = require("../utilities/createAppPackage"); const isMaster = appname => appname === "_master"; @@ -137,15 +141,23 @@ module.exports = async (context) => { const getInstanceApiForSession = async (appname, sessionId) => { if(isMaster(appname)) { const customId = bb.recordApi.customId("mastersession", sessionId); + const masterPkg = masterAppPackage(context); try { const session = await bb.recordApi.load(`/sessions/${customId}`); - return await getApisForSession( - masterDatastore, - masterAppPackage(context), - session); + return ({ + instance: await getApisForSession( + masterDatastore, + masterAppPackage(context), + session), + publicPath: masterPkg.mainUiPath + }); + } catch(_) { - return null; + return ({ + instance: null, + publicPath: masterPkg.unauthenticatedUiPath + }); } } else { @@ -163,12 +175,21 @@ module.exports = async (context) => { const appPackage = await applictionVersionPackage( context, appname, versionId, session.instanceKey); - return await getApisForSession( - instanceDatastore, - appPackage, - session); + return ({ + instance: await getApisForSession( + instanceDatastore, + appPackage, + session), + publicPath: appPackage.mainUiPath + }); + } catch(_) { - return null; + return ({ + instance:null, + publicPath: applictionVersionPublicPaths( + app.name, + app.defaultVersion.id).unauthenticatedUiPath + }); } } };