Unify endpoints

This commit is contained in:
Adria Navarro 2023-01-13 14:45:04 +00:00
parent c853d2c78e
commit ff10fa422b
5 changed files with 26 additions and 75 deletions

View File

@ -4,19 +4,21 @@ import { getGlobalUsers, getRawGlobalUser } from "../../utilities/global"
import { getFullUser } from "../../utilities/users" import { getFullUser } from "../../utilities/users"
import { import {
context, context,
constants,
roles as rolesCore, roles as rolesCore,
db as dbCore, db as dbCore,
} from "@budibase/backend-core" } from "@budibase/backend-core"
import { BBContext, Ctx, User } from "@budibase/types" import { BBContext, Ctx, isUser, User } from "@budibase/types"
import sdk from "../../sdk" import sdk from "../../sdk"
export async function syncUser(ctx: BBContext) { export async function syncUser(ctx: Ctx) {
let deleting = false, let deleting = false,
user: User | any user: User | any
const userId = ctx.params.id const userId = ctx.params.id
const previousUser = ctx.request.body?.previousUser
try { try {
user = await getRawGlobalUser(userId) user = (await getRawGlobalUser(userId)) as User
} catch (err: any) { } catch (err: any) {
if (err && err.status === 404) { if (err && err.status === 404) {
user = {} user = {}
@ -25,6 +27,11 @@ export async function syncUser(ctx: BBContext) {
throw err throw err
} }
} }
let previousApps = isUser(previousUser)
? Object.keys(previousUser.roles).map(appId => appId)
: []
const roles = deleting ? {} : user.roles const roles = deleting ? {} : user.roles
// remove props which aren't useful to metadata // remove props which aren't useful to metadata
delete user.password delete user.password
@ -40,8 +47,9 @@ export async function syncUser(ctx: BBContext) {
.filter(entry => entry[1] !== rolesCore.BUILTIN_ROLE_IDS.PUBLIC) .filter(entry => entry[1] !== rolesCore.BUILTIN_ROLE_IDS.PUBLIC)
.map(([appId]) => appId) .map(([appId]) => appId)
} }
for (let prodAppId of prodAppIds) { for (let prodAppId of new Set([...prodAppIds, ...previousApps])) {
const roleId = roles[prodAppId] const roleId = roles[prodAppId]
const deleteFromApp = !roleId
const devAppId = dbCore.getDevelopmentAppID(prodAppId) const devAppId = dbCore.getDevelopmentAppID(prodAppId)
for (let appId of [prodAppId, devAppId]) { for (let appId of [prodAppId, devAppId]) {
if (!(await dbCore.dbExists(appId))) { if (!(await dbCore.dbExists(appId))) {
@ -54,24 +62,24 @@ export async function syncUser(ctx: BBContext) {
try { try {
metadata = await db.get(metadataId) metadata = await db.get(metadataId)
} catch (err) { } catch (err) {
if (deleting) { if (deleteFromApp) {
return return
} }
metadata = { metadata = {
tableId: InternalTables.USER_METADATA, tableId: InternalTables.USER_METADATA,
} }
} }
if (deleteFromApp) {
await db.remove(metadata)
return
}
// assign the roleId for the metadata doc // assign the roleId for the metadata doc
if (roleId) { if (roleId) {
metadata.roleId = roleId metadata.roleId = roleId
} }
let combined = !deleting let combined = sdk.users.combineMetadataAndUser(user, metadata)
? sdk.users.combineMetadataAndUser(user, metadata)
: {
...metadata,
status: constants.UserStatus.INACTIVE,
metadata: rolesCore.BUILTIN_ROLE_IDS.PUBLIC,
}
// if its null then there was no updates required // if its null then there was no updates required
if (combined) { if (combined) {
await db.put(combined) await db.put(combined)
@ -173,30 +181,3 @@ export async function getFlags(ctx: BBContext) {
} }
ctx.body = doc ctx.body = doc
} }
export async function removeUserFromApp(ctx: Ctx) {
const { id: userId, prodAppId } = ctx.params
const devAppId = dbCore.getDevelopmentAppID(prodAppId)
for (let appId of [prodAppId, devAppId]) {
if (!(await dbCore.dbExists(appId))) {
continue
}
await context.doInAppContext(appId, async () => {
const db = context.getAppDB()
const metadataId = generateUserMetadataID(userId)
let metadata
try {
metadata = await db.get(metadataId)
} catch (err) {
console.warn(`User cannot be found in the app`, { userId, appId })
return
}
await db.remove(metadata)
})
}
ctx.body = {
message: `User ${userId} deleted from ${prodAppId} and ${devAppId}.`,
}
}

View File

@ -47,10 +47,5 @@ router
authorized(PermissionType.USER, PermissionLevel.READ), authorized(PermissionType.USER, PermissionLevel.READ),
controller.getFlags controller.getFlags
) )
.delete(
"/api/users/metadata/:id/app/:prodAppId",
authorized(PermissionType.USER, PermissionLevel.WRITE),
controller.removeUserFromApp
)
export default router export default router

View File

@ -70,6 +70,6 @@ export interface AdminUser extends User {
} }
} }
export function isUser(user: User | ThirdPartyUser): user is User { export function isUser(user: any): user is User {
return !!(user as User).roles return !!(user as User).roles
} }

View File

@ -258,17 +258,6 @@ export const save = async (
} }
} }
let appsToRemove: string[] = []
if (dbUser && isUser(user)) {
const newRoles = Object.keys(user.roles)
const existingRoles = Object.keys(dbUser.roles)
appsToRemove = existingRoles.filter(r => !newRoles.includes(r))
if (appsToRemove.length) {
console.log("Deleting access to apps", { appsToRemove })
}
}
try { try {
// save the user to db // save the user to db
let response = await db.put(builtUser) let response = await db.put(builtUser)
@ -278,12 +267,8 @@ export const save = async (
await addTenant(tenantId, _id, email) await addTenant(tenantId, _id, email)
await cache.user.invalidateUser(response.id) await cache.user.invalidateUser(response.id)
for (const appId of appsToRemove) {
await apps.removeUserFromApp(_id, appId)
}
// let server know to sync user // let server know to sync user
await apps.syncUserInApps(_id) await apps.syncUserInApps(_id, dbUser)
await Promise.all(groupPromises) await Promise.all(groupPromises)

View File

@ -2,6 +2,7 @@ import fetch from "node-fetch"
import { constants, tenancy } from "@budibase/backend-core" import { constants, tenancy } from "@budibase/backend-core"
import { checkSlashesInUrl } from "../utilities" import { checkSlashesInUrl } from "../utilities"
import env from "../environment" import env from "../environment"
import { User } from "@budibase/types"
async function makeAppRequest(url: string, method: string, body: any) { async function makeAppRequest(url: string, method: string, body: any) {
if (env.isTest()) { if (env.isTest()) {
@ -20,24 +21,13 @@ async function makeAppRequest(url: string, method: string, body: any) {
return fetch(checkSlashesInUrl(env.APPS_URL + url), request) return fetch(checkSlashesInUrl(env.APPS_URL + url), request)
} }
export async function syncUserInApps(userId: string) { export async function syncUserInApps(userId: string, previousUser?: User) {
const response = await makeAppRequest( const response = await makeAppRequest(
`/api/users/metadata/sync/${userId}`, `/api/users/metadata/sync/${userId}`,
"POST", "POST",
{} { previousUser }
) )
if (response && response.status !== 200) { if (response && response.status !== 200) {
throw "Unable to sync user." throw "Unable to sync user."
} }
} }
export async function removeUserFromApp(userId: string, appId: string) {
const response = await makeAppRequest(
`/api/users/metadata/${userId}/app/${appId}`,
"DELETE",
undefined
)
if (response && response.status !== 200) {
throw "Unable to delete user from app."
}
}