From 866b6fb9d2debb72673d3895f6cde8e047e347bc Mon Sep 17 00:00:00 2001 From: Artem Niehrieiev Date: Tue, 2 Sep 2025 12:47:43 +0000 Subject: [PATCH 1/3] refactor: update findFullCompanyInfoByUserId method and deprecate unused code --- ...ompany-info-custom-repository.extension.ts | 51 +++++++++---------- .../company-info-repository.interface.ts | 3 +- .../get-full-user-company-info.use.case.ts | 38 ++++++++------ 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/backend/src/entities/company-info/repository/company-info-custom-repository.extension.ts b/backend/src/entities/company-info/repository/company-info-custom-repository.extension.ts index 9c97e9d69..3cb121c91 100644 --- a/backend/src/entities/company-info/repository/company-info-custom-repository.extension.ts +++ b/backend/src/entities/company-info/repository/company-info-custom-repository.extension.ts @@ -48,23 +48,6 @@ export const companyInfoRepositoryExtension: ICompanyInfoRepository = { .getOne(); }, - // returns groups and connections where user is invited - async findFullCompanyInfoByUserId(userId: string): Promise { - return await this.createQueryBuilder('company_info') - .leftJoinAndSelect('company_info.logo', 'logo') - .leftJoinAndSelect('company_info.favicon', 'favicon') - .leftJoinAndSelect('company_info.tab_title', 'tab_title') - .leftJoinAndSelect('company_info.users', 'current_user') - .leftJoinAndSelect('company_info.users', 'users') - .leftJoinAndSelect('company_info.connections', 'connections') - .leftJoinAndSelect('company_info.invitations', 'invitations') - .leftJoinAndSelect('connections.groups', 'groups') - .leftJoinAndSelect('connections.author', 'connection_author') - .leftJoinAndSelect('groups.users', 'groups_users') - .where('current_user.id = :userId', { userId }) - .getOne(); - }, - async findFullCompanyInfoByCompanyId(companyId: string): Promise { return await this.createQueryBuilder('company_info') .leftJoinAndSelect('company_info.users', 'current_user') @@ -90,23 +73,39 @@ export const companyInfoRepositoryExtension: ICompanyInfoRepository = { .getOne(); }, - // temporary solution to handle "old" connections (case, when connection not attached to any company - // will be removed in during architecture refactoring) - async findAllCompanyWithConnectionsUsersJoining(companyId: string): Promise { + // returns groups and connections where user is invited + async findFullCompanyInfoByUserId(userId: string): Promise { return await this.createQueryBuilder('company_info') - .leftJoinAndSelect('company_info.users', 'users') .leftJoinAndSelect('company_info.logo', 'logo') .leftJoinAndSelect('company_info.favicon', 'favicon') .leftJoinAndSelect('company_info.tab_title', 'tab_title') - .leftJoinAndSelect('users.groups', 'groups') - .leftJoinAndSelect('groups.connection', 'connections') + .leftJoinAndSelect('company_info.users', 'current_user') + .leftJoinAndSelect('company_info.users', 'users') + .leftJoinAndSelect('company_info.connections', 'connections') + .leftJoinAndSelect('company_info.invitations', 'invitations') + .leftJoinAndSelect('connections.groups', 'groups') .leftJoinAndSelect('connections.author', 'connection_author') - .leftJoinAndSelect('connections.groups', 'connection_groups') - .leftJoinAndSelect('connection_groups.users', 'connection_groups_users') - .where('company_info.id = :companyId', { companyId }) + .leftJoinAndSelect('groups.users', 'groups_users') + .where('current_user.id = :userId', { userId }) .getOne(); }, + //todo deprecated code, will be removed in future + // async findAllCompanyWithConnectionsUsersJoining(companyId: string): Promise { + // return await this.createQueryBuilder('company_info') + // .leftJoinAndSelect('company_info.users', 'users') + // .leftJoinAndSelect('company_info.logo', 'logo') + // .leftJoinAndSelect('company_info.favicon', 'favicon') + // .leftJoinAndSelect('company_info.tab_title', 'tab_title') + // .leftJoinAndSelect('users.groups', 'groups') + // .leftJoinAndSelect('groups.connection', 'connections') + // .leftJoinAndSelect('connections.author', 'connection_author') + // .leftJoinAndSelect('connections.groups', 'connection_groups') + // .leftJoinAndSelect('connection_groups.users', 'connection_groups_users') + // .where('company_info.id = :companyId', { companyId }) + // .getOne(); + // }, + async findCompanyInfosByUserEmail(userEmail: string): Promise { return await this.createQueryBuilder('company_info') .leftJoinAndSelect('company_info.users', 'users') diff --git a/backend/src/entities/company-info/repository/company-info-repository.interface.ts b/backend/src/entities/company-info/repository/company-info-repository.interface.ts index 412f37f50..57d797ca3 100644 --- a/backend/src/entities/company-info/repository/company-info-repository.interface.ts +++ b/backend/src/entities/company-info/repository/company-info-repository.interface.ts @@ -20,7 +20,8 @@ export interface ICompanyInfoRepository { findUserCompanyWithUsers(userId: string): Promise; - findAllCompanyWithConnectionsUsersJoining(companyId: string): Promise; + //todo deprecated code, will be removed in future + // findAllCompanyWithConnectionsUsersJoining(companyId: string): Promise; findFullCompanyInfoByCompanyId(companyId: string): Promise; diff --git a/backend/src/entities/company-info/use-cases/get-full-user-company-info.use.case.ts b/backend/src/entities/company-info/use-cases/get-full-user-company-info.use.case.ts index cf63c89c8..7d4a14c36 100644 --- a/backend/src/entities/company-info/use-cases/get-full-user-company-info.use.case.ts +++ b/backend/src/entities/company-info/use-cases/get-full-user-company-info.use.case.ts @@ -44,26 +44,32 @@ export class GetUserCompanyFullInfoUseCase foundCompanyInfoByUserId.id, ); - let foundFullUserCoreCompanyInfo: CompanyInfoEntity; + const foundFullUserCoreCompanyInfo: CompanyInfoEntity = + await this._dbContext.companyInfoRepository.findFullCompanyInfoByUserId(userId); - if (foundUser.role === UserRoleEnum.ADMIN) { - //todo will be reworked in architecture refactoring - const companyId = foundCompanyInfoByUserId.id; + //todo deprecated code, will be removed in future + // if (foundUser.role === UserRoleEnum.ADMIN) { - const [companyInfoWithoutConnections, companyInfoWithUsers] = await Promise.all([ - this._dbContext.companyInfoRepository.findCompanyInfoByCompanyIdWithoutConnections(companyId), - this._dbContext.companyInfoRepository.findAllCompanyWithConnectionsUsersJoining(companyId), - ]); + // const companyId = foundCompanyInfoByUserId.id; - const uniqueConnections = companyInfoWithUsers.users - .flatMap((user) => user.groups.map((group) => group.connection)) - .filter((connection, index, self) => index === self.findIndex((t) => t.id === connection.id)); + // const [companyInfoWithoutConnections, companyInfoWithUsers] = await Promise.all([ + // this._dbContext.companyInfoRepository.findCompanyInfoByCompanyIdWithoutConnections(companyId), + // this._dbContext.companyInfoRepository.findAllCompanyWithConnectionsUsersJoining(companyId), + // ]); - companyInfoWithoutConnections.connections = uniqueConnections; - foundFullUserCoreCompanyInfo = companyInfoWithoutConnections; - } else { - foundFullUserCoreCompanyInfo = await this._dbContext.companyInfoRepository.findFullCompanyInfoByUserId(userId); - } + // const uniqueConnections = companyInfoWithUsers.users + // .flatMap((user) => user.groups.map((group) => group.connection)) + // .filter((connection, index, self) => index === self.findIndex((t) => t.id === connection.id)); + + // companyInfoWithoutConnections.connections = uniqueConnections; + // foundFullUserCoreCompanyInfo = companyInfoWithoutConnections; + // console.log( + // '🚀 ~ GetUserCompanyFullInfoUseCase ~ implementation ~ foundFullUserCoreCompanyInfo:', + // foundFullUserCoreCompanyInfo, + // ); + // } else { + // foundFullUserCoreCompanyInfo = await this._dbContext.companyInfoRepository.findFullCompanyInfoByUserId(userId); + // } let foundUserCompanySaasInfo = null; From f1376b4d9bca8fc028d28ad00a96d7be977fe3b5 Mon Sep 17 00:00:00 2001 From: Artem Niehrieiev Date: Wed, 3 Sep 2025 08:27:54 +0000 Subject: [PATCH 2/3] added company id check to usual register ds --- .../data-structures/usual-register-user.ds.ts | 4 ++-- .../saas-microservice/saas.controller.ts | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/backend/src/entities/user/application/data-structures/usual-register-user.ds.ts b/backend/src/entities/user/application/data-structures/usual-register-user.ds.ts index 2f8ff7cf3..eeeb7b879 100644 --- a/backend/src/entities/user/application/data-structures/usual-register-user.ds.ts +++ b/backend/src/entities/user/application/data-structures/usual-register-user.ds.ts @@ -16,8 +16,8 @@ export class UsualRegisterUserDs { } export class SaasUsualUserRegisterDS extends UsualRegisterUserDs { - @ApiProperty({ required: false }) - companyId?: string; + @ApiProperty({ required: true }) + companyId: string; @ApiProperty({ required: false, enum: UserRoleEnum }) userRole?: UserRoleEnum; diff --git a/backend/src/microservices/saas-microservice/saas.controller.ts b/backend/src/microservices/saas-microservice/saas.controller.ts index b5525c2d9..19562c373 100644 --- a/backend/src/microservices/saas-microservice/saas.controller.ts +++ b/backend/src/microservices/saas-microservice/saas.controller.ts @@ -1,4 +1,16 @@ -import { Body, Controller, Get, Inject, Injectable, Param, Post, Put, Query, UseInterceptors } from '@nestjs/common'; +import { + BadRequestException, + Body, + Controller, + Get, + Inject, + Injectable, + Param, + Post, + Put, + Query, + UseInterceptors, +} from '@nestjs/common'; import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { UseCaseType } from '../../common/data-injection.tokens.js'; import { CompanyInfoEntity } from '../../entities/company-info/company-info.entity.js'; @@ -29,6 +41,7 @@ import { ISuspendUsers, } from './use-cases/saas-use-cases.interface.js'; import { SkipThrottle } from '@nestjs/throttler'; +import { Messages } from '../../exceptions/text/messages.js'; @UseInterceptors(SentryInterceptor) @SkipThrottle() @@ -122,7 +135,9 @@ export class SaasController { @Body('companyId') companyId: string, @Body('companyName') companyName: string, ): Promise { - companyId = companyId ? companyId : null; + if (!companyId) { + throw new BadRequestException(Messages.COMPANY_ID_MISSING); + } return await this.usualRegisterUserUseCase.execute({ email, password, gclidValue, name, companyId, companyName }); } From 672237b61a98d88d970b6631fafd5b1295163b14 Mon Sep 17 00:00:00 2001 From: Artem Niehrieiev Date: Wed, 3 Sep 2025 08:44:58 +0000 Subject: [PATCH 3/3] refactor: reorder user role assignment and saving logic in register company webhook use case --- .../use-cases/register-company-webhook.use.case.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/microservices/saas-microservice/use-cases/register-company-webhook.use.case.ts b/backend/src/microservices/saas-microservice/use-cases/register-company-webhook.use.case.ts index d58d9256b..fb595463f 100644 --- a/backend/src/microservices/saas-microservice/use-cases/register-company-webhook.use.case.ts +++ b/backend/src/microservices/saas-microservice/use-cases/register-company-webhook.use.case.ts @@ -41,14 +41,14 @@ export class RegisteredCompanyWebhookUseCase HttpStatus.BAD_REQUEST, ); } - foundUser.role = UserRoleEnum.ADMIN; - await this._dbContext.userRepository.saveUserEntity(foundUser); + const newCompanyInfo = new CompanyInfoEntity(); newCompanyInfo.name = companyName ? companyName : 'New Company'; newCompanyInfo.id = companyId; newCompanyInfo.show_test_connections = true; const savedCompanyInfo = await this._dbContext.companyInfoRepository.save(newCompanyInfo); foundUser.company = savedCompanyInfo; + foundUser.role = UserRoleEnum.ADMIN; const savedUser = await this._dbContext.userRepository.saveUserEntity(foundUser); return { userId: savedUser.id,