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 () => {
|
fetchBuilderSelf: async () => {
|
||||||
return await API.get({
|
return await API.get({
|
||||||
url: "/api/global/users/self",
|
url: "/api/global/self",
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ export const buildUserEndpoints = API => ({
|
||||||
*/
|
*/
|
||||||
updateSelf: async user => {
|
updateSelf: async user => {
|
||||||
return await API.post({
|
return await API.post({
|
||||||
url: "/api/global/users/self",
|
url: "/api/global/self",
|
||||||
body: user,
|
body: user,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -59,7 +59,7 @@ exports.sendSmtpEmail = async (to, from, subject, contents, automation) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getGlobalSelf = async (ctx, appId = null) => {
|
exports.getGlobalSelf = async (ctx, appId = null) => {
|
||||||
const endpoint = `/api/global/users/self`
|
const endpoint = `/api/global/self`
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
||||||
// we don't want to use API key when getting self
|
// we don't want to use API key when getting self
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
||||||
const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db")
|
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 { newid } = require("@budibase/backend-core/utils")
|
||||||
|
const { getUser } = require("../../utilities")
|
||||||
|
|
||||||
function newApiKey() {
|
function newApiKey() {
|
||||||
return `${getTenantId()}${SEPARATOR}${newid()}`
|
return hash(`${getTenantId()}${SEPARATOR}${newid()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupDevInfo(info) {
|
function cleanupDevInfo(info) {
|
||||||
|
@ -43,3 +46,49 @@ exports.fetchAPIKey = async ctx => {
|
||||||
}
|
}
|
||||||
ctx.body = cleanupDevInfo(devInfo)
|
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,
|
generateNewUsageQuotaDoc,
|
||||||
} = require("@budibase/backend-core/db")
|
} = require("@budibase/backend-core/db")
|
||||||
const {
|
const {
|
||||||
hash,
|
|
||||||
getGlobalUserByEmail,
|
getGlobalUserByEmail,
|
||||||
saveUser,
|
saveUser,
|
||||||
platformLogout,
|
|
||||||
} = require("@budibase/backend-core/utils")
|
} = require("@budibase/backend-core/utils")
|
||||||
const { EmailTemplatePurpose } = require("../../../constants")
|
const { EmailTemplatePurpose } = require("../../../constants")
|
||||||
const { checkInviteCode } = require("../../../utilities/redis")
|
const { checkInviteCode } = require("../../../utilities/redis")
|
||||||
|
@ -24,7 +22,7 @@ const {
|
||||||
const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
|
const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
|
||||||
const env = require("../../../environment")
|
const env = require("../../../environment")
|
||||||
const { syncUserInApps } = require("../../../utilities/appService")
|
const { syncUserInApps } = require("../../../utilities/appService")
|
||||||
const { allUsers } = require("../../utilities")
|
const { allUsers, getUser } = require("../../utilities")
|
||||||
|
|
||||||
exports.save = async ctx => {
|
exports.save = async ctx => {
|
||||||
try {
|
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
|
// called internally by app server user fetch
|
||||||
exports.fetch = async ctx => {
|
exports.fetch = async ctx => {
|
||||||
const users = await allUsers(ctx)
|
const users = await allUsers(ctx)
|
||||||
|
@ -189,18 +141,7 @@ exports.fetch = async ctx => {
|
||||||
|
|
||||||
// called internally by app server user find
|
// called internally by app server user find
|
||||||
exports.find = async ctx => {
|
exports.find = async ctx => {
|
||||||
const db = getGlobalDB()
|
ctx.body = await getUser(ctx.params.id)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.tenantUserLookup = async ctx => {
|
exports.tenantUserLookup = async ctx => {
|
||||||
|
|
|
@ -67,6 +67,10 @@ const NO_TENANCY_ENDPOINTS = [
|
||||||
route: "/api/global/users/self",
|
route: "/api/global/users/self",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
route: "/api/global/self",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// most public endpoints are gets, but some are posts
|
// most public endpoints are gets, but some are posts
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
const Router = require("@koa/router")
|
const Router = require("@koa/router")
|
||||||
const controller = require("../../controllers/global/self")
|
const controller = require("../../controllers/global/self")
|
||||||
const builderOnly = require("../../../middleware/builderOnly")
|
const builderOnly = require("../../../middleware/builderOnly")
|
||||||
|
const { buildUserSaveValidation } = require("../../utilities/validation")
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
router
|
router
|
||||||
.post("/api/global/self/api_key", builderOnly, controller.generateAPIKey)
|
.post("/api/global/self/api_key", builderOnly, controller.generateAPIKey)
|
||||||
.get("/api/global/self/api_key", builderOnly, controller.fetchAPIKey)
|
.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
|
module.exports = router
|
||||||
|
|
|
@ -4,6 +4,8 @@ const joiValidator = require("../../../middleware/joi-validator")
|
||||||
const adminOnly = require("../../../middleware/adminOnly")
|
const adminOnly = require("../../../middleware/adminOnly")
|
||||||
const Joi = require("joi")
|
const Joi = require("joi")
|
||||||
const cloudRestricted = require("../../../middleware/cloudRestricted")
|
const cloudRestricted = require("../../../middleware/cloudRestricted")
|
||||||
|
const { buildUserSaveValidation } = require("../../utilities/validation")
|
||||||
|
const selfController = require("../../controllers/global/self")
|
||||||
|
|
||||||
const router = Router()
|
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() {
|
function buildInviteValidation() {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return joiValidator.body(Joi.object({
|
return joiValidator.body(Joi.object({
|
||||||
|
@ -78,11 +54,6 @@ router
|
||||||
controller.invite
|
controller.invite
|
||||||
)
|
)
|
||||||
// non-global endpoints
|
// non-global endpoints
|
||||||
.post(
|
|
||||||
"/api/global/users/self",
|
|
||||||
buildUserSaveValidation(true),
|
|
||||||
controller.updateSelf
|
|
||||||
)
|
|
||||||
.post(
|
.post(
|
||||||
"/api/global/users/invite/accept",
|
"/api/global/users/invite/accept",
|
||||||
buildInviteAcceptValidation(),
|
buildInviteAcceptValidation(),
|
||||||
|
@ -94,10 +65,15 @@ router
|
||||||
buildAdminInitValidation(),
|
buildAdminInitValidation(),
|
||||||
controller.adminUser
|
controller.adminUser
|
||||||
)
|
)
|
||||||
|
|
||||||
.get("/api/global/users/self", controller.getSelf)
|
|
||||||
.get("/api/global/users/tenant/:id", controller.tenantUserLookup)
|
.get("/api/global/users/tenant/:id", controller.tenantUserLookup)
|
||||||
// global endpoint but needs to come at end (blocks other endpoints otherwise)
|
// global endpoint but needs to come at end (blocks other endpoints otherwise)
|
||||||
.get("/api/global/users/:id", adminOnly, controller.find)
|
.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
|
module.exports = router
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
||||||
const { getGlobalUserParams } = require("@budibase/backend-core/db")
|
const { getGlobalUserParams } = require("@budibase/backend-core/db")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all users from the current tenancy.
|
||||||
|
*/
|
||||||
exports.allUsers = async () => {
|
exports.allUsers = async () => {
|
||||||
const db = getGlobalDB()
|
const db = getGlobalDB()
|
||||||
const response = await db.allDocs(
|
const response = await db.allDocs(
|
||||||
|
@ -10,3 +13,21 @@ exports.allUsers = async () => {
|
||||||
)
|
)
|
||||||
return response.rows.map(row => row.doc)
|
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