Merge pull request #152 from mjashanks/master

Exposing _master db to builder
This commit is contained in:
Michael Shanks 2020-03-10 10:14:36 +00:00 committed by GitHub
commit f1ba289a89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 session = require("./session")
const StatusCodes = require("../utilities/statusCodes")
const fs = require("fs")
const { resolve } = require("path")
const send = require("koa-send")
const routeHandlers = require("./routeHandlers")
const {
getPackageForBuilder,
getComponentDefinitions,
@ -38,6 +39,25 @@ module.exports = (config, app) => {
ctx.set("x-bbappname", appname)
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()
} else {
const instance = await ctx.master.getInstanceApiForSession(
@ -54,12 +74,6 @@ module.exports = (config, app) => {
}
})
.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 })
})
.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 })
})
.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", "")
if (path.startsWith("/api/")) {
@ -85,58 +93,36 @@ module.exports = (config, app) => {
await send(ctx, path, { root: builderPath })
}
})
.post("/:appname/api/authenticate", 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
})
.post("/:appname/api/setPasswordFromTemporaryCode", 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
})
.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
})
.post("/:appname/api/authenticate", routeHandlers.authenticate)
.post(
"/_builder/instance/:appname/:instanceid/api/authenticate",
routeHandlers.authenticate
)
.post(
"/:appname/api/setPasswordFromTemporaryCode",
routeHandlers.setPasswordFromTemporaryCode
)
.post(
"/_builder/instance/:appname/:instanceid/api/setPasswordFromTemporaryCode",
routeHandlers.setPasswordFromTemporaryCode
)
.post(
"/:appname/api/createTemporaryAccess",
routeHandlers.createTemporaryAccess
)
.post(
"/_builder/instance/:appname/:instanceid/api/createTemporaryAccess",
routeHandlers.createTemporaryAccess
)
.get("/_builder/api/apps", async ctx => {
ctx.body = await getApps(config, ctx.master)
ctx.response.status = StatusCodes.OK
})
.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
})
.get("/_builder/api/:appname/components", async ctx => {
@ -228,23 +214,9 @@ module.exports = (config, app) => {
.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}`, "")
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 })
}
})
.get("/:appname/*", routeHandlers.appDefault)
.get("/_builder/instance/:appname/:instanceid/*", routeHandlers.appDefault)
// EVERYTHING BELOW HERE REQUIRES AUTHENTICATION
.use(async (ctx, next) => {
if (ctx.isAuthenticated) {
await next()
@ -252,147 +224,85 @@ module.exports = (config, app) => {
ctx.response.status = StatusCodes.UNAUTHORIZED
}
})
.post("/:appname/api/changeMyPassword", async ctx => {
await ctx.instance.authApi.changeMyPassword(
ctx.request.body.currentPassword,
ctx.request.body.newPassword
)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/changeMyPassword", async ctx => {
await ctx.instance.authApi.changeMyPassword(
ctx.request.body.currentPassword,
ctx.request.body.newPassword
)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/executeAction/:actionname", async ctx => {
ctx.body = await ctx.instance.actionApi.execute(
ctx.request.body.actionname,
ctx.request.body.parameters
)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/createUser", async ctx => {
await ctx.instance.authApi.createUser(
ctx.request.body.user,
ctx.request.body.password
)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/enableUser", async ctx => {
await ctx.instance.authApi.enableUser(ctx.request.body.username)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/disableUser", 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
})
.get("/:appname/api/users", async ctx => {
ctx.body = await ctx.instance.authApi.getUsers()
ctx.response.status = StatusCodes.OK
})
.get("/:appname/api/accessLevels", async ctx => {
ctx.body = await ctx.instance.authApi.getAccessLevels()
ctx.response.status = StatusCodes.OK
})
.get("/:appname/api/listRecords/*", async ctx => {
const indexkey = getRecordKey(ctx.params.appname, ctx.request.path)
ctx.body = await ctx.instance.indexApi.listItems(indexkey)
ctx.response.status = StatusCodes.OK
})
.post("/:appname/api/listRecords/*", 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
})
.post("/:appname/api/aggregates/*", 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
})
.post("/:appname/api/files/*", 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
})
.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/`, "")
.post("/:appname/api/changeMyPassword", routeHandlers.changeMyPassword)
.post(
"/_builder/instance/:appname/:instanceid/api/changeMyPassword",
routeHandlers.changeMyPassword
)
.post(
"/:appname/api/executeAction/:actionname",
routeHandlers.executeAction
)
.post(
"/_builder/instance/:appname/:instanceid/api/executeAction/:actionname",
routeHandlers.executeAction
)
.post("/:appname/api/createUser", routeHandlers.createUser)
.post(
"/_builder/instance/:appname/:instanceid/api/createUser",
routeHandlers.createUser
)
.post("/:appname/api/enableUser", routeHandlers.enableUser)
.post(
"/_builder/instance/:appname/:instanceid/api/enableUser",
routeHandlers.enableUser
)
.post("/:appname/api/disableUser", routeHandlers.disableUser)
.post(
"/_builder/instance/:appname/:instanceid/api/disableUser",
routeHandlers.disableUser
)
.get("/:appname/api/users", routeHandlers.getUsers)
.get(
"/_builder/instance/:appname/:instanceid/api/users",
routeHandlers.getUsers
)
.get("/:appname/api/accessLevels", routeHandlers.getAccessLevels)
.get(
"/_builder/instance/:appname/:instanceid/api/accessLevels",
routeHandlers.getAccessLevels
)
.get("/:appname/api/listRecords/*", routeHandlers.listRecordsGet)
.get(
"/_builder/instance/:appname/:instanceid/api/listRecords/*",
routeHandlers.listRecordsGet
)
.post("/:appname/api/listRecords/*", routeHandlers.listRecordsPost)
.post(
"/_builder/instance/:appname/:instanceid/api/listRecords/*",
routeHandlers.listRecordsPost
)
.post("/:appname/api/aggregates/*", routeHandlers.aggregatesPost)
.post(
"/_builder/instance/:appname/:instanceid/api/aggregates/*",
routeHandlers.aggregatesPost
)
.post("/:appname/api/files/*", routeHandlers.postFiles)
.post(
"/_builder/instance/:appname/:instanceid/api/files/*",
routeHandlers.postFiles
)
.post("/:appname/api/record/*", routeHandlers.saveRecord)
.post(
"/_builder/instance/:appname/:instanceid/api/record/*",
routeHandlers.saveRecord
)
.get("/:appname/api/lookup_field/*", routeHandlers.lookupField)
.get(
"/_builder/instance/:appname/:instanceid/api/lookup_field/*",
routeHandlers.lookupField
)
.get("/:appname/api/record/*", routeHandlers.getRecord)
.get(
"/_builder/instance/:appname/:instanceid/api/record/*",
routeHandlers.getRecord
)
.del("/:appname/api/record/*", routeHandlers.deleteRecord)
.del(
"/_builder/instance/:appname/:instanceid/api/record/*",
routeHandlers.deleteRecord
)
.post("/:appname/api/apphierarchy", routeHandlers.saveAppHierarchy)
return router
}

