From 24f8f3a7cbfe5d5aa30103f96e8491f757cac4f3 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 12 Jan 2023 15:38:22 +0000 Subject: [PATCH 01/12] Fix currentapp middleware to allow app_ parameters --- packages/server/src/middleware/currentapp.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/server/src/middleware/currentapp.ts b/packages/server/src/middleware/currentapp.ts index 2cd11aa438..593e96adcb 100644 --- a/packages/server/src/middleware/currentapp.ts +++ b/packages/server/src/middleware/currentapp.ts @@ -25,6 +25,7 @@ export default async (ctx: BBContext, next: any) => { if (!appCookie && !requestAppId) { return next() } + // check the app exists referenced in cookie if (appCookie) { const appId = appCookie.appId @@ -51,7 +52,7 @@ export default async (ctx: BBContext, next: any) => { let appId: string | undefined, roleId = roles.BUILTIN_ROLE_IDS.PUBLIC - if (!ctx.user) { + if (!ctx.user?._id) { // not logged in, try to set a cookie for public apps appId = requestAppId } else if (requestAppId != null) { @@ -96,7 +97,7 @@ export default async (ctx: BBContext, next: any) => { // need to judge this only based on the request app ID, if ( env.MULTI_TENANCY && - ctx.user && + ctx.user?._id && requestAppId && !tenancy.isUserInAppTenant(requestAppId, ctx.user) ) { From 09b4533cc8fb14f5da53e37e92cf0c57567b58b2 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 12 Jan 2023 16:26:46 +0000 Subject: [PATCH 02/12] Add endpoint to deactivate user from app on delete --- packages/server/src/api/controllers/user.ts | 32 +++++++++++++++++++++ packages/server/src/api/routes/user.ts | 5 ++++ 2 files changed, 37 insertions(+) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index df64ffc7d0..f37af55ee0 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -173,3 +173,35 @@ export async function getFlags(ctx: BBContext) { } ctx.body = doc } + +export async function removeUserFromApp(ctx: BBContext) { + 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) { + return + } + + let combined = { + ...metadata, + status: constants.UserStatus.INACTIVE, + metadata: rolesCore.BUILTIN_ROLE_IDS.PUBLIC, + } + + await db.put(combined) + }) + } + ctx.body = { + message: `User ${userId} deleted from ${prodAppId} and ${"devapp"}.`, + } +} diff --git a/packages/server/src/api/routes/user.ts b/packages/server/src/api/routes/user.ts index 14deb111e6..556954fd77 100644 --- a/packages/server/src/api/routes/user.ts +++ b/packages/server/src/api/routes/user.ts @@ -47,5 +47,10 @@ router authorized(PermissionType.USER, PermissionLevel.READ), controller.getFlags ) + .delete( + "/api/users/metadata/:id/app/:prodAppId", + authorized(PermissionType.USER, PermissionLevel.WRITE), + controller.removeUserFromApp + ) export default router From 09570e26f6e0ccf87c4f325c51ce04650aea470b Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 12 Jan 2023 16:28:02 +0000 Subject: [PATCH 03/12] Remove user within the app on deletion --- packages/worker/src/sdk/users/users.ts | 20 ++++++++++++++++++++ packages/worker/src/utilities/appService.ts | 11 +++++++++++ 2 files changed, 31 insertions(+) diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index f3117b63ab..cd3f0622d4 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -188,6 +188,10 @@ const validateUniqueUser = async (email: string, tenantId: string) => { } } +function instanceOfUser(user: User | ThirdPartyUser): user is User { + return !!(user as User).roles +} + export const save = async ( user: User | ThirdPartyUser, opts: SaveUserOpts = {} @@ -257,6 +261,17 @@ export const save = async ( } } + let appsToRemove: string[] = [] + if (dbUser && instanceOfUser(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 { // save the user to db let response = await db.put(builtUser) @@ -265,6 +280,11 @@ export const save = async ( await eventHelpers.handleSaveEvents(builtUser, dbUser) await addTenant(tenantId, _id, email) await cache.user.invalidateUser(response.id) + + for (const appId of appsToRemove) { + await apps.removeUserFromApp(_id, appId) + } + // let server know to sync user await apps.syncUserInApps(_id) diff --git a/packages/worker/src/utilities/appService.ts b/packages/worker/src/utilities/appService.ts index a0c4314f65..95a90aebc0 100644 --- a/packages/worker/src/utilities/appService.ts +++ b/packages/worker/src/utilities/appService.ts @@ -30,3 +30,14 @@ export async function syncUserInApps(userId: string) { 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." + } +} From 34cd26781bd0f59adf20f686b6b09aeac0bd25c5 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 13 Jan 2023 10:26:05 +0000 Subject: [PATCH 04/12] Delete instead of deactivating --- packages/server/src/api/controllers/user.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index f37af55ee0..5458d97f76 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -189,16 +189,11 @@ export async function removeUserFromApp(ctx: BBContext) { try { metadata = await db.get(metadataId) } catch (err) { + console.warn(`User cannot be found in the app`, { userId, appId }) return } - let combined = { - ...metadata, - status: constants.UserStatus.INACTIVE, - metadata: rolesCore.BUILTIN_ROLE_IDS.PUBLIC, - } - - await db.put(combined) + await db.remove(metadata) }) } ctx.body = { From a5c145d9f64419171dea15e95cadcbadb43b949b Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 13 Jan 2023 13:31:48 +0000 Subject: [PATCH 05/12] Replace BBContext for Ctx --- packages/server/src/api/controllers/user.ts | 4 ++-- packages/types/src/sdk/koa.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index 5458d97f76..3fdca188a5 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -8,7 +8,7 @@ import { roles as rolesCore, db as dbCore, } from "@budibase/backend-core" -import { BBContext, User } from "@budibase/types" +import { BBContext, Ctx, User } from "@budibase/types" import sdk from "../../sdk" export async function syncUser(ctx: BBContext) { @@ -174,7 +174,7 @@ export async function getFlags(ctx: BBContext) { ctx.body = doc } -export async function removeUserFromApp(ctx: BBContext) { +export async function removeUserFromApp(ctx: Ctx) { const { id: userId, prodAppId } = ctx.params const devAppId = dbCore.getDevelopmentAppID(prodAppId) diff --git a/packages/types/src/sdk/koa.ts b/packages/types/src/sdk/koa.ts index 302d1aeb67..f824b73458 100644 --- a/packages/types/src/sdk/koa.ts +++ b/packages/types/src/sdk/koa.ts @@ -41,7 +41,7 @@ export interface UserCtx } /** - * Deprecated: Use UserCtx / Ctx appropriately + * @deprecated: Use UserCtx / Ctx appropriately * Authenticated context. */ export interface BBContext extends Ctx { From 50565dc22678179c2c1607fe551a384b6946b6c0 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 13 Jan 2023 13:33:40 +0000 Subject: [PATCH 06/12] Fix copy on reponse message --- packages/server/src/api/controllers/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index 3fdca188a5..d8c5c5c679 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -197,6 +197,6 @@ export async function removeUserFromApp(ctx: Ctx) { }) } ctx.body = { - message: `User ${userId} deleted from ${prodAppId} and ${"devapp"}.`, + message: `User ${userId} deleted from ${prodAppId} and ${devAppId}.`, } } From c853d2c78e3673cd832e59bd86f0df463b44f084 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 13 Jan 2023 13:36:35 +0000 Subject: [PATCH 07/12] Rename and move type check --- packages/types/src/documents/global/user.ts | 4 ++++ packages/worker/src/sdk/users/users.ts | 7 ++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/types/src/documents/global/user.ts b/packages/types/src/documents/global/user.ts index fbf34cb196..ee83969a52 100644 --- a/packages/types/src/documents/global/user.ts +++ b/packages/types/src/documents/global/user.ts @@ -69,3 +69,7 @@ export interface AdminUser extends User { global: boolean } } + +export function isUser(user: User | ThirdPartyUser): user is User { + return !!(user as User).roles +} diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index cd3f0622d4..209ba4d41c 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -31,6 +31,7 @@ import { SearchUsersRequest, User, ThirdPartyUser, + isUser, } from "@budibase/types" import { sendEmail } from "../../utilities/email" import { EmailTemplatePurpose } from "../../constants" @@ -188,10 +189,6 @@ const validateUniqueUser = async (email: string, tenantId: string) => { } } -function instanceOfUser(user: User | ThirdPartyUser): user is User { - return !!(user as User).roles -} - export const save = async ( user: User | ThirdPartyUser, opts: SaveUserOpts = {} @@ -262,7 +259,7 @@ export const save = async ( } let appsToRemove: string[] = [] - if (dbUser && instanceOfUser(user)) { + if (dbUser && isUser(user)) { const newRoles = Object.keys(user.roles) const existingRoles = Object.keys(dbUser.roles) From ff10fa422bb8681ac38566ed2745dd4b54d0faa8 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 13 Jan 2023 14:45:04 +0000 Subject: [PATCH 08/12] Unify endpoints --- packages/server/src/api/controllers/user.ts | 61 +++++++-------------- packages/server/src/api/routes/user.ts | 5 -- packages/types/src/documents/global/user.ts | 2 +- packages/worker/src/sdk/users/users.ts | 17 +----- packages/worker/src/utilities/appService.ts | 16 +----- 5 files changed, 26 insertions(+), 75 deletions(-) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index d8c5c5c679..bdbb1c7f93 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -4,19 +4,21 @@ import { getGlobalUsers, getRawGlobalUser } from "../../utilities/global" import { getFullUser } from "../../utilities/users" import { context, - constants, roles as rolesCore, db as dbCore, } from "@budibase/backend-core" -import { BBContext, Ctx, User } from "@budibase/types" +import { BBContext, Ctx, isUser, User } from "@budibase/types" import sdk from "../../sdk" -export async function syncUser(ctx: BBContext) { +export async function syncUser(ctx: Ctx) { let deleting = false, user: User | any const userId = ctx.params.id + + const previousUser = ctx.request.body?.previousUser + try { - user = await getRawGlobalUser(userId) + user = (await getRawGlobalUser(userId)) as User } catch (err: any) { if (err && err.status === 404) { user = {} @@ -25,6 +27,11 @@ export async function syncUser(ctx: BBContext) { throw err } } + + let previousApps = isUser(previousUser) + ? Object.keys(previousUser.roles).map(appId => appId) + : [] + const roles = deleting ? {} : user.roles // remove props which aren't useful to metadata delete user.password @@ -40,8 +47,9 @@ export async function syncUser(ctx: BBContext) { .filter(entry => entry[1] !== rolesCore.BUILTIN_ROLE_IDS.PUBLIC) .map(([appId]) => appId) } - for (let prodAppId of prodAppIds) { + for (let prodAppId of new Set([...prodAppIds, ...previousApps])) { const roleId = roles[prodAppId] + const deleteFromApp = !roleId const devAppId = dbCore.getDevelopmentAppID(prodAppId) for (let appId of [prodAppId, devAppId]) { if (!(await dbCore.dbExists(appId))) { @@ -54,24 +62,24 @@ export async function syncUser(ctx: BBContext) { try { metadata = await db.get(metadataId) } catch (err) { - if (deleting) { + if (deleteFromApp) { return } metadata = { tableId: InternalTables.USER_METADATA, } } + + if (deleteFromApp) { + await db.remove(metadata) + return + } + // assign the roleId for the metadata doc if (roleId) { metadata.roleId = roleId } - let combined = !deleting - ? sdk.users.combineMetadataAndUser(user, metadata) - : { - ...metadata, - status: constants.UserStatus.INACTIVE, - metadata: rolesCore.BUILTIN_ROLE_IDS.PUBLIC, - } + let combined = sdk.users.combineMetadataAndUser(user, metadata) // if its null then there was no updates required if (combined) { await db.put(combined) @@ -173,30 +181,3 @@ export async function getFlags(ctx: BBContext) { } 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}.`, - } -} diff --git a/packages/server/src/api/routes/user.ts b/packages/server/src/api/routes/user.ts index 556954fd77..14deb111e6 100644 --- a/packages/server/src/api/routes/user.ts +++ b/packages/server/src/api/routes/user.ts @@ -47,10 +47,5 @@ router authorized(PermissionType.USER, PermissionLevel.READ), controller.getFlags ) - .delete( - "/api/users/metadata/:id/app/:prodAppId", - authorized(PermissionType.USER, PermissionLevel.WRITE), - controller.removeUserFromApp - ) export default router diff --git a/packages/types/src/documents/global/user.ts b/packages/types/src/documents/global/user.ts index ee83969a52..5787318680 100644 --- a/packages/types/src/documents/global/user.ts +++ b/packages/types/src/documents/global/user.ts @@ -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 } diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index 209ba4d41c..7132c886e6 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -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 { // save the user to db let response = await db.put(builtUser) @@ -278,12 +267,8 @@ export const save = async ( await addTenant(tenantId, _id, email) await cache.user.invalidateUser(response.id) - for (const appId of appsToRemove) { - await apps.removeUserFromApp(_id, appId) - } - // let server know to sync user - await apps.syncUserInApps(_id) + await apps.syncUserInApps(_id, dbUser) await Promise.all(groupPromises) diff --git a/packages/worker/src/utilities/appService.ts b/packages/worker/src/utilities/appService.ts index 95a90aebc0..7c725d0a85 100644 --- a/packages/worker/src/utilities/appService.ts +++ b/packages/worker/src/utilities/appService.ts @@ -2,6 +2,7 @@ import fetch from "node-fetch" import { constants, tenancy } from "@budibase/backend-core" import { checkSlashesInUrl } from "../utilities" import env from "../environment" +import { User } from "@budibase/types" async function makeAppRequest(url: string, method: string, body: any) { if (env.isTest()) { @@ -20,24 +21,13 @@ async function makeAppRequest(url: string, method: string, body: any) { 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( `/api/users/metadata/sync/${userId}`, "POST", - {} + { previousUser } ) if (response && response.status !== 200) { 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." - } -} From 748b55c732481fb601b5040dd27f33d9c9787858 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 13 Jan 2023 14:48:01 +0000 Subject: [PATCH 09/12] Fix undefineds --- packages/server/src/api/controllers/user.ts | 7 ++++--- packages/types/src/documents/global/user.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index bdbb1c7f93..8af7619634 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -28,9 +28,10 @@ export async function syncUser(ctx: Ctx) { } } - let previousApps = isUser(previousUser) - ? Object.keys(previousUser.roles).map(appId => appId) - : [] + let previousApps = + previousUser && isUser(previousUser) + ? Object.keys(previousUser.roles).map(appId => appId) + : [] const roles = deleting ? {} : user.roles // remove props which aren't useful to metadata diff --git a/packages/types/src/documents/global/user.ts b/packages/types/src/documents/global/user.ts index 5787318680..91543a6368 100644 --- a/packages/types/src/documents/global/user.ts +++ b/packages/types/src/documents/global/user.ts @@ -70,6 +70,6 @@ export interface AdminUser extends User { } } -export function isUser(user: any): user is User { +export function isUser(user: object): user is User { return !!(user as User).roles } From 23266bd456337fb97434c25f53ef02a404c23585 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Fri, 13 Jan 2023 14:54:26 +0000 Subject: [PATCH 10/12] Send old user on delete --- packages/worker/src/sdk/users/users.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index 7132c886e6..5124a5c5b1 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -574,7 +574,7 @@ export const destroy = async (id: string, currentUser: any) => { await cache.user.invalidateUser(userId) await sessions.invalidateSessions(userId, { reason: "deletion" }) // let server know to sync user - await apps.syncUserInApps(userId) + await apps.syncUserInApps(userId, dbUser) } const bulkDeleteProcessing = async (dbUser: User) => { @@ -584,7 +584,7 @@ const bulkDeleteProcessing = async (dbUser: User) => { await cache.user.invalidateUser(userId) await sessions.invalidateSessions(userId, { reason: "bulk-deletion" }) // let server know to sync user - await apps.syncUserInApps(userId) + await apps.syncUserInApps(userId, dbUser) } export const invite = async ( From 946cc35ff7121d6e7cdb07ec1c9175274c8bc671 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 16 Jan 2023 10:15:00 +0000 Subject: [PATCH 11/12] Type request and body --- packages/server/src/api/controllers/user.ts | 11 +++++------ packages/types/src/api/web/user.ts | 4 ++++ packages/worker/src/utilities/appService.ts | 8 ++++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index 8af7619634..1ae1a68824 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -7,10 +7,10 @@ import { roles as rolesCore, db as dbCore, } from "@budibase/backend-core" -import { BBContext, Ctx, isUser, User } from "@budibase/types" +import { BBContext, Ctx, SyncUserRequest, User } from "@budibase/types" import sdk from "../../sdk" -export async function syncUser(ctx: Ctx) { +export async function syncUser(ctx: Ctx) { let deleting = false, user: User | any const userId = ctx.params.id @@ -28,10 +28,9 @@ export async function syncUser(ctx: Ctx) { } } - let previousApps = - previousUser && isUser(previousUser) - ? Object.keys(previousUser.roles).map(appId => appId) - : [] + let previousApps = previousUser + ? Object.keys(previousUser.roles).map(appId => appId) + : [] const roles = deleting ? {} : user.roles // remove props which aren't useful to metadata diff --git a/packages/types/src/api/web/user.ts b/packages/types/src/api/web/user.ts index 0ebe4ccce8..6acaf6912d 100644 --- a/packages/types/src/api/web/user.ts +++ b/packages/types/src/api/web/user.ts @@ -57,3 +57,7 @@ export interface CreateAdminUserRequest { password: string tenantId: string } + +export interface SyncUserRequest { + previousUser?: User +} diff --git a/packages/worker/src/utilities/appService.ts b/packages/worker/src/utilities/appService.ts index 7c725d0a85..a2b68eb80b 100644 --- a/packages/worker/src/utilities/appService.ts +++ b/packages/worker/src/utilities/appService.ts @@ -2,7 +2,7 @@ import fetch from "node-fetch" import { constants, tenancy } from "@budibase/backend-core" import { checkSlashesInUrl } from "../utilities" import env from "../environment" -import { User } from "@budibase/types" +import { SyncUserRequest, User } from "@budibase/types" async function makeAppRequest(url: string, method: string, body: any) { if (env.isTest()) { @@ -22,10 +22,14 @@ async function makeAppRequest(url: string, method: string, body: any) { } export async function syncUserInApps(userId: string, previousUser?: User) { + const body: SyncUserRequest = { + previousUser, + } + const response = await makeAppRequest( `/api/users/metadata/sync/${userId}`, "POST", - { previousUser } + body ) if (response && response.status !== 200) { throw "Unable to sync user." From dc8e54cd84123c2d44e76f7ca291003c4e75875b Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 16 Jan 2023 10:19:05 +0000 Subject: [PATCH 12/12] Add test --- .../server/src/api/routes/tests/user.spec.js | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/routes/tests/user.spec.js b/packages/server/src/api/routes/tests/user.spec.js index 56f1923cb0..8f4f44d4c5 100644 --- a/packages/server/src/api/routes/tests/user.spec.js +++ b/packages/server/src/api/routes/tests/user.spec.js @@ -171,9 +171,28 @@ describe("/users", () => { .expect("Content-Type", /json/) expect(res.body.message).toEqual('User synced.') }) + + + it("should sync the user when a previous user is specified", async () => { + const app1 = await config.createApp('App 1') + const app2 = await config.createApp('App 2') + + let user = await config.createUser( + undefined, + undefined, + undefined, + undefined, + false, + true, + { [app1.appId]: 'ADMIN' }) + let res = await request + .post(`/api/users/metadata/sync/${user._id}`) + .set(config.defaultHeaders()) + .send({ previousUser: { ...user, roles: { ...user.roles, [app2.appId]: 'BASIC' } } }) + .expect(200) + .expect("Content-Type", /json/) + + expect(res.body.message).toEqual('User synced.') + }) }) - - - - })