diff --git a/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte b/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte index 79da462da5..99da91a603 100644 --- a/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte +++ b/packages/builder/src/pages/builder/portal/manage/users/_components/AddUserModal.svelte @@ -8,12 +8,10 @@ Layout, } from "@budibase/bbui" import { groups, auth } from "stores/portal" - import { createEventDispatcher } from "svelte" import { Constants } from "@budibase/frontend-core" export let showOnboardingTypeModal const password = Math.random().toString(36).substring(2, 22) - const dispatch = createEventDispatcher() let disabled let userGroups = [] @@ -41,10 +39,8 @@ { - showOnboardingTypeModal() - dispatch("change", { users: userData, groups: userGroups }) - }} + onConfirm={async () => + showOnboardingTypeModal({ users: userData, groups: userGroups })} size="M" title="Add new user" confirmText="Add user" diff --git a/packages/builder/src/pages/builder/portal/manage/users/index.svelte b/packages/builder/src/pages/builder/portal/manage/users/index.svelte index fb4943cf6f..5a047e9b03 100644 --- a/packages/builder/src/pages/builder/portal/manage/users/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/users/index.svelte @@ -112,12 +112,15 @@ } }) } - function showOnboardingTypeModal() { + const showOnboardingTypeModal = async addUsersData => { + userData = await removingDuplicities(addUsersData) + if (!userData?.users?.length) return + onboardingTypeModal.show() } async function createUserFlow() { - let emails = userData.map(x => x.email) + let emails = userData?.users?.map(x => x.email) || [] try { const res = await users.invite({ emails: emails, @@ -132,8 +135,29 @@ } } + const removingDuplicities = async userData => { + const currentUserEmails = (await users.fetch())?.map(x => x.email) || [] + const newUsers = [] + + for (const user of userData?.users) { + const { email } = user + + if ( + newUsers.find(x => x.email === email) || + currentUserEmails.includes(email) + ) + continue + + newUsers.push(user) + } + + if (!newUsers.length) + notifications.info("Duplicated! There is no new users to add.") + return { ...userData, users: newUsers } + } + const createUsersFromCsv = async userCsvData => { - const { userEmails, usersRole, userGroups } = userCsvData + const { userEmails, usersRole, userGroups: groups } = userCsvData const users = [] for (const email of userEmails) { @@ -147,13 +171,15 @@ users.push(newUser) } - userData = { groups: userGroups, users: users } + userData = await removingDuplicities({ groups, users }) + if (!userData.users.length) return + return createUser() } async function createUser() { try { - await users.create(userData) + await users.create(await removingDuplicities(userData)) notifications.success("Successfully created user") await groups.actions.init() passwordModal.show() @@ -272,14 +298,7 @@ - (userData = e.detail)} - on:created={async () => { - pageInfo.reset() - await fetchUsers() - }} - {showOnboardingTypeModal} - /> + diff --git a/packages/builder/src/stores/portal/users.js b/packages/builder/src/stores/portal/users.js index 4e0643676a..6ed77932bf 100644 --- a/packages/builder/src/stores/portal/users.js +++ b/packages/builder/src/stores/portal/users.js @@ -23,6 +23,10 @@ export function createUsersStore() { } } + const fetch = async () => { + return await API.getUsers() + } + async function invite({ emails, builder, admin }) { return API.inviteUsers({ emails, @@ -87,6 +91,7 @@ export function createUsersStore() { subscribe, search, get, + fetch, invite, acceptInvite, create, diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts index 13f2a14efe..7c288139d7 100644 --- a/packages/worker/src/api/controllers/global/users.ts +++ b/packages/worker/src/api/controllers/global/users.ts @@ -23,10 +23,23 @@ export const save = async (ctx: any) => { } export const bulkSave = async (ctx: any) => { - let { users: newUsers, groups } = ctx.request.body + let { users: newUsersRequested, groups } = ctx.request.body let usersToSave: any[] = [] let groupsToSave: any[] = [] + const newUsers: any[] = [] const db = tenancy.getGlobalDB() + const currentUserEmails = + (await users.allUsers())?.map((x: any) => x.email) || [] + + for (const newUser of newUsersRequested) { + if ( + newUsers.find((x: any) => x.email === newUser.email) || + currentUserEmails.includes(newUser.email) + ) + continue + + newUsers.push(newUser) + } newUsers.forEach((user: any) => { usersToSave.push(