diff --git a/packages/backend-core/src/db/views.ts b/packages/backend-core/src/db/views.ts index 5d9c5b74d3..6ee06d12ef 100644 --- a/packages/backend-core/src/db/views.ts +++ b/packages/backend-core/src/db/views.ts @@ -199,9 +199,8 @@ export const createPlatformUserView = async () => { export const queryPlatformView = async ( viewName: ViewName, - params: DatabaseQueryOpts, - opts?: QueryViewOptions -): Promise => { + params: DatabaseQueryOpts +): Promise => { const CreateFuncByName: any = { [ViewName.ACCOUNT_BY_EMAIL]: createPlatformAccountEmailView, [ViewName.PLATFORM_USERS_LOWERCASE]: createPlatformUserView, @@ -209,7 +208,9 @@ export const queryPlatformView = async ( return doWithDB(StaticDatabases.PLATFORM_INFO.name, async (db: Database) => { const createFn = CreateFuncByName[viewName] - return queryView(viewName, params, db, createFn, opts) + return queryView(viewName, params, db, createFn, { + arrayResponse: true, + }) as Promise }) } diff --git a/packages/backend-core/src/platform/users.ts b/packages/backend-core/src/platform/users.ts index 93e9df8c0e..9378e23724 100644 --- a/packages/backend-core/src/platform/users.ts +++ b/packages/backend-core/src/platform/users.ts @@ -25,6 +25,11 @@ export async function getUserDoc(emailOrId: string): Promise { return db.get(emailOrId) } +export async function updateUserDoc(platformUser: PlatformUserById) { + const db = getPlatformDB() + await db.put(platformUser) +} + // CREATE function newUserIdDoc(id: string, tenantId: string): PlatformUserById { diff --git a/packages/backend-core/src/users/db.ts b/packages/backend-core/src/users/db.ts index 4865ebb5bc..c96c615f4b 100644 --- a/packages/backend-core/src/users/db.ts +++ b/packages/backend-core/src/users/db.ts @@ -18,6 +18,9 @@ import { User, UserStatus, UserGroup, + PlatformUserBySsoId, + PlatformUserById, + AnyDocument, } from "@budibase/types" import { getAccountHolderFromUserIds, @@ -25,7 +28,11 @@ import { isCreator, validateUniqueUser, } from "./utils" -import { searchExistingEmails } from "./lookup" +import { + getFirstPlatformUser, + getPlatformUsers, + searchExistingEmails, +} from "./lookup" import { hash } from "../utils" import { validatePassword } from "../security" @@ -446,9 +453,32 @@ export class UserDB { creator => !!creator ).length + const ssoUsersToDelete: AnyDocument[] = [] for (let user of usersToDelete) { + const platformUser = (await getFirstPlatformUser( + user._id! + )) as PlatformUserById + const ssoId = platformUser.ssoId + if (ssoId) { + // Need to get the _rev of the SSO user doc to delete it. The view also returns docs that have the ssoId property, so we need to ignore those. + const ssoUsers = (await getPlatformUsers( + ssoId + )) as PlatformUserBySsoId[] + ssoUsers + .filter(user => user.ssoId == null) + .forEach(user => { + ssoUsersToDelete.push({ + ...user, + _deleted: true, + }) + }) + } await bulkDeleteProcessing(user) } + + // Delete any associated SSO user docs + await platform.getPlatformDB().bulkDocs(ssoUsersToDelete) + await UserDB.quotas.removeUsers(toDelete.length, creatorsToDeleteCount) // Build Response diff --git a/packages/backend-core/src/users/lookup.ts b/packages/backend-core/src/users/lookup.ts index 355be74dab..5324ba950f 100644 --- a/packages/backend-core/src/users/lookup.ts +++ b/packages/backend-core/src/users/lookup.ts @@ -34,15 +34,22 @@ export async function searchExistingEmails(emails: string[]) { } // lookup, could be email or userId, either will return a doc -export async function getPlatformUser( +export async function getPlatformUsers( identifier: string -): Promise { +): Promise { // use the view here and allow to find anyone regardless of casing // Use lowercase to ensure email login is case insensitive - return (await dbUtils.queryPlatformView(ViewName.PLATFORM_USERS_LOWERCASE, { + return await dbUtils.queryPlatformView(ViewName.PLATFORM_USERS_LOWERCASE, { keys: [identifier.toLowerCase()], include_docs: true, - })) as PlatformUser + }) +} + +export async function getFirstPlatformUser( + identifier: string +): Promise { + const platformUserDocs = await getPlatformUsers(identifier) + return platformUserDocs[0] ?? null } export async function getExistingTenantUsers( @@ -74,15 +81,10 @@ export async function getExistingPlatformUsers( keys: lcEmails, include_docs: true, } - - const opts = { - arrayResponse: true, - } - return (await dbUtils.queryPlatformView( + return await dbUtils.queryPlatformView( ViewName.PLATFORM_USERS_LOWERCASE, - params, - opts - )) as PlatformUserByEmail[] + params + ) } export async function getExistingAccounts( @@ -93,14 +95,5 @@ export async function getExistingAccounts( keys: lcEmails, include_docs: true, } - - const opts = { - arrayResponse: true, - } - - return (await dbUtils.queryPlatformView( - ViewName.ACCOUNT_BY_EMAIL, - params, - opts - )) as AccountMetadata[] + return await dbUtils.queryPlatformView(ViewName.ACCOUNT_BY_EMAIL, params) } diff --git a/packages/backend-core/src/users/utils.ts b/packages/backend-core/src/users/utils.ts index 348ad1532f..e1e3da181d 100644 --- a/packages/backend-core/src/users/utils.ts +++ b/packages/backend-core/src/users/utils.ts @@ -1,7 +1,7 @@ import { CloudAccount, ContextUser, User, UserGroup } from "@budibase/types" import * as accountSdk from "../accounts" import env from "../environment" -import { getPlatformUser } from "./lookup" +import { getFirstPlatformUser } from "./lookup" import { EmailUnavailableError } from "../errors" import { getTenantId } from "../context" import { sdk } from "@budibase/shared-core" @@ -51,7 +51,7 @@ async function isCreatorByGroupMembership(user?: User | ContextUser) { export async function validateUniqueUser(email: string, tenantId: string) { // check budibase users in other tenants if (env.MULTI_TENANCY) { - const tenantUser = await getPlatformUser(email) + const tenantUser = await getFirstPlatformUser(email) if (tenantUser != null && tenantUser.tenantId !== tenantId) { throw new EmailUnavailableError(email) } diff --git a/packages/bbui/src/InlineAlert/InlineAlert.svelte b/packages/bbui/src/InlineAlert/InlineAlert.svelte index bfc56818cb..3b98936f62 100644 --- a/packages/bbui/src/InlineAlert/InlineAlert.svelte +++ b/packages/bbui/src/InlineAlert/InlineAlert.svelte @@ -36,9 +36,11 @@
{header}
- {#each split as splitMsg} -
{splitMsg}
- {/each} + + {#each split as splitMsg} +
{splitMsg}
+ {/each} +
{#if onConfirm}