Shifting over all of self API, deprecating old endpoints.
This commit is contained in:
parent
a2e4ac2b5b
commit
93f2ed11ff
|
@ -15,7 +15,7 @@ export const buildUserEndpoints = API => ({
|
|||
*/
|
||||
fetchBuilderSelf: async () => {
|
||||
return await API.get({
|
||||
url: "/api/global/users/self",
|
||||
url: "/api/global/self",
|
||||
})
|
||||
},
|
||||
|
||||
|
@ -67,7 +67,7 @@ export const buildUserEndpoints = API => ({
|
|||
*/
|
||||
updateSelf: async user => {
|
||||
return await API.post({
|
||||
url: "/api/global/users/self",
|
||||
url: "/api/global/self",
|
||||
body: user,
|
||||
})
|
||||
},
|
||||
|
|
|
@ -59,7 +59,7 @@ exports.sendSmtpEmail = async (to, from, subject, contents, automation) => {
|
|||
}
|
||||
|
||||
exports.getGlobalSelf = async (ctx, appId = null) => {
|
||||
const endpoint = `/api/global/users/self`
|
||||
const endpoint = `/api/global/self`
|
||||
const response = await fetch(
|
||||
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
||||
// we don't want to use API key when getting self
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
||||
const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db")
|
||||
const { user: userCache } = require("@budibase/backend-core/cache")
|
||||
const { hash, platformLogout } = require("@budibase/backend-core/utils")
|
||||
const { newid } = require("@budibase/backend-core/utils")
|
||||
const { getUser } = require("../../utilities")
|
||||
|
||||
function newApiKey() {
|
||||
return `${getTenantId()}${SEPARATOR}${newid()}`
|
||||
return hash(`${getTenantId()}${SEPARATOR}${newid()}`)
|
||||
}
|
||||
|
||||
function cleanupDevInfo(info) {
|
||||
|
@ -43,3 +46,49 @@ exports.fetchAPIKey = async ctx => {
|
|||
}
|
||||
ctx.body = cleanupDevInfo(devInfo)
|
||||
}
|
||||
|
||||
exports.getSelf = async ctx => {
|
||||
if (!ctx.user) {
|
||||
ctx.throw(403, "User not logged in")
|
||||
}
|
||||
const userId = ctx.user._id
|
||||
ctx.params = {
|
||||
id: userId,
|
||||
}
|
||||
// get the main body of the user
|
||||
ctx.body = await getUser(userId)
|
||||
// forward session information not found in db
|
||||
ctx.body.account = ctx.user.account
|
||||
ctx.body.budibaseAccess = ctx.user.budibaseAccess
|
||||
ctx.body.accountPortalAccess = ctx.user.accountPortalAccess
|
||||
ctx.body.csrfToken = ctx.user.csrfToken
|
||||
}
|
||||
|
||||
exports.updateSelf = async ctx => {
|
||||
const db = getGlobalDB()
|
||||
const user = await db.get(ctx.user._id)
|
||||
if (ctx.request.body.password) {
|
||||
// changing password
|
||||
ctx.request.body.password = await hash(ctx.request.body.password)
|
||||
// Log all other sessions out apart from the current one
|
||||
await platformLogout({
|
||||
ctx,
|
||||
userId: ctx.user._id,
|
||||
keepActiveSession: true,
|
||||
})
|
||||
}
|
||||
// don't allow sending up an ID/Rev, always use the existing one
|
||||
delete ctx.request.body._id
|
||||
delete ctx.request.body._rev
|
||||
// don't allow setting the csrf token
|
||||
delete ctx.request.body.csrfToken
|
||||
const response = await db.put({
|
||||
...user,
|
||||
...ctx.request.body,
|
||||
})
|
||||
await userCache.invalidateUser(user._id)
|
||||
ctx.body = {
|
||||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,8 @@ const {
|
|||
generateNewUsageQuotaDoc,
|
||||
} = require("@budibase/backend-core/db")
|
||||
const {
|
||||
hash,
|
||||
getGlobalUserByEmail,
|
||||
saveUser,
|
||||
platformLogout,
|
||||
} = require("@budibase/backend-core/utils")
|
||||
const { EmailTemplatePurpose } = require("../../../constants")
|
||||
const { checkInviteCode } = require("../../../utilities/redis")
|
||||
|
@ -24,7 +22,7 @@ const {
|
|||
const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
|
||||
const env = require("../../../environment")
|
||||
const { syncUserInApps } = require("../../../utilities/appService")
|
||||
const { allUsers } = require("../../utilities")
|
||||
const { allUsers, getUser } = require("../../utilities")
|
||||
|
||||
exports.save = async ctx => {
|
||||
try {
|
||||
|
@ -129,52 +127,6 @@ exports.destroy = async ctx => {
|
|||
}
|
||||
}
|
||||
|
||||
exports.getSelf = async ctx => {
|
||||
if (!ctx.user) {
|
||||
ctx.throw(403, "User not logged in")
|
||||
}
|
||||
ctx.params = {
|
||||
id: ctx.user._id,
|
||||
}
|
||||
// this will set the body
|
||||
await exports.find(ctx)
|
||||
|
||||
// forward session information not found in db
|
||||
ctx.body.account = ctx.user.account
|
||||
ctx.body.budibaseAccess = ctx.user.budibaseAccess
|
||||
ctx.body.accountPortalAccess = ctx.user.accountPortalAccess
|
||||
ctx.body.csrfToken = ctx.user.csrfToken
|
||||
}
|
||||
|
||||
exports.updateSelf = async ctx => {
|
||||
const db = getGlobalDB()
|
||||
const user = await db.get(ctx.user._id)
|
||||
if (ctx.request.body.password) {
|
||||
// changing password
|
||||
ctx.request.body.password = await hash(ctx.request.body.password)
|
||||
// Log all other sessions out apart from the current one
|
||||
await platformLogout({
|
||||
ctx,
|
||||
userId: ctx.user._id,
|
||||
keepActiveSession: true,
|
||||
})
|
||||
}
|
||||
// don't allow sending up an ID/Rev, always use the existing one
|
||||
delete ctx.request.body._id
|
||||
delete ctx.request.body._rev
|
||||
// don't allow setting the csrf token
|
||||
delete ctx.request.body.csrfToken
|
||||
const response = await db.put({
|
||||
...user,
|
||||
...ctx.request.body,
|
||||
})
|
||||
await userCache.invalidateUser(user._id)
|
||||
ctx.body = {
|
||||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
}
|
||||
}
|
||||
|
||||
// called internally by app server user fetch
|
||||
exports.fetch = async ctx => {
|
||||
const users = await allUsers(ctx)
|
||||
|
@ -189,18 +141,7 @@ exports.fetch = async ctx => {
|
|||
|
||||
// called internally by app server user find
|
||||
exports.find = async ctx => {
|
||||
const db = getGlobalDB()
|
||||
let user
|
||||
try {
|
||||
user = await db.get(ctx.params.id)
|
||||
} catch (err) {
|
||||
// no user found, just return nothing
|
||||
user = {}
|
||||
}
|
||||
if (user) {
|
||||
delete user.password
|
||||
}
|
||||
ctx.body = user
|
||||
ctx.body = await getUser(ctx.params.id)
|
||||
}
|
||||
|
||||
exports.tenantUserLookup = async ctx => {
|
||||
|
|
|
@ -67,6 +67,10 @@ const NO_TENANCY_ENDPOINTS = [
|
|||
route: "/api/global/users/self",
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
route: "/api/global/self",
|
||||
method: "GET",
|
||||
},
|
||||
]
|
||||
|
||||
// most public endpoints are gets, but some are posts
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/global/self")
|
||||
const builderOnly = require("../../../middleware/builderOnly")
|
||||
const { buildUserSaveValidation } = require("../../utilities/validation")
|
||||
|
||||
const router = Router()
|
||||
|
||||
router
|
||||
.post("/api/global/self/api_key", builderOnly, controller.generateAPIKey)
|
||||
.get("/api/global/self/api_key", builderOnly, controller.fetchAPIKey)
|
||||
.get("/api/global/self", controller.getSelf)
|
||||
.post(
|
||||
"/api/global/self",
|
||||
buildUserSaveValidation(true),
|
||||
controller.updateSelf
|
||||
)
|
||||
|
||||
module.exports = router
|
||||
|
|
|
@ -4,6 +4,8 @@ const joiValidator = require("../../../middleware/joi-validator")
|
|||
const adminOnly = require("../../../middleware/adminOnly")
|
||||
const Joi = require("joi")
|
||||
const cloudRestricted = require("../../../middleware/cloudRestricted")
|
||||
const { buildUserSaveValidation } = require("../../utilities/validation")
|
||||
const selfController = require("../../controllers/global/self")
|
||||
|
||||
const router = Router()
|
||||
|
||||
|
@ -19,32 +21,6 @@ function buildAdminInitValidation() {
|
|||
)
|
||||
}
|
||||
|
||||
function buildUserSaveValidation(isSelf = false) {
|
||||
let schema = {
|
||||
email: Joi.string().allow(null, ""),
|
||||
password: Joi.string().allow(null, ""),
|
||||
forceResetPassword: Joi.boolean().optional(),
|
||||
firstName: Joi.string().allow(null, ""),
|
||||
lastName: Joi.string().allow(null, ""),
|
||||
builder: Joi.object({
|
||||
global: Joi.boolean().optional(),
|
||||
apps: Joi.array().optional(),
|
||||
})
|
||||
.unknown(true)
|
||||
.optional(),
|
||||
// maps appId -> roleId for the user
|
||||
roles: Joi.object().pattern(/.*/, Joi.string()).required().unknown(true),
|
||||
}
|
||||
if (!isSelf) {
|
||||
schema = {
|
||||
...schema,
|
||||
_id: Joi.string(),
|
||||
_rev: Joi.string(),
|
||||
}
|
||||
}
|
||||
return joiValidator.body(Joi.object(schema).required().unknown(true))
|
||||
}
|
||||
|
||||
function buildInviteValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
|
@ -78,11 +54,6 @@ router
|
|||
controller.invite
|
||||
)
|
||||
// non-global endpoints
|
||||
.post(
|
||||
"/api/global/users/self",
|
||||
buildUserSaveValidation(true),
|
||||
controller.updateSelf
|
||||
)
|
||||
.post(
|
||||
"/api/global/users/invite/accept",
|
||||
buildInviteAcceptValidation(),
|
||||
|
@ -94,10 +65,15 @@ router
|
|||
buildAdminInitValidation(),
|
||||
controller.adminUser
|
||||
)
|
||||
|
||||
.get("/api/global/users/self", controller.getSelf)
|
||||
.get("/api/global/users/tenant/:id", controller.tenantUserLookup)
|
||||
// global endpoint but needs to come at end (blocks other endpoints otherwise)
|
||||
.get("/api/global/users/:id", adminOnly, controller.find)
|
||||
// DEPRECATED - use new versions with self API
|
||||
.get("/api/global/users/self", selfController.getSelf)
|
||||
.post(
|
||||
"/api/global/users/self",
|
||||
buildUserSaveValidation(true),
|
||||
selfController.updateSelf
|
||||
)
|
||||
|
||||
module.exports = router
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||
const { getGlobalUserParams } = require("@budibase/backend-core/db")
|
||||
|
||||
/**
|
||||
* Retrieves all users from the current tenancy.
|
||||
*/
|
||||
exports.allUsers = async () => {
|
||||
const db = getGlobalDB()
|
||||
const response = await db.allDocs(
|
||||
|
@ -10,3 +13,21 @@ exports.allUsers = async () => {
|
|||
)
|
||||
return response.rows.map(row => row.doc)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a user by ID from the global database, based on the current tenancy.
|
||||
*/
|
||||
exports.getUser = async userId => {
|
||||
const db = getGlobalDB()
|
||||
let user
|
||||
try {
|
||||
user = await db.get(userId)
|
||||
} catch (err) {
|
||||
// no user found, just return nothing
|
||||
user = {}
|
||||
}
|
||||
if (user) {
|
||||
delete user.password
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
const joiValidator = require("../../middleware/joi-validator")
|
||||
const Joi = require("joi")
|
||||
|
||||
exports.buildUserSaveValidation = (isSelf = false) => {
|
||||
let schema = {
|
||||
email: Joi.string().allow(null, ""),
|
||||
password: Joi.string().allow(null, ""),
|
||||
forceResetPassword: Joi.boolean().optional(),
|
||||
firstName: Joi.string().allow(null, ""),
|
||||
lastName: Joi.string().allow(null, ""),
|
||||
builder: Joi.object({
|
||||
global: Joi.boolean().optional(),
|
||||
apps: Joi.array().optional(),
|
||||
})
|
||||
.unknown(true)
|
||||
.optional(),
|
||||
// maps appId -> roleId for the user
|
||||
roles: Joi.object().pattern(/.*/, Joi.string()).required().unknown(true),
|
||||
}
|
||||
if (!isSelf) {
|
||||
schema = {
|
||||
...schema,
|
||||
_id: Joi.string(),
|
||||
_rev: Joi.string(),
|
||||
}
|
||||
}
|
||||
return joiValidator.body(Joi.object(schema).required().unknown(true))
|
||||
}
|
Loading…
Reference in New Issue