exposing _master database operations to builder

This commit is contained in:
Michael Shanks 2020-03-10 10:05:09 +00:00
parent 14ad487d92
commit f8e71d0e96
25 changed files with 448 additions and 234 deletions

View File

@ -0,0 +1,12 @@
const StatusCodes = require("../../utilities/statusCodes")
const { getRecordKey } = require("./helpers")
module.exports = async ctx => {
const indexkey = getRecordKey(ctx.params.appname, ctx.request.path)
ctx.body = await ctx.instance.indexApi.aggregates(indexkey, {
rangeStartParams: ctx.request.body.rangeStartParams,
rangeEndParams: ctx.request.body.rangeEndParams,
searchPhrase: ctx.request.body.searchPhrase,
})
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,19 @@
const send = require("koa-send")
module.exports = async (ctx, next) => {
const path = ctx.path.replace(`/${ctx.params.appname}`, "")
if (path.startsWith("/api/")) {
await next()
} else if (path.startsWith("/_shared/")) {
await send(ctx, path.replace(`/_shared/`, ""), { root: ctx.sharedPath })
} else if (
path.endsWith(".js") ||
path.endsWith(".map") ||
path.endsWith(".css")
) {
await send(ctx, path, { root: ctx.publicPath })
} else {
await send(ctx, "/index.html", { root: ctx.publicPath })
}
}

View File

@ -0,0 +1,15 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
const user = await ctx.master.authenticate(
ctx.sessionId,
ctx.params.appname,
ctx.request.body.username,
ctx.request.body.password
)
if (!user) {
ctx.throw(StatusCodes.UNAUTHORIZED, "invalid username or password")
}
ctx.body = user.user_json
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,9 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
await ctx.instance.authApi.changeMyPassword(
ctx.request.body.currentPassword,
ctx.request.body.newPassword
)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,17 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
const instanceApi = await ctx.master.getFullAccessInstanceApiForUsername(
ctx.params.appname,
ctx.request.body.username
)
if (!instanceApi) {
ctx.request.status = StatusCodes.OK
return
}
await instanceApi.authApi.createTemporaryAccess(ctx.request.body.username)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,10 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
await ctx.instance.authApi.createUser(
ctx.request.body.user,
ctx.request.body.password
)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,9 @@
const StatusCodes = require("../../utilities/statusCodes")
const { getRecordKey } = require("./helpers")
module.exports = async ctx => {
await ctx.instance.recordApi.delete(
getRecordKey(ctx.params.appname, ctx.request.path)
)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,11 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
await ctx.instance.authApi.disableUser(ctx.request.body.username)
await ctx.master.removeSessionsForUser(
ctx.params.appname,
ctx.request.body.username
)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,6 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
await ctx.instance.authApi.enableUser(ctx.request.body.username)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,9 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
ctx.body = await ctx.instance.actionApi.execute(
ctx.request.body.actionname,
ctx.request.body.parameters
)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,6 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
ctx.body = await ctx.instance.authApi.getAccessLevels()
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,15 @@
const StatusCodes = require("../../utilities/statusCodes")
const { getRecordKey } = require("./helpers")
module.exports = async ctx => {
try {
ctx.body = await ctx.instance.recordApi.load(
getRecordKey(ctx.params.appname, ctx.request.path)
)
ctx.response.status = StatusCodes.OK
} catch (e) {
// need to be catching for 404s here
ctx.response.status = StatusCodes.INTERAL_ERROR
ctx.response.body = e.message
}
}

View File

@ -0,0 +1,6 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
ctx.body = await ctx.instance.authApi.getUsers()
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,7 @@
exports.getRecordKey = (appname, wholePath) =>
wholePath
.replace(`/${appname}/api/files/`, "")
.replace(`/${appname}/api/lookup_field/`, "")
.replace(`/${appname}/api/record/`, "")
.replace(`/${appname}/api/listRecords/`, "")
.replace(`/${appname}/api/aggregates/`, "")

View File

@ -0,0 +1,43 @@
const authenticate = require("./authenticate")
const setPasswordFromTemporaryCode = require("./setPasswordFromTemporaryCode")
const createTemporaryAccess = require("./createTemporaryAccess")
const appDefault = require("./appDefault")
const changeMyPassword = require("./changeMyPassword")
const executeAction = require("./executeAction")
const createUser = require("./createUser")
const enableUser = require("./enableUser")
const disableUser = require("./disableUser")
const getUsers = require("./getUsers")
const getAccessLevels = require("./getAccessLevels")
const listRecordsGet = require("./listRecordsGet")
const listRecordsPost = require("./listRecordsPost")
const aggregatesPost = require("./aggregatesPost")
const postFiles = require("./postFiles")
const saveRecord = require("./saveRecord")
const lookupField = require("./lookupField")
const getRecord = require("./getRecord")
const deleteRecord = require("./deleteRecord")
const saveAppHierarchy = require("./saveAppHierarchy")
module.exports = {
authenticate,
setPasswordFromTemporaryCode,
createTemporaryAccess,
appDefault,
changeMyPassword,
executeAction,
createUser,
enableUser,
disableUser,
getUsers,
getAccessLevels,
listRecordsGet,
listRecordsPost,
aggregatesPost,
postFiles,
saveRecord,
lookupField,
getRecord,
deleteRecord,
saveAppHierarchy,
}

View File

@ -0,0 +1,8 @@
const StatusCodes = require("../../utilities/statusCodes")
const { getRecordKey } = require("./helpers")
module.exports = async ctx => {
const indexkey = getRecordKey(ctx.params.appname, ctx.request.path)
ctx.body = await ctx.instance.indexApi.listItems(indexkey)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,12 @@
const StatusCodes = require("../../utilities/statusCodes")
const { getRecordKey } = require("./helpers")
module.exports = async ctx => {
const indexkey = getRecordKey(ctx.params.appname, ctx.request.path)
ctx.body = await ctx.instance.indexApi.listItems(indexkey, {
rangeStartParams: ctx.request.body.rangeStartParams,
rangeEndParams: ctx.request.body.rangeEndParams,
searchPhrase: ctx.request.body.searchPhrase,
})
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,14 @@
const StatusCodes = require("../../utilities/statusCodes")
const { getRecordKey } = require("./helpers")
module.exports = async ctx => {
const recordKey = getRecordKey(ctx.params.appname, ctx.request.path)
const fields = ctx.query.fields.split(",")
const recordContext = await ctx.instance.recordApi.getContext(recordKey)
const allContext = []
for (let field of fields) {
allContext.push(await recordContext.referenceOptions(field))
}
ctx.body = allContext
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,13 @@
const StatusCodes = require("../../utilities/statusCodes")
const { getRecordKey } = require("./helpers")
const fs = require("fs")
module.exports = async ctx => {
const file = ctx.request.files.file
ctx.body = await ctx.instance.recordApi.uploadFile(
getRecordKey(ctx.params.appname, ctx.request.path),
fs.createReadStream(file.path),
file.name
)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,6 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
ctx.body = await ctx.instance.templateApi.saveApplicationHierarchy(ctx.body)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,6 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
ctx.body = await ctx.instance.recordApi.save(ctx.request.body)
ctx.response.status = StatusCodes.OK
}

View File

@ -0,0 +1,20 @@
const StatusCodes = require("../../utilities/statusCodes")
module.exports = async ctx => {
const instanceApi = await ctx.master.getFullAccessInstanceApiForUsername(
ctx.params.appname,
ctx.request.body.username
)
if (!instanceApi) {
ctx.request.status = StatusCodes.OK
return
}
await instanceApi.authApi.setPasswordFromTemporaryCode(
ctx.request.body.tempCode,
ctx.request.body.newPassword
)
ctx.response.status = StatusCodes.OK
}

View File

@ -1,9 +1,10 @@
const Router = require("@koa/router") const Router = require("@koa/router")
const session = require("./session") const session = require("./session")
const StatusCodes = require("../utilities/statusCodes") const StatusCodes = require("../utilities/statusCodes")
const fs = require("fs")
const { resolve } = require("path") const { resolve } = require("path")
const send = require("koa-send") const send = require("koa-send")
const routeHandlers = require("./routeHandlers")
const { const {
getPackageForBuilder, getPackageForBuilder,
getComponentDefinitions, getComponentDefinitions,
@ -38,6 +39,25 @@ module.exports = (config, app) => {
ctx.set("x-bbappname", appname) ctx.set("x-bbappname", appname)
if (appname === "_builder") { if (appname === "_builder") {
if (!config.dev) {
ctx.response.status = StatusCodes.FORBIDDEN
ctx.body = "run in dev mode to access builder"
return
}
if (ctx.path.startsWith("/_builder/instance/_master")) {
ctx.instance = ctx.master.getFullAccessApiForMaster()
ctx.isAuthenticated = !!ctx.instance
} else if (ctx.path.startsWith("/_builder/instance")) {
const builderAppName = pathParts[3]
const instanceId = pathParts[4]
ctx.instance = ctx.master.getFullAccessApiForInstanceId(
builderAppName,
instanceId
).bbInstance
ctx.isAuthenticated = !!ctx.instance
}
await next() await next()
} else { } else {
const instance = await ctx.master.getInstanceApiForSession( const instance = await ctx.master.getInstanceApiForSession(
@ -54,12 +74,6 @@ module.exports = (config, app) => {
} }
}) })
.get("/_builder", async ctx => { .get("/_builder", async ctx => {
if (!config.dev) {
ctx.response.status = StatusCodes.FORBIDDEN
ctx.body = "run in dev mode to access builder"
return
}
await send(ctx, "/index.html", { root: builderPath }) await send(ctx, "/index.html", { root: builderPath })
}) })
.get("/_builder/:appname/componentlibrary", async ctx => { .get("/_builder/:appname/componentlibrary", async ctx => {
@ -71,12 +85,6 @@ module.exports = (config, app) => {
await send(ctx, info.components._lib || "index.js", { root: info.libDir }) await send(ctx, info.components._lib || "index.js", { root: info.libDir })
}) })
.get("/_builder/*", async (ctx, next) => { .get("/_builder/*", async (ctx, next) => {
if (!config.dev) {
ctx.response.status = StatusCodes.FORBIDDEN
ctx.body = "run in dev mode to access builder"
return
}
const path = ctx.path.replace("/_builder", "") const path = ctx.path.replace("/_builder", "")
if (path.startsWith("/api/")) { if (path.startsWith("/api/")) {
@ -85,58 +93,36 @@ module.exports = (config, app) => {
await send(ctx, path, { root: builderPath }) await send(ctx, path, { root: builderPath })
} }
}) })
.post("/:appname/api/authenticate", async ctx => { .post("/:appname/api/authenticate", routeHandlers.authenticate)
const user = await ctx.master.authenticate( .post(
ctx.sessionId, "/_builder/instance/:appname/:instanceid/api/authenticate",
ctx.params.appname, routeHandlers.authenticate
ctx.request.body.username, )
ctx.request.body.password .post(
) "/:appname/api/setPasswordFromTemporaryCode",
if (!user) { routeHandlers.setPasswordFromTemporaryCode
ctx.throw(StatusCodes.UNAUTHORIZED, "invalid username or password") )
} .post(
ctx.body = user.user_json "/_builder/instance/:appname/:instanceid/api/setPasswordFromTemporaryCode",
ctx.response.status = StatusCodes.OK routeHandlers.setPasswordFromTemporaryCode
}) )
.post("/:appname/api/setPasswordFromTemporaryCode", async ctx => { .post(
const instanceApi = await ctx.master.getFullAccessInstanceApiForUsername( "/:appname/api/createTemporaryAccess",
ctx.params.appname, routeHandlers.createTemporaryAccess
ctx.request.body.username )
) .post(
"/_builder/instance/:appname/:instanceid/api/createTemporaryAccess",
if (!instanceApi) { routeHandlers.createTemporaryAccess
ctx.request.status = StatusCodes.OK )
return
}
await instanceApi.authApi.setPasswordFromTemporaryCode(
ctx.request.body.tempCode,
ctx.request.body.newPassword
)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/createTemporaryAccess", async ctx => {
const instanceApi = await ctx.master.getFullAccessInstanceApiForUsername(
ctx.params.appname,
ctx.request.body.username
)
if (!instanceApi) {
ctx.request.status = StatusCodes.OK
return
}
await instanceApi.authApi.createTemporaryAccess(ctx.request.body.username)
ctx.response.status = StatusCodes.OK
})
.get("/_builder/api/apps", async ctx => { .get("/_builder/api/apps", async ctx => {
ctx.body = await getApps(config, ctx.master) ctx.body = await getApps(config, ctx.master)
ctx.response.status = StatusCodes.OK ctx.response.status = StatusCodes.OK
}) })
.get("/_builder/api/:appname/appPackage", async ctx => { .get("/_builder/api/:appname/appPackage", async ctx => {
ctx.body = await getPackageForBuilder(config, ctx.params.appname) const application = await ctx.master.getApplicationWithInstances(
ctx.params.appname
)
ctx.body = await getPackageForBuilder(config, application)
ctx.response.status = StatusCodes.OK ctx.response.status = StatusCodes.OK
}) })
.get("/_builder/api/:appname/components", async ctx => { .get("/_builder/api/:appname/components", async ctx => {
@ -228,23 +214,9 @@ module.exports = (config, app) => {
.get("/:appname", async ctx => { .get("/:appname", async ctx => {
await send(ctx, "/index.html", { root: ctx.publicPath }) await send(ctx, "/index.html", { root: ctx.publicPath })
}) })
.get("/:appname/*", async (ctx, next) => { .get("/:appname/*", routeHandlers.appDefault)
const path = ctx.path.replace(`/${ctx.params.appname}`, "") .get("/_builder/instance/:appname/:instanceid/*", routeHandlers.appDefault)
// EVERYTHING BELOW HERE REQUIRES AUTHENTICATION
if (path.startsWith("/api/")) {
await next()
} else if (path.startsWith("/_shared/")) {
await send(ctx, path.replace(`/_shared/`, ""), { root: ctx.sharedPath })
} else if (
path.endsWith(".js") ||
path.endsWith(".map") ||
path.endsWith(".css")
) {
await send(ctx, path, { root: ctx.publicPath })
} else {
await send(ctx, "/index.html", { root: ctx.publicPath })
}
})
.use(async (ctx, next) => { .use(async (ctx, next) => {
if (ctx.isAuthenticated) { if (ctx.isAuthenticated) {
await next() await next()
@ -252,147 +224,85 @@ module.exports = (config, app) => {
ctx.response.status = StatusCodes.UNAUTHORIZED ctx.response.status = StatusCodes.UNAUTHORIZED
} }
}) })
.post("/:appname/api/changeMyPassword", async ctx => { .post("/:appname/api/changeMyPassword", routeHandlers.changeMyPassword)
await ctx.instance.authApi.changeMyPassword( .post(
ctx.request.body.currentPassword, "/_builder/instance/:appname/:instanceid/api/changeMyPassword",
ctx.request.body.newPassword routeHandlers.changeMyPassword
) )
ctx.response.status = StatusCodes.OK .post(
}) "/:appname/api/executeAction/:actionname",
.post("/:appname/api/changeMyPassword", async ctx => { routeHandlers.executeAction
await ctx.instance.authApi.changeMyPassword( )
ctx.request.body.currentPassword, .post(
ctx.request.body.newPassword "/_builder/instance/:appname/:instanceid/api/executeAction/:actionname",
) routeHandlers.executeAction
ctx.response.status = StatusCodes.OK )
}) .post("/:appname/api/createUser", routeHandlers.createUser)
.post("/:appname/api/executeAction/:actionname", async ctx => { .post(
ctx.body = await ctx.instance.actionApi.execute( "/_builder/instance/:appname/:instanceid/api/createUser",
ctx.request.body.actionname, routeHandlers.createUser
ctx.request.body.parameters )
) .post("/:appname/api/enableUser", routeHandlers.enableUser)
ctx.response.status = StatusCodes.OK .post(
}) "/_builder/instance/:appname/:instanceid/api/enableUser",
.post("/:appname/api/createUser", async ctx => { routeHandlers.enableUser
await ctx.instance.authApi.createUser( )
ctx.request.body.user, .post("/:appname/api/disableUser", routeHandlers.disableUser)
ctx.request.body.password .post(
) "/_builder/instance/:appname/:instanceid/api/disableUser",
routeHandlers.disableUser
ctx.response.status = StatusCodes.OK )
}) .get("/:appname/api/users", routeHandlers.getUsers)
.post("/:appname/api/enableUser", async ctx => { .get(
await ctx.instance.authApi.enableUser(ctx.request.body.username) "/_builder/instance/:appname/:instanceid/api/users",
ctx.response.status = StatusCodes.OK routeHandlers.getUsers
}) )
.post("/:appname/api/disableUser", async ctx => { .get("/:appname/api/accessLevels", routeHandlers.getAccessLevels)
await ctx.instance.authApi.disableUser(ctx.request.body.username) .get(
"/_builder/instance/:appname/:instanceid/api/accessLevels",
await ctx.master.removeSessionsForUser( routeHandlers.getAccessLevels
ctx.params.appname, )
ctx.request.body.username .get("/:appname/api/listRecords/*", routeHandlers.listRecordsGet)
) .get(
ctx.response.status = StatusCodes.OK "/_builder/instance/:appname/:instanceid/api/listRecords/*",
}) routeHandlers.listRecordsGet
.get("/:appname/api/users", async ctx => { )
ctx.body = await ctx.instance.authApi.getUsers() .post("/:appname/api/listRecords/*", routeHandlers.listRecordsPost)
ctx.response.status = StatusCodes.OK .post(
}) "/_builder/instance/:appname/:instanceid/api/listRecords/*",
.get("/:appname/api/accessLevels", async ctx => { routeHandlers.listRecordsPost
ctx.body = await ctx.instance.authApi.getAccessLevels() )
ctx.response.status = StatusCodes.OK .post("/:appname/api/aggregates/*", routeHandlers.aggregatesPost)
}) .post(
.get("/:appname/api/listRecords/*", async ctx => { "/_builder/instance/:appname/:instanceid/api/aggregates/*",
const indexkey = getRecordKey(ctx.params.appname, ctx.request.path) routeHandlers.aggregatesPost
ctx.body = await ctx.instance.indexApi.listItems(indexkey) )
ctx.response.status = StatusCodes.OK .post("/:appname/api/files/*", routeHandlers.postFiles)
}) .post(
.post("/:appname/api/listRecords/*", async ctx => { "/_builder/instance/:appname/:instanceid/api/files/*",
const indexkey = getRecordKey(ctx.params.appname, ctx.request.path) routeHandlers.postFiles
ctx.body = await ctx.instance.indexApi.listItems(indexkey, { )
rangeStartParams: ctx.request.body.rangeStartParams, .post("/:appname/api/record/*", routeHandlers.saveRecord)
rangeEndParams: ctx.request.body.rangeEndParams, .post(
searchPhrase: ctx.request.body.searchPhrase, "/_builder/instance/:appname/:instanceid/api/record/*",
}) routeHandlers.saveRecord
ctx.response.status = StatusCodes.OK )
}) .get("/:appname/api/lookup_field/*", routeHandlers.lookupField)
.post("/:appname/api/aggregates/*", async ctx => { .get(
const indexkey = getRecordKey(ctx.params.appname, ctx.request.path) "/_builder/instance/:appname/:instanceid/api/lookup_field/*",
ctx.body = await ctx.instance.indexApi.aggregates(indexkey, { routeHandlers.lookupField
rangeStartParams: ctx.request.body.rangeStartParams, )
rangeEndParams: ctx.request.body.rangeEndParams, .get("/:appname/api/record/*", routeHandlers.getRecord)
searchPhrase: ctx.request.body.searchPhrase, .get(
}) "/_builder/instance/:appname/:instanceid/api/record/*",
ctx.response.status = StatusCodes.OK routeHandlers.getRecord
}) )
.post("/:appname/api/files/*", async ctx => { .del("/:appname/api/record/*", routeHandlers.deleteRecord)
const file = ctx.request.files.file .del(
ctx.body = await ctx.instance.recordApi.uploadFile( "/_builder/instance/:appname/:instanceid/api/record/*",
getRecordKey(ctx.params.appname, ctx.request.path), routeHandlers.deleteRecord
fs.createReadStream(file.path), )
file.name .post("/:appname/api/apphierarchy", routeHandlers.saveAppHierarchy)
)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/record/*", async ctx => {
ctx.body = await ctx.instance.recordApi.save(ctx.request.body)
ctx.response.status = StatusCodes.OK
})
.get("/:appname/api/lookup_field/*", async ctx => {
const recordKey = getRecordKey(ctx.params.appname, ctx.request.path)
const fields = ctx.query.fields.split(",")
const recordContext = await ctx.instance.recordApi.getContext(recordKey)
const allContext = []
for (let field of fields) {
allContext.push(await recordContext.referenceOptions(field))
}
ctx.body = allContext
ctx.response.status = StatusCodes.OK
})
.get("/:appname/api/record/*", async ctx => {
try {
ctx.body = await ctx.instance.recordApi.load(
getRecordKey(ctx.params.appname, ctx.request.path)
)
ctx.response.status = StatusCodes.OK
} catch (e) {
// need to be catching for 404s here
ctx.response.status = StatusCodes.INTERAL_ERROR
ctx.response.body = e.message
}
})
.del("/:appname/api/record/*", async ctx => {
await ctx.instance.recordApi.delete(
getRecordKey(ctx.params.appname, ctx.request.path)
)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/apphierarchy", async ctx => {
ctx.body = await ctx.instance.templateApi.saveApplicationHierarchy(
ctx.body
)
ctx.response.status = StatusCodes.OK
})
/*.post("/:appname/api/actionsAndTriggers", async (ctx) => {
ctx.body = await ctx.instance.templateApi.saveApplicationHierarchy(
ctx.body
);
ctx.response.status = StatusCodes.OK;
})
.get("/:appname/api/appDefinition", async (ctx) => {
ctx.body = await ctx.instance.templateApi.saveActionsAndTriggers(
ctx.body
);
ctx.response.status = StatusCodes.OK;
})*/
const getRecordKey = (appname, wholePath) =>
wholePath
.replace(`/${appname}/api/files/`, "")
.replace(`/${appname}/api/lookup_field/`, "")
.replace(`/${appname}/api/record/`, "")
.replace(`/${appname}/api/listRecords/`, "")
.replace(`/${appname}/api/aggregates/`, "")
return router return router
} }

View File

@ -27,8 +27,8 @@ module.exports.saveBackend = saveBackend
const getAppDefinition = async appPath => const getAppDefinition = async appPath =>
await readJSON(`${appPath}/appDefinition.json`) await readJSON(`${appPath}/appDefinition.json`)
module.exports.getPackageForBuilder = async (config, appname) => { module.exports.getPackageForBuilder = async (config, application) => {
const appPath = appPackageFolder(config, appname) const appPath = appPackageFolder(config, application.name)
const pages = await getPages(appPath) const pages = await getPages(appPath)
@ -40,6 +40,8 @@ module.exports.getPackageForBuilder = async (config, appname) => {
pages, pages,
components: await getComponentDefinitions(appPath, pages), components: await getComponentDefinitions(appPath, pages),
application,
} }
} }

View File

@ -6,7 +6,7 @@ const {
const getDatastore = require("./datastore") const getDatastore = require("./datastore")
const getDatabaseManager = require("./databaseManager") const getDatabaseManager = require("./databaseManager")
const { $ } = require("@budibase/core").common const { $ } = require("@budibase/core").common
const { keyBy, values } = require("lodash/fp") const { keyBy, values, cloneDeep } = require("lodash/fp")
const { const {
masterAppPackage, masterAppPackage,
applictionVersionPackage, applictionVersionPackage,
@ -128,20 +128,10 @@ module.exports = async context => {
const userInMaster = await getUser(app.id, username) const userInMaster = await getUser(app.id, username)
if (!userInMaster) return null if (!userInMaster) return null
const instance = await bb.recordApi.load(userInMaster.instance.key) const { instance, bbInstance } = await getFullAccessApiForInstanceId(
const versionId = determineVersionId(instance.version)
const dsConfig = JSON.parse(instance.datastoreconfig)
const appPackage = await applictionVersionPackage(
context,
appname, appname,
versionId, userInMaster.instance.id,
instance.key app.id
)
const bbInstance = await getApisWithFullAccess(
datastoreModule.getDatastore(dsConfig),
appPackage
) )
const authUser = await bbInstance.authApi.authenticate(username, password) const authUser = await bbInstance.authApi.authenticate(username, password)
@ -164,6 +154,34 @@ module.exports = async context => {
return session return session
} }
const getFullAccessApiForInstanceId = async (appname, instanceId, appId) => {
if (!appId) {
appId = (await getApplication(appname)).id
}
const instanceKey = `/applications/${appId}/instances/${instanceId}`
const instance = await bb.recordApi.load(instanceKey)
const versionId = determineVersionId(instance.version)
const dsConfig = JSON.parse(instance.datastoreconfig)
const appPackage = await applictionVersionPackage(
context,
appname,
versionId,
instance.key
)
return {
bbInstance: await getApisWithFullAccess(
datastoreModule.getDatastore(dsConfig),
appPackage
),
instance,
}
}
const getFullAccessApiForMaster = async () =>
await getApisWithFullAccess(masterDatastore, masterAppPackage(context))
const getInstanceApiForSession = async (appname, sessionId) => { const getInstanceApiForSession = async (appname, sessionId) => {
if (isMaster(appname)) { if (isMaster(appname)) {
const customId = bb.recordApi.customId("mastersession", sessionId) const customId = bb.recordApi.customId("mastersession", sessionId)
@ -295,6 +313,14 @@ module.exports = async context => {
} }
} }
const getApplicationWithInstances = async appname => {
const app = cloneDeep(await getApplication(appname))
app.instances = await bb.indexApi.listItems(
`/applications/${app.id}/allinstances`
)
return app
}
const disableUser = async (app, username) => { const disableUser = async (app, username) => {
await removeSessionsForUser(app.name, username) await removeSessionsForUser(app.name, username)
const userInMaster = await getUser(app.id, username) const userInMaster = await getUser(app.id, username)
@ -324,5 +350,8 @@ module.exports = async context => {
createAppUser, createAppUser,
bbMaster: bb, bbMaster: bb,
listApplications, listApplications,
getFullAccessApiForInstanceId,
getFullAccessApiForMaster,
getApplicationWithInstances,
} }
} }