diff --git a/package.json b/package.json index c12755c1386d..5191a6dbbded 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "bcrypt": "^5.1.1", "better-sqlite3": "^9.2.2", "body-parser": "^1.20.2", - "bullmq": "^4.14.0", + "bullmq": "^4.15.0", "bytes": "^3.1.2", "class-transformer": "^0.5.1", "clsx": "^2.1.1", diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts index 415c2be34281..26cf789de9b9 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts @@ -1,18 +1,17 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useEffect } from 'react'; import { useForm } from 'react-hook-form'; +import { useLocation, useSearchParams } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { z } from 'zod'; -import { useLocation } from 'react-router-dom'; -import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex'; -import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState'; -import { useSearchParams } from 'react-router-dom'; -import { isDefined } from '~/utils/isDefined'; import { SignInUpStep, signInUpStepState, } from '@/auth/states/signInUpStepState'; +import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex'; +import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState'; +import { isDefined } from '~/utils/isDefined'; const makeValidationSchema = (signInUpStep: SignInUpStep) => z @@ -63,6 +62,11 @@ export const useSignInUpForm = () => { form.setValue('email', 'tim@apple.dev'); form.setValue('password', 'Applecar2025'); } - }, [form, isDeveloperDefaultSignInPrefilled, prefilledEmail, location.search]); - return { form: form }; + }, [ + form, + isDeveloperDefaultSignInPrefilled, + prefilledEmail, + location.search, + ]); + return { form, validationSchema }; }; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts index 3aa1c306a184..90a6ac1cccdc 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts @@ -143,6 +143,10 @@ export const queries = { allowImpersonation activationStatus isPublicInviteLinkEnabled + isGoogleAuthEnabled + isMicrosoftAuthEnabled + isPasswordAuthEnabled + subdomain hasValidEntrepriseKey featureFlags { id @@ -164,6 +168,7 @@ export const queries = { logo displayName domainName + subdomain } } userVars @@ -286,6 +291,10 @@ export const responseData = { activationStatus: 'active', isPublicInviteLinkEnabled: false, hasValidEntrepriseKey: false, + isGoogleAuthEnabled: true, + isMicrosoftAuthEnabled: false, + isPasswordAuthEnabled: true, + subdomain: 'test', featureFlags: [], metadataVersion: 1, currentBillingSubscription: null, diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts index 368c5343c6aa..cc8c2af81e4b 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/sign-in-up.service.spec.ts @@ -2,22 +2,23 @@ import { HttpService } from '@nestjs/axios'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import bcrypt from 'bcrypt'; import { expect, jest } from '@jest/globals'; +import bcrypt from 'bcrypt'; +import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.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 { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; import { Workspace, WorkspaceActivationStatus, } from 'src/engine/core-modules/workspace/workspace.entity'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; -import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service'; -import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; jest.mock('bcrypt'); @@ -75,9 +76,7 @@ describe('SignInUpService', () => { }, { provide: WorkspaceService, - useValue: { - generateSubdomain: jest.fn().mockReturnValue('tartanpion'), - }, + useValue: {}, }, { provide: UserWorkspaceService, @@ -114,6 +113,12 @@ describe('SignInUpService', () => { workspaceInvitationFindInvitationByWorkspaceSubdomainAndUserEmailMock, }, }, + { + provide: DomainManagerService, + useValue: { + generateSubdomain: jest.fn().mockReturnValue('testSubDomain'), + }, + }, ], }).compile(); @@ -139,7 +144,7 @@ describe('SignInUpService', () => { await service.signInUp({ email: 'test@test.com', fromSSO: true, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect(spy).toHaveBeenCalledWith( @@ -169,7 +174,7 @@ describe('SignInUpService', () => { const result = await service.signInUp({ email, fromSSO: true, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect(result).toEqual(existingUser); @@ -204,7 +209,7 @@ describe('SignInUpService', () => { await service.signInUp({ email, fromSSO: true, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect(spySignInUpOnExistingWorkspace).toHaveBeenCalledWith( @@ -257,7 +262,7 @@ describe('SignInUpService', () => { const result = await service.signInUp({ email, fromSSO: true, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect(result).toEqual(existingUser); @@ -297,7 +302,7 @@ describe('SignInUpService', () => { email, fromSSO: true, workspacePersonalInviteToken, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect(spySignInUpOnExistingWorkspace).toHaveBeenCalledWith( @@ -348,7 +353,7 @@ describe('SignInUpService', () => { email, fromSSO: true, workspacePersonalInviteToken, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect( @@ -375,7 +380,7 @@ describe('SignInUpService', () => { email, password, fromSSO: false, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect( @@ -400,7 +405,7 @@ describe('SignInUpService', () => { email, password, fromSSO: false, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect(UserCreateMock).toHaveBeenCalledTimes(1); @@ -436,7 +441,7 @@ describe('SignInUpService', () => { password, fromSSO: false, workspacePersonalInviteToken, - targetWorkspaceSubdomain: 'tartanpion', + targetWorkspaceSubdomain: 'testSubDomain', }); expect(UserCreateMock).toHaveBeenCalledTimes(1); diff --git a/packages/twenty-server/src/engine/core-modules/domain-manager/service/domain-manager.service.ts b/packages/twenty-server/src/engine/core-modules/domain-manager/service/domain-manager.service.ts index bc59918278aa..626fb75f2fb0 100644 --- a/packages/twenty-server/src/engine/core-modules/domain-manager/service/domain-manager.service.ts +++ b/packages/twenty-server/src/engine/core-modules/domain-manager/service/domain-manager.service.ts @@ -4,17 +4,16 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; -import { isDefined } from 'src/utils/is-defined'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceException, WorkspaceExceptionCode, } from 'src/engine/core-modules/workspace/workspace.exception'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { isWorkEmail } from 'src/utils/is-work-email'; import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email'; +import { isDefined } from 'src/utils/is-defined'; +import { isWorkEmail } from 'src/utils/is-work-email'; @Injectable() -// eslint-disable-next-line @nx/workspace-inject-workspace-repository export class DomainManagerService { constructor( @InjectRepository(Workspace, 'core') @@ -126,6 +125,7 @@ export class DomainManagerService { order: { createdAt: 'DESC', }, + relations: ['workspaceSSOIdentityProviders'], }); if (workspaces.length > 1) { @@ -153,7 +153,12 @@ export class DomainManagerService { if (!isDefined(subdomain)) return; - return this.workspaceRepository.findOneBy({ subdomain }); + const workspace = await this.workspaceRepository.findOne({ + where: { subdomain }, + relations: ['workspaceSSOIdentityProviders'], + }); + + return workspace; } catch (e) { throw new WorkspaceException( 'Workspace not found', diff --git a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts index f4c74a88c789..49b9e36a2fc4 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace-invitation/services/workspace-invitation.service.ts @@ -17,19 +17,19 @@ import { AuthException, AuthExceptionCode, } from 'src/engine/core-modules/auth/auth.exception'; +import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service'; import { EmailService } from 'src/engine/core-modules/email/email.service'; import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; import { SendInvitationsOutput } from 'src/engine/core-modules/workspace-invitation/dtos/send-invitations.output'; +import { castAppTokenToWorkspaceInvitationUtil } from 'src/engine/core-modules/workspace-invitation/utils/cast-app-token-to-workspace-invitation.util'; import { WorkspaceInvitationException, WorkspaceInvitationExceptionCode, } from 'src/engine/core-modules/workspace-invitation/workspace-invitation.exception'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service'; -import { castAppTokenToWorkspaceInvitationUtil } from 'src/engine/core-modules/workspace-invitation/utils/cast-app-token-to-workspace-invitation.util'; @Injectable() // eslint-disable-next-line @nx/workspace-inject-workspace-repository @@ -338,7 +338,7 @@ export class WorkspaceInvitationService { ? { inviteToken: invitation.value.appToken.value, email: invitation.value.email, - } + } : {}, }); const emailData = { diff --git a/yarn.lock b/yarn.lock index 94ebc7496965..4473fd9b5e84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21176,9 +21176,9 @@ __metadata: languageName: node linkType: hard -"bullmq@npm:^4.14.0": - version: 4.17.0 - resolution: "bullmq@npm:4.17.0" +"bullmq@npm:^4.15.0": + version: 4.18.2 + resolution: "bullmq@npm:4.18.2" dependencies: cron-parser: "npm:^4.6.0" glob: "npm:^8.0.3" @@ -21189,7 +21189,7 @@ __metadata: semver: "npm:^7.5.4" tslib: "npm:^2.0.0" uuid: "npm:^9.0.0" - checksum: 10c0/7dde2fcc2a6432aa52fb255ac470fbc6c01530d2825bad1b48549706de2d3af90b1895954db16a753f60a3e6f2755d9e9987b422597dbf74762932e98bc8fbd2 + checksum: 10c0/09371a6d53377e556a37e3e046576bb20056a14ac26d29528bd0a4054c33f458f1764ae696ae6a39fda688e8215ef34f1ba94fe56ba89db5b9ad2c9aa0082f2f languageName: node linkType: hard @@ -44483,7 +44483,7 @@ __metadata: bcrypt: "npm:^5.1.1" better-sqlite3: "npm:^9.2.2" body-parser: "npm:^1.20.2" - bullmq: "npm:^4.14.0" + bullmq: "npm:^4.15.0" bytes: "npm:^3.1.2" chromatic: "npm:^6.18.0" class-transformer: "npm:^0.5.1"