fix(signin): allow to signin in pending creation workspace (#10052)
This commit is contained in:
@ -21,6 +21,11 @@ import { UserService } from 'src/engine/core-modules/user/services/user.service'
|
|||||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||||
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
|
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||||
|
import {
|
||||||
|
AuthException,
|
||||||
|
AuthExceptionCode,
|
||||||
|
} from 'src/engine/core-modules/auth/auth.exception';
|
||||||
|
|
||||||
jest.mock('src/utils/image', () => {
|
jest.mock('src/utils/image', () => {
|
||||||
return {
|
return {
|
||||||
@ -75,6 +80,7 @@ describe('SignInUpService', () => {
|
|||||||
provide: UserWorkspaceService,
|
provide: UserWorkspaceService,
|
||||||
useValue: {
|
useValue: {
|
||||||
addUserToWorkspace: jest.fn(),
|
addUserToWorkspace: jest.fn(),
|
||||||
|
checkUserWorkspaceExists: jest.fn(),
|
||||||
create: jest.fn(),
|
create: jest.fn(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -248,4 +254,65 @@ describe('SignInUpService', () => {
|
|||||||
expect(UserRepository.save).toHaveBeenCalled();
|
expect(UserRepository.save).toHaveBeenCalled();
|
||||||
expect(fileUploadService.uploadImage).toHaveBeenCalled();
|
expect(fileUploadService.uploadImage).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle signIn on workspace in pending state', async () => {
|
||||||
|
const params: SignInUpBaseParams &
|
||||||
|
ExistingUserOrPartialUserWithPicture &
|
||||||
|
AuthProviderWithPasswordType = {
|
||||||
|
workspace: {
|
||||||
|
id: 'workspaceId',
|
||||||
|
activationStatus: WorkspaceActivationStatus.PENDING_CREATION,
|
||||||
|
} as Workspace,
|
||||||
|
authParams: { provider: 'password', password: 'validPassword' },
|
||||||
|
userData: {
|
||||||
|
type: 'existingUser',
|
||||||
|
existingUser: { email: 'test@example.com' } as User,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.spyOn(environmentService, 'get').mockReturnValue(false);
|
||||||
|
jest
|
||||||
|
.spyOn(userWorkspaceService, 'addUserToWorkspace')
|
||||||
|
.mockResolvedValue({} as User);
|
||||||
|
jest
|
||||||
|
.spyOn(userWorkspaceService, 'checkUserWorkspaceExists')
|
||||||
|
.mockResolvedValue({} as UserWorkspace);
|
||||||
|
|
||||||
|
const result = await service.signInUp(params);
|
||||||
|
|
||||||
|
expect(result.workspace).toEqual(params.workspace);
|
||||||
|
expect(result.user).toBeDefined();
|
||||||
|
expect(userWorkspaceService.addUserToWorkspace).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw - handle signUp on workspace in pending state', async () => {
|
||||||
|
const params: SignInUpBaseParams &
|
||||||
|
ExistingUserOrPartialUserWithPicture &
|
||||||
|
AuthProviderWithPasswordType = {
|
||||||
|
workspace: {
|
||||||
|
id: 'workspaceId',
|
||||||
|
activationStatus: WorkspaceActivationStatus.PENDING_CREATION,
|
||||||
|
} as Workspace,
|
||||||
|
authParams: { provider: 'password', password: 'validPassword' },
|
||||||
|
userData: {
|
||||||
|
type: 'existingUser',
|
||||||
|
existingUser: { email: 'test@example.com' } as User,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.spyOn(environmentService, 'get').mockReturnValue(false);
|
||||||
|
jest
|
||||||
|
.spyOn(userWorkspaceService, 'addUserToWorkspace')
|
||||||
|
.mockResolvedValue({} as User);
|
||||||
|
jest
|
||||||
|
.spyOn(userWorkspaceService, 'checkUserWorkspaceExists')
|
||||||
|
.mockResolvedValue(null);
|
||||||
|
|
||||||
|
await expect(() => service.signInUp(params)).rejects.toThrow(
|
||||||
|
new AuthException(
|
||||||
|
'Workspace is not ready to welcome new members',
|
||||||
|
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -38,7 +38,6 @@ import { UserService } from 'src/engine/core-modules/user/services/user.service'
|
|||||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||||
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
|
||||||
import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email';
|
import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email';
|
||||||
import { getImageBufferFromUrl } from 'src/utils/image';
|
import { getImageBufferFromUrl } from 'src/utils/image';
|
||||||
import { isWorkEmail } from 'src/utils/is-work-email';
|
import { isWorkEmail } from 'src/utils/is-work-email';
|
||||||
@ -214,18 +213,39 @@ export class SignInUpService {
|
|||||||
return await this.userRepository.save(userToCreate);
|
return await this.userRepository.save(userToCreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async throwIfWorkspaceIsNotReadyForSignInUp(
|
||||||
|
workspace: Workspace,
|
||||||
|
user: ExistingUserOrPartialUserWithPicture,
|
||||||
|
) {
|
||||||
|
if (workspace.activationStatus === WorkspaceActivationStatus.ACTIVE) return;
|
||||||
|
|
||||||
|
if (user.userData.type !== 'existingUser') {
|
||||||
|
throw new AuthException(
|
||||||
|
'Workspace is not ready to welcome new members',
|
||||||
|
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userWorkspaceExists =
|
||||||
|
await this.userWorkspaceService.checkUserWorkspaceExists(
|
||||||
|
user.userData.existingUser.id,
|
||||||
|
workspace.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!userWorkspaceExists) {
|
||||||
|
throw new AuthException(
|
||||||
|
'User is not part of the workspace',
|
||||||
|
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async signInUpOnExistingWorkspace(
|
async signInUpOnExistingWorkspace(
|
||||||
params: {
|
params: {
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
} & ExistingUserOrPartialUserWithPicture,
|
} & ExistingUserOrPartialUserWithPicture,
|
||||||
) {
|
) {
|
||||||
workspaceValidator.assertIsActive(
|
await this.throwIfWorkspaceIsNotReadyForSignInUp(params.workspace, params);
|
||||||
params.workspace,
|
|
||||||
new AuthException(
|
|
||||||
'Workspace is not ready to welcome new members',
|
|
||||||
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
const currentUser =
|
const currentUser =
|
||||||
params.userData.type === 'newUserWithPicture'
|
params.userData.type === 'newUserWithPicture'
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import { WorkspaceActivationStatus } from 'twenty-shared';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AuthException,
|
AuthException,
|
||||||
AuthExceptionCode,
|
AuthExceptionCode,
|
||||||
@ -24,16 +22,6 @@ const assertIsDefinedOrThrow = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const assertIsActive = (
|
|
||||||
workspace: Workspace,
|
|
||||||
exceptionToThrow: CustomException,
|
|
||||||
): asserts workspace is Workspace & {
|
|
||||||
activationStatus: WorkspaceActivationStatus.ACTIVE;
|
|
||||||
} => {
|
|
||||||
if (workspace.activationStatus === WorkspaceActivationStatus.ACTIVE) return;
|
|
||||||
throw exceptionToThrow;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isAuthEnabledOrThrow = (
|
const isAuthEnabledOrThrow = (
|
||||||
provider: WorkspaceAuthProvider,
|
provider: WorkspaceAuthProvider,
|
||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
@ -52,10 +40,8 @@ const isAuthEnabledOrThrow = (
|
|||||||
|
|
||||||
export const workspaceValidator: {
|
export const workspaceValidator: {
|
||||||
assertIsDefinedOrThrow: typeof assertIsDefinedOrThrow;
|
assertIsDefinedOrThrow: typeof assertIsDefinedOrThrow;
|
||||||
assertIsActive: typeof assertIsActive;
|
|
||||||
isAuthEnabledOrThrow: typeof isAuthEnabledOrThrow;
|
isAuthEnabledOrThrow: typeof isAuthEnabledOrThrow;
|
||||||
} = {
|
} = {
|
||||||
assertIsDefinedOrThrow: assertIsDefinedOrThrow,
|
assertIsDefinedOrThrow: assertIsDefinedOrThrow,
|
||||||
assertIsActive: assertIsActive,
|
|
||||||
isAuthEnabledOrThrow: isAuthEnabledOrThrow,
|
isAuthEnabledOrThrow: isAuthEnabledOrThrow,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user