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 { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||
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', () => {
|
||||
return {
|
||||
@ -75,6 +80,7 @@ describe('SignInUpService', () => {
|
||||
provide: UserWorkspaceService,
|
||||
useValue: {
|
||||
addUserToWorkspace: jest.fn(),
|
||||
checkUserWorkspaceExists: jest.fn(),
|
||||
create: jest.fn(),
|
||||
},
|
||||
},
|
||||
@ -248,4 +254,65 @@ describe('SignInUpService', () => {
|
||||
expect(UserRepository.save).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 { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||
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 { getImageBufferFromUrl } from 'src/utils/image';
|
||||
import { isWorkEmail } from 'src/utils/is-work-email';
|
||||
@ -214,18 +213,39 @@ export class SignInUpService {
|
||||
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(
|
||||
params: {
|
||||
workspace: Workspace;
|
||||
} & ExistingUserOrPartialUserWithPicture,
|
||||
) {
|
||||
workspaceValidator.assertIsActive(
|
||||
params.workspace,
|
||||
new AuthException(
|
||||
'Workspace is not ready to welcome new members',
|
||||
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||
),
|
||||
);
|
||||
await this.throwIfWorkspaceIsNotReadyForSignInUp(params.workspace, params);
|
||||
|
||||
const currentUser =
|
||||
params.userData.type === 'newUserWithPicture'
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared';
|
||||
|
||||
import {
|
||||
AuthException,
|
||||
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 = (
|
||||
provider: WorkspaceAuthProvider,
|
||||
workspace: Workspace,
|
||||
@ -52,10 +40,8 @@ const isAuthEnabledOrThrow = (
|
||||
|
||||
export const workspaceValidator: {
|
||||
assertIsDefinedOrThrow: typeof assertIsDefinedOrThrow;
|
||||
assertIsActive: typeof assertIsActive;
|
||||
isAuthEnabledOrThrow: typeof isAuthEnabledOrThrow;
|
||||
} = {
|
||||
assertIsDefinedOrThrow: assertIsDefinedOrThrow,
|
||||
assertIsActive: assertIsActive,
|
||||
isAuthEnabledOrThrow: isAuthEnabledOrThrow,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user