From 991bd69671b3b99cc7bbac518f210af3a272d20c Mon Sep 17 00:00:00 2001 From: michael shanks Date: Tue, 9 Jul 2019 07:29:50 +0100 Subject: [PATCH] injecting plugins into child apps --- packages/server/app.js | 10 +-- .../appPackages/master/appDefinition.json | 24 +++++- packages/server/appPackages/master/main.js | 13 +-- .../appPackages/testApp/dist/package.tar.gz | Bin 1185 -> 1185 bytes packages/server/index.js | 4 +- packages/server/initialise/buildAppContext.js | 11 +++ .../server/initialise/createInstanceDb.js | 11 ++- packages/server/initialise/createMasterDb.js | 15 +++- .../server/initialise/initialiseBudibase.js | 12 +-- .../initialise/initialiseRuntimePackages.js | 4 +- .../access_levels.json | 0 .../appDefinition.json | 0 .../plugins.js | 0 packages/server/tests/authenticate.js | 1 - packages/server/tests/createNewApp.js | 2 +- packages/server/tests/testApp.js | 14 ++-- packages/server/utilities/budibaseApi.js | 20 +++++ packages/server/utilities/createAppPackage.js | 23 ++++-- .../utilities/injectedPlugins/createUser.js | 17 ++++ .../utilities/injectedPlugins/disableUser.js | 6 ++ .../utilities/injectedPlugins/enableUser.js | 6 ++ .../server/utilities/injectedPlugins/index.js | 77 ++++++++++++++++++ .../server/utilities/masterAppInternal.js | 46 ++++++++--- 23 files changed, 260 insertions(+), 56 deletions(-) create mode 100644 packages/server/initialise/buildAppContext.js rename packages/server/runtime_apps/testApp/{3-Y5vsgF-ZEjh => 3-M8CjoLngYZw}/access_levels.json (100%) rename packages/server/runtime_apps/testApp/{3-Y5vsgF-ZEjh => 3-M8CjoLngYZw}/appDefinition.json (100%) rename packages/server/runtime_apps/testApp/{3-Y5vsgF-ZEjh => 3-M8CjoLngYZw}/plugins.js (100%) create mode 100644 packages/server/utilities/injectedPlugins/createUser.js create mode 100644 packages/server/utilities/injectedPlugins/disableUser.js create mode 100644 packages/server/utilities/injectedPlugins/enableUser.js create mode 100644 packages/server/utilities/injectedPlugins/index.js diff --git a/packages/server/app.js b/packages/server/app.js index 7f95aea917..d4c4926428 100644 --- a/packages/server/app.js +++ b/packages/server/app.js @@ -1,19 +1,19 @@ const Koa = require('koa'); const app = new Koa(); -const getMasterAppInternal = require("./utilities/masterAppInternal"); const router = require("./middleware/routers"); const koaBody = require('koa-body'); const initialiseRuntimePackages = require("./initialise/initialiseRuntimePackages"); -module.exports = async (config) => { +module.exports = async (budibaseContext) => { + const { config } = budibaseContext; app.keys = config.keys; - app.context.master = await getMasterAppInternal(config); + app.context.master = budibaseContext.master; app.context.getAppPackage = await initialiseRuntimePackages( - config, + budibaseContext, app.context.master, config.latestAppsPath - ) + ); app.use(koaBody({ multipart : true })); app.use(router(config, app).routes()); return app.listen(); diff --git a/packages/server/appPackages/master/appDefinition.json b/packages/server/appPackages/master/appDefinition.json index 02296255c6..244e9f87ef 100644 --- a/packages/server/appPackages/master/appDefinition.json +++ b/packages/server/appPackages/master/appDefinition.json @@ -74,6 +74,16 @@ "getInitialValue": "default", "getUndefinedValue": "default" }, + { + "name": "createdByMaster", + "type": "bool", + "typeOptions": { + "allowNulls": false + }, + "label": "Created by Master", + "getInitialValue": "default", + "getUndefinedValue": "default" + }, { "name": "instance", "type": "reference", @@ -273,6 +283,18 @@ "getInitialValue": "default", "getUndefinedValue": "default" }, + { + "name": "instanceKey", + "type": "string", + "typeOptions": { + "maxLength": null, + "values": null, + "allowDeclaredValuesOnly": false + }, + "label": "Instance Key", + "getInitialValue": "default", + "getUndefinedValue": "default" + }, { "name": "instanceVersion", "type": "string", @@ -467,7 +489,7 @@ "actionName": "create_user", "eventName": "recordApi:save:onRecordCreated", "optionsCreator": "return ({ user:context.record, apis });", - "condition": "context.record.type === \"user\"" + "condition": "context.record.type === \"user\" && context.record.createdByMaster === true" } ] } \ No newline at end of file diff --git a/packages/server/appPackages/master/main.js b/packages/server/appPackages/master/main.js index 849b90c720..b53de81248 100644 --- a/packages/server/appPackages/master/main.js +++ b/packages/server/appPackages/master/main.js @@ -11,7 +11,8 @@ const { createWriteStream } = require("fs"); const { applictionVersionPackage } = require("../../utilities/createAppPackage"); const { getApisWithFullAccess } = require("../../utilities/budibaseApi"); -module.exports = (config) => { +module.exports = (context) => { + const { config } = context; const datastoreModule = require(`../../../datastores/datastores/${config.datastore}`); return ({ initialiseInstance : async ({ instance, apis }) => { @@ -36,9 +37,8 @@ module.exports = (config) => { await downloadAppPackage(apis, instance, application.name, versionId); const dbConfig = await createInstanceDb( - config, + context, datastoreModule, - config.datastoreConfig, application, instance ); @@ -67,10 +67,11 @@ module.exports = (config) => { last, ]); - const appPackage = applictionVersionPackage( - config, + const appPackage = await applictionVersionPackage( + context, application.name, - versionId); + versionId, + instance.key); const instanceApis = await getApisWithFullAccess( datastoreModule.getDatastore( diff --git a/packages/server/appPackages/testApp/dist/package.tar.gz b/packages/server/appPackages/testApp/dist/package.tar.gz index ee34a92d9fe435c2cb12d46ae02d7edaff05ea0c..4f95910d929db345683972977f3a1369c153ec7e 100644 GIT binary patch delta 1131 zcmV-x1eE)s384v)MSlT-Wbt?p-W~5prhTw`@_m0e91{CPsz0+IL2uv>M}wdrbcyee zdj5zU44%NYgG3vu(3EZE)Sdg65Di1n`hvq1aNYh(OY!A(+!Oy^FdW(V2lzJX1wG;i z-BG`b<6qvCRr;UD|L*9J5HAbAHzt4DpM>0H4;&G64*1=Z*M9<(*DAippyo_#CPisl zWvXK{x3QZZDxe04f>5exDJD}PBlrn!En6qVaL73*-3h+EV^QiYIn&mCN+RH}b0tX} z?cNhyt!T$8HjPM!i7Ux))97@cZt=EKx@lT$rF63hZl&^CF?7?wJm$E_dXsEOG#2?| z=4mh_rdnTHKYuq+Xswlss#}sZqDRR9K`%KFsYt}MdwsP1*_vg#$zm6L%zVzYaauQ+ zwz<|h6?6)Oi3n~U9WHC__PRsKIfMrH|MKko^*noVzt5dW?+Vw*a*v6BbeKMO+uPHE zXdJ(W2@}kQ@_F!I-|r7{{MYjbzQce1aF735cpyoD{> zTlr%+V?0tI%0RHRc@&cJZdY!IrG{DWmEME_k81F;wk?&UyJxF5SZsVoF)?i%ejl3! zimgc|cC)+r8N}4ga5TWMwpKWqKwXEB37KP=o88OvYL1mme1sXPg||6^Zc~*B_o9Is3y>#2Hona9)pNIe%SN2C-xq9s_W}e@nP?dzHt6=znWOldN2>4_+-I<@Q8 za1TN&OT5-%#M8p$Tr@GWA7eJo&N?3ucaNnwm3ThG^Jr<3%&a=KY%apMJ(@%ba!0Iq zyG-L3_N0`d_7~(Egx|uzjcHpj-?j{`?0=Im<9tYg#?o!ud8ZgElD;gdM5f3=KCA7k zd`j&km%;ZvTK_K-o}A6Dbv*F?KX4boqb}lqKL~>T{r^)?%#$e-_U3 x9}6ihat9)m5yG0Wmzc?SUTV#*0W^H1C(pggd)m{U_VmxAzX2YT!aV>Y002;`K4t&_ delta 1131 zcmV-x1eE)s384v)MSmHA9z5QIcgOotX&>yKeBU1qhs0iy>euWc=neegXb|*+F7f?Q z&mWP4!4ueakZ3~{nzF5&x^w>$qG1SHUvRhruG@cUDZadpd*a^S$QYRjGi}|cBmxdQSCYih z?mfZPigv7G(};AKxRMMvjZXLJ7H=!1o2JE9N;iw(Rw}O*LpKe~V~&fgH_3)XW05~* zo(4l=s`a(?bAJPc)>^5kx+Pg7dXx+h^pXRSibPDi+eh1;E_NH|{|rku;`*AQ~5Ao|1cz8Bms^MrB@RsOVY z9;cVU*MIsp1@qR{E#*#d26ZMh;iif812zk+^Mw^<<}z=(d^j(MqAA3d)&*mMW7fu_ z2^p=8c!Q#fGCG%uSaG_dPbBlpYT{K`K9d8EXU;^vY~L@bL0XnG59W;^WOK@Y<>#3XH@mYc|DHhbbnbH#FAln48R5dE#c1XRUQkH-$r&t z>LU*HteJ(?#v*+-qbhnsLnDFKnLfi^gF{ofuB()Lyjyx!Hf)_& zjUEmAmC9Ukr#MtpHq&*!Ed0o|dNDP#Uuax0rOCXdBffo+rKv~5S|NEdF>zupjJ%jI zr+>ZS+d`FP`H|rgX7q~5M4jPZxPYHbG;zGE$ogHrsY+s5C6wwsEkV?U@z^7#Q@d^r z-$7_)iPu_;cv_g8iza6FW6Z|cS?2@d?y(f763=IN9xY9hnN_Ej%|#fuN0TT)?uZp{ zmudXMo|H1w{(^ji@LL$TF>MRx+m@k~y?+vBoDV6`Sh{UH?-WBt(w8Nb$P_uqXSIEm zPpO^cGWfnn>;GlKle5{ijt74KNBrOI1ql580Dryx_y4D$m?u*v?3e%D>9{Zcz5cNH z|Ic99$M^@`;r{&hB!pYPHe{m7E27|2!W0~P6YZV6JUTo&oXZF?OdD=usf=YgMr8I0 zo1TzYKak@^bF>|~f}6`Nn2eDxZ(>D{N}Yfj)Sl?J`x app(appContext)); \ No newline at end of file diff --git a/packages/server/initialise/buildAppContext.js b/packages/server/initialise/buildAppContext.js new file mode 100644 index 0000000000..242238044a --- /dev/null +++ b/packages/server/initialise/buildAppContext.js @@ -0,0 +1,11 @@ +const getMasterAppInternal = require("../utilities/masterAppInternal"); + +module.exports = async (config, masterIsCreated) => { + const context = { config }; + + if(!masterIsCreated) return context; + + const master = await getMasterAppInternal(context); + context.master = master; + return context; +}; \ No newline at end of file diff --git a/packages/server/initialise/createInstanceDb.js b/packages/server/initialise/createInstanceDb.js index e5273d0f3f..c0f95d86b0 100644 --- a/packages/server/initialise/createInstanceDb.js +++ b/packages/server/initialise/createInstanceDb.js @@ -3,19 +3,18 @@ const { setupDatastore, common } = require("budibase-core"); -const constructHierarchy = require("../utilities/constructHierarchy"); const getDatabaseManager = require("../utilities/databaseManager"); -const masterDbAppDefinition = require("../appPackages/master/appDefinition.json"); const { applictionVersionPackage } = require("../utilities/createAppPackage"); const { last } = require("lodash/fp"); const {$,splitKey} = common; -module.exports = async (config, datastoreModule, rootDatastoreConfig, app, instance) => { +module.exports = async (context, datastoreModule, app, instance) => { try { const databaseManager = getDatabaseManager( - datastoreModule, rootDatastoreConfig); + datastoreModule, + context.config.datastoreConfig); await databaseManager.createEmptyInstanceDb( app.id, instance.id); @@ -31,8 +30,8 @@ module.exports = async (config, datastoreModule, rootDatastoreConfig, app, insta last ]); - const appPackage = applictionVersionPackage( - config, app.name, versionId + const appPackage = await applictionVersionPackage( + context, app.name, versionId, instance.key ); await initialiseData( diff --git a/packages/server/initialise/createMasterDb.js b/packages/server/initialise/createMasterDb.js index c8affcf328..ea67877c3b 100644 --- a/packages/server/initialise/createMasterDb.js +++ b/packages/server/initialise/createMasterDb.js @@ -6,9 +6,11 @@ const masterDbAppDefinition = require("../appPackages/master/appDefinition.json" const masterDbAccessLevels = require("../appPackages/master/access_levels.json"); const { masterAppPackage } = require("../utilities/createAppPackage"); -module.exports = async (datastoreModule, rootDatastoreConfig, username, password, budibaseConfig) => { +module.exports = async (context, datastoreModule, username, password) => { try { - const databaseManager = getDatabaseManager(datastoreModule, rootDatastoreConfig); + const { config } = context; + const databaseManager = getDatabaseManager( + datastoreModule, config.datastoreConfig); await databaseManager.createEmptyMasterDb(); const masterDbConfig = databaseManager.masterDatastoreConfig; @@ -19,15 +21,20 @@ module.exports = async (datastoreModule, rootDatastoreConfig, username, password await initialiseData(datastore, constructHierarchy(masterDbAppDefinition)); + const masterPackage = masterAppPackage(context); const bbMaster = await getApisWithFullAccess( - datastore, masterAppPackage(budibaseConfig)); + datastore, masterPackage); await bbMaster.authApi.saveAccessLevels(masterDbAccessLevels); const user = bbMaster.authApi.getNewUser(); user.name = username; user.accessLevels= ["owner"]; await bbMaster.authApi.createUser(user, password); - return await getApisForUser(datastore, masterAppPackage(budibaseConfig), username, password); + return await getApisForUser( + datastore, + masterPackage, + username, + password); } catch(e) { throw e; } diff --git a/packages/server/initialise/initialiseBudibase.js b/packages/server/initialise/initialiseBudibase.js index b741a17483..3d9f9d4b18 100644 --- a/packages/server/initialise/initialiseBudibase.js +++ b/packages/server/initialise/initialiseBudibase.js @@ -4,7 +4,7 @@ const readline = require('readline'); const { promisify } = require('util'); const { mkdir, rimraf } = require("../utilities/fsawait"); const budibaseConfig = require("../config"); - +const buildAppContext = require("../initialise/buildAppContext"); readline.Interface.prototype.question[promisify.custom] = function(prompt) { @@ -67,10 +67,10 @@ const question = async (q) => { await mkdir(rootconfig.rootPath); } + const appContext = await buildAppContext(budibaseConfig, false); await create( - datastoreModule, - rootconfig, - username, - password, - budibaseConfig) + appContext, + datastoreModule, + username, + password); })() \ No newline at end of file diff --git a/packages/server/initialise/initialiseRuntimePackages.js b/packages/server/initialise/initialiseRuntimePackages.js index 5ff7807f0a..0387e2873e 100644 --- a/packages/server/initialise/initialiseRuntimePackages.js +++ b/packages/server/initialise/initialiseRuntimePackages.js @@ -15,7 +15,7 @@ const copyfolder = (source, destination) => }); -module.exports = async (config, bbMaster, latestAppsFolder) => { +module.exports = async (context, bbMaster, latestAppsFolder) => { // create runtime folder // copy master into /master/latest @@ -42,7 +42,7 @@ module.exports = async (config, bbMaster, latestAppsFolder) => { const apps = { - "_master": masterAppPackage(config) + "_master": masterAppPackage(context) } return ((appName, versionId) => { diff --git a/packages/server/runtime_apps/testApp/3-Y5vsgF-ZEjh/access_levels.json b/packages/server/runtime_apps/testApp/3-M8CjoLngYZw/access_levels.json similarity index 100% rename from packages/server/runtime_apps/testApp/3-Y5vsgF-ZEjh/access_levels.json rename to packages/server/runtime_apps/testApp/3-M8CjoLngYZw/access_levels.json diff --git a/packages/server/runtime_apps/testApp/3-Y5vsgF-ZEjh/appDefinition.json b/packages/server/runtime_apps/testApp/3-M8CjoLngYZw/appDefinition.json similarity index 100% rename from packages/server/runtime_apps/testApp/3-Y5vsgF-ZEjh/appDefinition.json rename to packages/server/runtime_apps/testApp/3-M8CjoLngYZw/appDefinition.json diff --git a/packages/server/runtime_apps/testApp/3-Y5vsgF-ZEjh/plugins.js b/packages/server/runtime_apps/testApp/3-M8CjoLngYZw/plugins.js similarity index 100% rename from packages/server/runtime_apps/testApp/3-Y5vsgF-ZEjh/plugins.js rename to packages/server/runtime_apps/testApp/3-M8CjoLngYZw/plugins.js diff --git a/packages/server/tests/authenticate.js b/packages/server/tests/authenticate.js index d5bf37d75f..8a4e1624d3 100644 --- a/packages/server/tests/authenticate.js +++ b/packages/server/tests/authenticate.js @@ -52,7 +52,6 @@ module.exports = (app, appName) => { name: testUserName, accessLevels:["owner"], enabled:true - }, password: testPassword }) diff --git a/packages/server/tests/createNewApp.js b/packages/server/tests/createNewApp.js index 18dad0cafc..3b398bcbd1 100644 --- a/packages/server/tests/createNewApp.js +++ b/packages/server/tests/createNewApp.js @@ -86,7 +86,7 @@ module.exports = (app) => { user1_instance1 = master.recordApi .getNew(`${newAppKey}/users`, "user"); user1_instance1.name = app.credentials.testApp.username; - + user1_instance1.createdByMaster = true; /*const lookupResponse = await app.get(`/_master/api/lookup_field/${user1_instance1.key}?fields=instance`) .set("cookie", app.credentials._master.cookie) diff --git a/packages/server/tests/testApp.js b/packages/server/tests/testApp.js index c221b2b174..bb5469c52e 100644 --- a/packages/server/tests/testApp.js +++ b/packages/server/tests/testApp.js @@ -4,7 +4,7 @@ const createMasterDb = require("../initialise/createMasterDb"); const request = require("supertest"); const fs = require("fs"); const { masterAppPackage } = require("../utilities/createAppPackage"); - +const buildAppContext = require("../initialise/buildAppContext"); var enableDestroy = require('server-destroy'); const masterOwnerName = "test_master"; @@ -58,7 +58,8 @@ module.exports = () => { start: async () => { try { await reInitialize(); - server = await app(config); + const budibaseContext = await buildAppContext(config, true); + server = await app(budibaseContext); } catch(e) { console.log(e.message); } @@ -85,7 +86,7 @@ module.exports = () => { name: "testApp" }, destroy: () => server.destroy(), - masterAppPackage: masterAppPackage(config) + masterAppPackage: masterAppPackage({ config }) }) }; @@ -110,12 +111,13 @@ const reInitialize = async () => { await mkdir(config.datastoreConfig.rootPath); const datastoreModule = require("../../datastores/datastores/" + config.datastore); + const budibaseContext = await buildAppContext(config, false); await createMasterDb( + budibaseContext, datastoreModule, - config.datastoreConfig, masterOwnerName, - masterOwnerPassword , - config + masterOwnerPassword ); } + diff --git a/packages/server/utilities/budibaseApi.js b/packages/server/utilities/budibaseApi.js index 3a9a3f5e3c..4482fba181 100644 --- a/packages/server/utilities/budibaseApi.js +++ b/packages/server/utilities/budibaseApi.js @@ -1,5 +1,9 @@ const crypto = require("../nodeCrypto"); const {getAppApis, getTemplateApi} = require("budibase-core"); +const getDatastore = require("./datastore"); +const { masterAppPackage } = require("../utilities/createAppPackage"); +const getDatabaseManager = require("../utilities/databaseManager"); + const constructHierarchy = (datastore, appDefinition) => { appDefinition.hierarchy = getTemplateApi({datastore}) @@ -62,4 +66,20 @@ module.exports.getApisForSession = async (datastore, appPackage, session) => { bb.asUser(user); return bb; +} + +module.exports.getMasterApisWithFullAccess = async (context) => { + const { config } = context; + const datastoreModule = getDatastore(config); + + const databaseManager = getDatabaseManager( + datastoreModule, + config.datastoreConfig); + + + const masterDatastore = datastoreModule.getDatastore( + databaseManager.masterDatastoreConfig); + + return await module.exports.getApisWithFullAccess( + masterDatastore, masterAppPackage(context)); } \ No newline at end of file diff --git a/packages/server/utilities/createAppPackage.js b/packages/server/utilities/createAppPackage.js index 1582647b7e..e8fad5f9a1 100644 --- a/packages/server/utilities/createAppPackage.js +++ b/packages/server/utilities/createAppPackage.js @@ -2,7 +2,9 @@ const { join } = require("path"); const constructHierarchy = require("./constructHierarchy"); const { common } = require("budibase-core"); const { getRuntimePackageDirectory } = require("../utilities/runtimePackages"); -const createAppPackage = (config, appPath) => { +const injectPlugins = require("./injectedPlugins"); + +const createAppPackage = (context, appPath) => { const appDefModule = require( join(appPath, "appDefinition.json")); @@ -16,14 +18,15 @@ const createAppPackage = (config, appPath) => { return ({ appDefinition: appDefModule, - behaviourSources: pluginsModule(config), + behaviourSources: pluginsModule(context), appPath, accessLevels }) } -module.exports.masterAppPackage = (config) => { - const standardPackage = createAppPackage(config, "../appPackages/master"); +module.exports.masterAppPackage = (context) => { + const { config } = context; + const standardPackage = createAppPackage(context, "../appPackages/master"); const customizeMaster = config && config.customizeMaster ? config.customizeMaster @@ -35,7 +38,7 @@ module.exports.masterAppPackage = (config) => { ]); const plugins = require("../appPackages/master/plugins.js") - (config); + (context); return ({ appDefinition, @@ -46,11 +49,17 @@ module.exports.masterAppPackage = (config) => { }); } -module.exports.applictionVersionPackage = (config, appname, versionId) => { +module.exports.applictionVersionPackage = async (context, appname, versionId, instanceKey) => { const pkg = createAppPackage( - config, + context, join("..", getRuntimePackageDirectory(appname, versionId)) ); pkg.appDefinition = constructHierarchy(pkg.appDefinition); + await injectPlugins( + pkg, + context.master, + appname, + instanceKey + ); return pkg; } diff --git a/packages/server/utilities/injectedPlugins/createUser.js b/packages/server/utilities/injectedPlugins/createUser.js new file mode 100644 index 0000000000..8181cafc9d --- /dev/null +++ b/packages/server/utilities/injectedPlugins/createUser.js @@ -0,0 +1,17 @@ + + +module.exports = ({ masterAppInternal, instanceKey }) => async ({ user }) => { + const { bbMaster } = masterAppInternal; + const masterUser = bbMaster.recordApi + .getNew(`${newAppKey}/users`, "user"); + masterUser.name = user.name; + masterUser.createdByMaster = false; + masterUser.instance = await bbMaster.recordApi + .load(instanceKey); + + masterUser.active = user.enabled; + await bbMaster.recordApi.save(masterUser); +} + + + diff --git a/packages/server/utilities/injectedPlugins/disableUser.js b/packages/server/utilities/injectedPlugins/disableUser.js new file mode 100644 index 0000000000..e794a079cf --- /dev/null +++ b/packages/server/utilities/injectedPlugins/disableUser.js @@ -0,0 +1,6 @@ + +module.exports = ({ masterAppInternal, app }) => async ({ username }) => { + await masterAppInternal.disableUser( + app, username + ); +} \ No newline at end of file diff --git a/packages/server/utilities/injectedPlugins/enableUser.js b/packages/server/utilities/injectedPlugins/enableUser.js new file mode 100644 index 0000000000..f9bf4a49c6 --- /dev/null +++ b/packages/server/utilities/injectedPlugins/enableUser.js @@ -0,0 +1,6 @@ + +module.exports = ({ masterAppInternal, app }) => async ({ username }) => { + await masterAppInternal.enableUser( + app, username + ); +} \ No newline at end of file diff --git a/packages/server/utilities/injectedPlugins/index.js b/packages/server/utilities/injectedPlugins/index.js new file mode 100644 index 0000000000..74cdc47b97 --- /dev/null +++ b/packages/server/utilities/injectedPlugins/index.js @@ -0,0 +1,77 @@ +const createUser = require("./createUser"); +const enableUser = require("./enableUser"); +const disableUser = require("./disableUser"); + +module.exports = async (appPackage, masterAppInternal, instanceKey, appName) => { + + const plugin = await constructPlugin( + masterAppInternal, + appName, + instanceKey + ); + + appPackage.behaviourSources._injected = plugin; + + createActions(appPackage); + createTriggers(appPackage); +} + +const createTriggers = (appPackage) => { + const appDef = appPackage.appDefinition; + appDef.triggers.push({ + actionName: 'createUser', + eventName: 'authApi:createUser:onComplete', + optionsCreator: 'return {user:context.user};', + condition: '' + }); + appDef.triggers.push({ + actionName: 'enableUser', + eventName: 'authApi:enableUser:onComplete', + optionsCreator: 'return {username:context.username};', + condition: '' + }); + appDef.triggers.push({ + actionName: 'disableUser', + eventName: 'authApi:disableUser:onComplete', + optionsCreator: 'return {username:context.username};', + condition: '' + }); +} + +const createActions = (appPackage) => { + const appDef = appPackage.appDefinition; + appDef.actions.createUser = { + name: "createUser", + behaviourSource: '_injected', + behaviourName: 'createUser', + initialOptions: {} + }; + appDef.actions.createUser = { + name: "enableUser", + behaviourSource: '_injected', + behaviourName: 'enableUser', + initialOptions: {} + }; + appDef.actions.createUser = { + name: "disableUser", + behaviourSource: '_injected', + behaviourName: 'disableUser', + initialOptions: {} + }; +} + + +const constructPlugin = async (masterAppInternal, appName, instanceKey) => { + + const app = await masterAppInternal.getApplication(appName); + const initialiseObj = { + masterAppInternal, app, instanceKey + }; + + return ({ + createUser:createUser(initialiseObj), + enableUser:enableUser(initialiseObj), + disableUser:disableUser(initialiseObj) + }); + +} \ No newline at end of file diff --git a/packages/server/utilities/masterAppInternal.js b/packages/server/utilities/masterAppInternal.js index e9d7e67c01..76eb70f144 100644 --- a/packages/server/utilities/masterAppInternal.js +++ b/packages/server/utilities/masterAppInternal.js @@ -1,27 +1,29 @@ -const {getApisWithFullAccess, getApisForSession} = require("./budibaseApi"); +const { + getApisWithFullAccess, + getApisForSession, + getMasterApisWithFullAccess +} = require("./budibaseApi"); const getDatastore = require("./datastore"); const getDatabaseManager = require("./databaseManager"); const {$, splitKey} = require("budibase-core").common; const { keyBy, last } = require("lodash/fp"); -const {unauthorized} = require("./exceptions"); const { masterAppPackage, applictionVersionPackage } = require("../utilities/createAppPackage"); const isMaster = appname => appname === "_master"; -module.exports = async (config) => { +module.exports = async (context) => { + const { config } = context; const datastoreModule = getDatastore(config); const databaseManager = getDatabaseManager( datastoreModule, config.datastoreConfig); - const masterDatastore = datastoreModule.getDatastore( databaseManager.masterDatastoreConfig); - const bb = await getApisWithFullAccess( - masterDatastore, masterAppPackage(config)); + const bb = await getMasterApisWithFullAccess(context); let applications; const loadApplications = async () => @@ -100,9 +102,11 @@ module.exports = async (config) => { ]); const dsConfig = JSON.parse(instance.datastoreconfig); + const appPackage = await applictionVersionPackage( + context, appname, versionId, instance.key); const bbInstance = await getApisWithFullAccess( datastoreModule.getDatastore(dsConfig), - applictionVersionPackage(config, appname, versionId) + appPackage ); const authUser = await bbInstance.authApi.authenticate(username, password); @@ -115,6 +119,7 @@ module.exports = async (config) => { bb.recordApi.setCustomId(session, sessionId); session.user_json = JSON.stringify(authUser); session.instanceDatastoreConfig = instance.datastoreconfig; + session.instanceKey = instance.key; session.username = username; session.instanceVersion = instance.version.key; await bb.recordApi.save(session); @@ -128,7 +133,7 @@ module.exports = async (config) => { const session = await bb.recordApi.load(`/sessions/${customId}`); return await getApisForSession( masterDatastore, - masterAppPackage(config), + masterAppPackage(context), session); } catch(_) { @@ -147,9 +152,12 @@ module.exports = async (config) => { last ]); + const appPackage = await applictionVersionPackage( + context, appname, versionId, session.instanceKey); + return await getApisForSession( instanceDatastore, - applictionVersionPackage(config, appname, versionId), + appPackage, session); } catch(_) { return null; @@ -190,10 +198,13 @@ module.exports = async (config) => { splitKey, last ]); + + const appPackage = await applictionVersionPackage( + context, appname, versionId, user.instanceKey); return await getApisWithFullAccess( instanceDatastore, - applictionVersionPackage(config, appname, versionId)); + appPackage); } }; @@ -230,6 +241,19 @@ module.exports = async (config) => { } } + const disableUser = async (app, username) => { + await removeSessionsForUser(appName, username); + const userInMaster = await getUser(bb, app.id, username); + userInMaster.active = false; + await bb.recordApi.save(userInMaster); + } + + const enableUser = async (app, username) => { + const userInMaster = await getUser(bb, app.id, username); + userInMaster.active = true; + await bb.recordApi.save(userInMaster); + } + return ({ getApplication, getSession, @@ -238,6 +262,8 @@ module.exports = async (config) => { getInstanceApiForSession, getFullAccessInstanceApiForUsername, removeSessionsForUser, + disableUser, + enableUser, bbMaster:bb });