2021-04-09 16:11:49 +02:00
|
|
|
const fetch = require("node-fetch")
|
|
|
|
const env = require("../environment")
|
|
|
|
const { checkSlashesInUrl } = require("./index")
|
2021-05-14 16:43:41 +02:00
|
|
|
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
2021-05-17 15:20:19 +02:00
|
|
|
const { getDeployedAppID } = require("@budibase/auth/db")
|
2021-04-09 16:11:49 +02:00
|
|
|
|
|
|
|
function getAppRole(appId, user) {
|
|
|
|
if (!user.roles) {
|
|
|
|
return user
|
|
|
|
}
|
|
|
|
user.roleId = user.roles[appId]
|
|
|
|
if (!user.roleId) {
|
|
|
|
user.roleId = BUILTIN_ROLE_IDS.PUBLIC
|
|
|
|
}
|
2021-04-15 16:57:55 +02:00
|
|
|
delete user.roles
|
2021-04-09 16:11:49 +02:00
|
|
|
return user
|
|
|
|
}
|
|
|
|
|
2021-04-15 16:57:55 +02:00
|
|
|
function request(ctx, request) {
|
2021-04-09 16:11:49 +02:00
|
|
|
if (!request.headers) {
|
|
|
|
request.headers = {}
|
|
|
|
}
|
2021-05-10 14:18:05 +02:00
|
|
|
if (request.body && Object.keys(request.body).length > 0) {
|
2021-04-09 16:11:49 +02:00
|
|
|
request.headers["Content-Type"] = "application/json"
|
|
|
|
request.body =
|
|
|
|
typeof request.body === "object"
|
|
|
|
? JSON.stringify(request.body)
|
|
|
|
: request.body
|
2021-05-10 14:18:05 +02:00
|
|
|
} else {
|
|
|
|
delete request.body
|
2021-04-09 16:11:49 +02:00
|
|
|
}
|
2021-05-11 13:02:29 +02:00
|
|
|
if (ctx && ctx.headers) {
|
2021-04-09 18:33:21 +02:00
|
|
|
request.headers.cookie = ctx.headers.cookie
|
|
|
|
}
|
2021-04-09 16:11:49 +02:00
|
|
|
return request
|
|
|
|
}
|
|
|
|
|
2021-04-15 16:57:55 +02:00
|
|
|
exports.request = request
|
|
|
|
|
2021-05-11 16:08:59 +02:00
|
|
|
exports.sendSmtpEmail = async (to, from, subject, contents) => {
|
2021-05-11 13:02:29 +02:00
|
|
|
const response = await fetch(
|
2021-05-11 16:08:59 +02:00
|
|
|
checkSlashesInUrl(env.WORKER_URL + `/api/admin/email/send`),
|
2021-05-11 13:02:29 +02:00
|
|
|
request(null, {
|
|
|
|
method: "POST",
|
|
|
|
headers: {
|
2021-05-11 16:23:03 +02:00
|
|
|
"x-budibase-api-key": env.INTERNAL_API_KEY,
|
2021-05-11 13:02:29 +02:00
|
|
|
},
|
2021-05-11 16:08:59 +02:00
|
|
|
body: {
|
|
|
|
email: to,
|
|
|
|
from,
|
|
|
|
contents,
|
|
|
|
subject,
|
|
|
|
purpose: "custom",
|
|
|
|
},
|
2021-05-11 13:02:29 +02:00
|
|
|
})
|
|
|
|
)
|
2021-05-11 16:08:59 +02:00
|
|
|
|
|
|
|
const json = await response.json()
|
|
|
|
if (json.status !== 200 && response.status !== 200) {
|
|
|
|
throw "Unable to send email."
|
|
|
|
}
|
|
|
|
return json
|
2021-05-11 13:02:29 +02:00
|
|
|
}
|
|
|
|
|
2021-05-04 12:32:22 +02:00
|
|
|
exports.getDeployedApps = async ctx => {
|
2021-04-09 16:11:49 +02:00
|
|
|
try {
|
|
|
|
const response = await fetch(
|
|
|
|
checkSlashesInUrl(env.WORKER_URL + `/api/apps`),
|
2021-04-15 16:57:55 +02:00
|
|
|
request(ctx, {
|
2021-04-09 16:11:49 +02:00
|
|
|
method: "GET",
|
|
|
|
})
|
|
|
|
)
|
|
|
|
const json = await response.json()
|
|
|
|
const apps = {}
|
|
|
|
for (let [key, value] of Object.entries(json)) {
|
|
|
|
if (value.url) {
|
|
|
|
value.url = value.url.toLowerCase()
|
|
|
|
apps[key] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return apps
|
|
|
|
} catch (err) {
|
|
|
|
// error, cannot determine deployed apps, don't stop app creation - sort this later
|
|
|
|
return {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-19 17:26:33 +02:00
|
|
|
exports.deleteGlobalUser = async (ctx, globalId) => {
|
|
|
|
const endpoint = `/api/admin/users/${globalId}`
|
2021-04-09 16:11:49 +02:00
|
|
|
const reqCfg = { method: "DELETE" }
|
|
|
|
const response = await fetch(
|
|
|
|
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
2021-04-15 16:57:55 +02:00
|
|
|
request(ctx, reqCfg)
|
2021-04-09 16:11:49 +02:00
|
|
|
)
|
|
|
|
return response.json()
|
|
|
|
}
|
|
|
|
|
2021-04-19 17:26:33 +02:00
|
|
|
exports.getGlobalUsers = async (ctx, appId = null, globalId = null) => {
|
2021-05-17 15:20:19 +02:00
|
|
|
// always use the deployed app
|
|
|
|
appId = getDeployedAppID(appId)
|
2021-04-19 17:26:33 +02:00
|
|
|
const endpoint = globalId
|
|
|
|
? `/api/admin/users/${globalId}`
|
|
|
|
: `/api/admin/users`
|
2021-04-09 16:11:49 +02:00
|
|
|
const reqCfg = { method: "GET" }
|
|
|
|
const response = await fetch(
|
|
|
|
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
2021-04-15 16:57:55 +02:00
|
|
|
request(ctx, reqCfg)
|
2021-04-09 16:11:49 +02:00
|
|
|
)
|
|
|
|
let users = await response.json()
|
2021-04-15 16:57:55 +02:00
|
|
|
if (!appId) {
|
|
|
|
return users
|
|
|
|
}
|
2021-04-09 16:11:49 +02:00
|
|
|
if (Array.isArray(users)) {
|
2021-05-04 12:32:22 +02:00
|
|
|
users = users.map(user => getAppRole(appId, user))
|
2021-04-09 16:11:49 +02:00
|
|
|
} else {
|
|
|
|
users = getAppRole(appId, users)
|
|
|
|
}
|
|
|
|
return users
|
|
|
|
}
|
|
|
|
|
2021-04-20 18:17:44 +02:00
|
|
|
exports.saveGlobalUser = async (ctx, appId, body) => {
|
|
|
|
const globalUser = body._id
|
|
|
|
? await exports.getGlobalUsers(ctx, appId, body._id)
|
|
|
|
: {}
|
2021-05-17 15:20:19 +02:00
|
|
|
const preRoles = globalUser.roles || {}
|
2021-04-09 16:11:49 +02:00
|
|
|
if (body.roleId) {
|
2021-05-17 15:20:19 +02:00
|
|
|
preRoles[appId] = body.roleId
|
|
|
|
}
|
|
|
|
// make sure no dev app IDs in roles
|
|
|
|
const roles = {}
|
|
|
|
for (let [appId, roleId] of Object.entries(preRoles)) {
|
|
|
|
roles[getDeployedAppID(appId)] = roleId
|
2021-04-09 16:11:49 +02:00
|
|
|
}
|
|
|
|
const endpoint = `/api/admin/users`
|
|
|
|
const reqCfg = {
|
|
|
|
method: "POST",
|
|
|
|
body: {
|
|
|
|
...globalUser,
|
2021-04-13 18:11:55 +02:00
|
|
|
password: body.password || undefined,
|
2021-04-09 16:11:49 +02:00
|
|
|
status: body.status,
|
2021-04-19 17:26:33 +02:00
|
|
|
email: body.email,
|
2021-04-09 16:11:49 +02:00
|
|
|
roles,
|
2021-04-13 19:12:35 +02:00
|
|
|
builder: {
|
|
|
|
global: true,
|
|
|
|
},
|
2021-04-09 16:11:49 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
const response = await fetch(
|
|
|
|
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
2021-04-15 16:57:55 +02:00
|
|
|
request(ctx, reqCfg)
|
2021-04-09 16:11:49 +02:00
|
|
|
)
|
|
|
|
const json = await response.json()
|
|
|
|
if (json.status !== 200 && response.status !== 200) {
|
|
|
|
ctx.throw(400, "Unable to save global user.")
|
|
|
|
}
|
|
|
|
delete body.password
|
2021-04-13 18:11:55 +02:00
|
|
|
delete body.roles
|
|
|
|
delete body.builder
|
2021-04-29 20:06:58 +02:00
|
|
|
// TODO: for now these have been left in as they are
|
|
|
|
// TODO: pretty important to keeping relationships working
|
|
|
|
// TODO: however if user metadata is changed this should be removed
|
|
|
|
// delete body.email
|
|
|
|
// delete body.roleId
|
|
|
|
// delete body.status
|
2021-04-19 17:26:33 +02:00
|
|
|
return {
|
|
|
|
...body,
|
|
|
|
_id: json._id,
|
|
|
|
}
|
2021-04-09 16:11:49 +02:00
|
|
|
}
|