View File

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

View File

@ -6,7 +6,7 @@ const {
const getDatastore = require("./datastore")
const getDatabaseManager = require("./databaseManager")
const { $ } = require("@budibase/core").common
const { keyBy, values } = require("lodash/fp")
const { keyBy, values, cloneDeep } = require("lodash/fp")
const {
masterAppPackage,
applictionVersionPackage,
@ -128,20 +128,10 @@ module.exports = async context => {
const userInMaster = await getUser(app.id, username)
if (!userInMaster) return null
const instance = await bb.recordApi.load(userInMaster.instance.key)
const versionId = determineVersionId(instance.version)
const dsConfig = JSON.parse(instance.datastoreconfig)
const appPackage = await applictionVersionPackage(
context,
const { instance, bbInstance } = await getFullAccessApiForInstanceId(
appname,
versionId,
instance.key
)
const bbInstance = await getApisWithFullAccess(
datastoreModule.getDatastore(dsConfig),
appPackage
userInMaster.instance.id,
app.id
)
const authUser = await bbInstance.authApi.authenticate(username, password)
@ -164,6 +154,34 @@ module.exports = async context => {
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) => {
if (isMaster(appname)) {
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) => {
await removeSessionsForUser(app.name, username)
const userInMaster = await getUser(app.id, username)
@ -324,5 +350,8 @@ module.exports = async context => {
createAppUser,
bbMaster: bb,
listApplications,
getFullAccessApiForInstanceId,
getFullAccessApiForMaster,
getApplicationWithInstances,
}
}