diff --git a/packages/twenty-server/src/core/auth/auth.resolver.ts b/packages/twenty-server/src/core/auth/auth.resolver.ts index 55bad8033a8..da957addcfd 100644 --- a/packages/twenty-server/src/core/auth/auth.resolver.ts +++ b/packages/twenty-server/src/core/auth/auth.resolver.ts @@ -95,6 +95,14 @@ export class AuthResolver { return { loginToken }; } + @Mutation(() => Workspace) + @UseGuards(JwtAuthGuard) + async createWorkspaceSchema(@AuthUser() user: User): Promise { + await this.authService.createWorkspaceSchema(user); + + return user.defaultWorkspace; + } + @Mutation(() => TransientToken) @UseGuards(JwtAuthGuard) async generateTransientToken( diff --git a/packages/twenty-server/src/core/auth/services/auth.service.ts b/packages/twenty-server/src/core/auth/services/auth.service.ts index 660cd44e0b7..fee0dcbb04f 100644 --- a/packages/twenty-server/src/core/auth/services/auth.service.ts +++ b/packages/twenty-server/src/core/auth/services/auth.service.ts @@ -7,11 +7,11 @@ import { import { InjectRepository } from '@nestjs/typeorm'; import { HttpService } from '@nestjs/axios'; -import FileType from 'file-type'; import { Repository } from 'typeorm'; import { v4 } from 'uuid'; import { render } from '@react-email/components'; import { PasswordUpdateNotifyEmail } from 'twenty-emails'; +import FileType from 'file-type'; import { FileFolder } from 'src/core/file/interfaces/file-folder.interface'; @@ -29,11 +29,11 @@ import { User } from 'src/core/user/user.entity'; import { Workspace } from 'src/core/workspace/workspace.entity'; import { UserService } from 'src/core/user/services/user.service'; import { WorkspaceManagerService } from 'src/workspace/workspace-manager/workspace-manager.service'; -import { getImageBufferFromUrl } from 'src/utils/image'; import { FileUploadService } from 'src/core/file/services/file-upload.service'; import { EnvironmentService } from 'src/integrations/environment/environment.service'; import { EmailService } from 'src/integrations/email/email.service'; import { UpdatePassword } from 'src/core/auth/dto/update-password.entity'; +import { getImageBufferFromUrl } from 'src/utils/image'; import { TokenService } from './token.service'; @@ -135,18 +135,8 @@ export class AuthService { }); workspace = await this.workspaceRepository.save(workspaceToCreate); - await this.workspaceManagerService.init(workspace.id); } - const userToCreate = this.userRepository.create({ - email: email, - firstName: firstName, - lastName: lastName, - canImpersonate: false, - passwordHash, - defaultWorkspace: workspace, - }); - const user = await this.userRepository.save(userToCreate); let imagePath: string | undefined = undefined; if (picture) { @@ -166,9 +156,23 @@ export class AuthService { imagePath = paths[0]; } - await this.userService.createWorkspaceMember(user, imagePath); - return user; + const userToCreate = this.userRepository.create({ + email: email, + firstName: firstName, + lastName: lastName, + defaultAvatarUrl: imagePath, + canImpersonate: false, + passwordHash, + defaultWorkspace: workspace, + }); + + return await this.userRepository.save(userToCreate); + } + + async createWorkspaceSchema(user: User) { + await this.workspaceManagerService.init(user.defaultWorkspace.id); + await this.userService.createWorkspaceMember(user); } async verify(email: string): Promise { @@ -189,7 +193,6 @@ export class AuthService { // passwordHash is hidden for security reasons user.passwordHash = ''; - user.workspaceMember = await this.userService.loadWorkspaceMember(user); const accessToken = await this.tokenService.generateAccessToken(user.id); const refreshToken = await this.tokenService.generateRefreshToken(user.id); diff --git a/packages/twenty-server/src/core/user/services/user.service.ts b/packages/twenty-server/src/core/user/services/user.service.ts index 39b816d5b8b..fe12fa0df44 100644 --- a/packages/twenty-server/src/core/user/services/user.service.ts +++ b/packages/twenty-server/src/core/user/services/user.service.ts @@ -63,7 +63,7 @@ export class UserService extends TypeOrmQueryService { ); } - async createWorkspaceMember(user: User, avatarUrl?: string) { + async createWorkspaceMember(user: User) { const dataSourceMetadata = await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( user.defaultWorkspace.id, @@ -77,7 +77,7 @@ export class UserService extends TypeOrmQueryService { ("nameFirstName", "nameLastName", "colorScheme", "userId", "avatarUrl") VALUES ('${user.firstName}', '${user.lastName}', 'Light', '${ user.id - }', '${avatarUrl ?? ''}')`, + }', '${user.defaultAvatarUrl ?? ''}')`, ); } diff --git a/packages/twenty-server/src/core/user/user.entity.ts b/packages/twenty-server/src/core/user/user.entity.ts index bc6980bcd5e..5de3c04522d 100644 --- a/packages/twenty-server/src/core/user/user.entity.ts +++ b/packages/twenty-server/src/core/user/user.entity.ts @@ -34,6 +34,10 @@ export class User { @Column() email: string; + @Field({ nullable: true }) + @Column({ nullable: true }) + defaultAvatarUrl: string; + @Field() @Column({ default: false }) emailVerified: boolean; diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/1706613419989-addDefaultAvatarUrlToUser.ts b/packages/twenty-server/src/database/typeorm/core/migrations/1706613419989-addDefaultAvatarUrlToUser.ts new file mode 100644 index 00000000000..6846716377d --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/1706613419989-addDefaultAvatarUrlToUser.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddDefaultAvatarUrlToUser1706613419989 implements MigrationInterface { + name = 'AddDefaultAvatarUrlToUser1706613419989' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "core"."user" ADD "defaultAvatarUrl" character varying`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "core"."user" DROP COLUMN "defaultAvatarUrl"`); + } + +}