diff --git a/packages/cli/src/requests.ts b/packages/cli/src/requests.ts index ffc04925a3..4765ac1fad 100644 --- a/packages/cli/src/requests.ts +++ b/packages/cli/src/requests.ts @@ -244,7 +244,13 @@ export declare namespace UserRequest { >; export type InviteResponse = { - user: { id: string; email: string; inviteAcceptUrl?: string; emailSent: boolean }; + user: { + id: string; + email: string; + inviteAcceptUrl?: string; + emailSent: boolean; + role: AssignableRole; + }; error?: string; }; diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index 1668878a8c..ba02375aba 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -130,6 +130,7 @@ export class UserService { email, inviteAcceptUrl, emailSent: false, + role, }, error: '', }; diff --git a/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts b/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts index 48663e1ef3..f1e8e2a1b9 100644 --- a/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts +++ b/packages/cli/test/integration/controllers/invitation/invitation.controller.integration.test.ts @@ -246,6 +246,7 @@ describe('InvitationController', () => { const { user } = response.body.data[0]; expect(user.inviteAcceptUrl).toBeDefined(); + expect(user).toHaveProperty('role', 'global:member'); const inviteUrl = new URL(user.inviteAcceptUrl); diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index 97ca0cf4eb..add7905fcf 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -1189,6 +1189,7 @@ export interface IInviteResponse { email: string; emailSent: boolean; inviteAcceptUrl: string; + role: IRole; }; error?: string; } diff --git a/packages/editor-ui/src/stores/users.store.test.ts b/packages/editor-ui/src/stores/users.store.test.ts index 8e9969e8eb..3a9ca7dbf0 100644 --- a/packages/editor-ui/src/stores/users.store.test.ts +++ b/packages/editor-ui/src/stores/users.store.test.ts @@ -2,10 +2,11 @@ import type { CurrentUserResponse } from '@/Interface'; import { useUsersStore } from './users.store'; import { createPinia, setActivePinia } from 'pinia'; -const { loginCurrentUser, identify } = vi.hoisted(() => { +const { loginCurrentUser, identify, inviteUsers } = vi.hoisted(() => { return { loginCurrentUser: vi.fn(), identify: vi.fn(), + inviteUsers: vi.fn(), }; }); @@ -13,6 +14,10 @@ vi.mock('@/api/users', () => ({ loginCurrentUser, })); +vi.mock('@/api/invitation', () => ({ + inviteUsers, +})); + vi.mock('@/composables/useTelemetry', () => ({ useTelemetry: vi.fn(() => ({ identify, @@ -58,4 +63,31 @@ describe('users.store', () => { expect(identify).toHaveBeenCalledWith('test-instance-id', mockUser.id); }); }); + + describe('inviteUsers', () => { + it('should add pending user to the store', async () => { + const usersStore = useUsersStore(); + + inviteUsers.mockResolvedValueOnce([ + { + user: { id: 'random-id', email: 'test@n8n.io', emailSent: true, role: 'global:member' }, + }, + ]); + + await usersStore.inviteUsers([{ email: 'test@n8n.io', role: 'global:member' }]); + + expect(usersStore.allUsers[0]).toMatchObject( + expect.objectContaining({ + id: 'random-id', + email: 'test@n8n.io', + role: 'global:member', + isPending: true, + isDefaultUser: false, + isPendingUser: true, + fullName: undefined, + emailSent: true, + }), + ); + }); + }); }); diff --git a/packages/editor-ui/src/stores/users.store.ts b/packages/editor-ui/src/stores/users.store.ts index 2091048fd6..4f17aa3f76 100644 --- a/packages/editor-ui/src/stores/users.store.ts +++ b/packages/editor-ui/src/stores/users.store.ts @@ -278,9 +278,8 @@ export const useUsersStore = defineStore(STORES.USERS, () => { const inviteUsers = async (params: Array<{ email: string; role: InvitableRoleName }>) => { const invitedUsers = await invitationsApi.inviteUsers(rootStore.restApiContext, params); addUsers( - invitedUsers.map(({ user }, index) => ({ + invitedUsers.map(({ user }) => ({ isPending: true, - globalRole: { name: params[index].role }, ...user, })), );