diff --git a/backend/src/entities/company-info/use-cases/verify-invite-user-in-company.use.case.ts b/backend/src/entities/company-info/use-cases/verify-invite-user-in-company.use.case.ts index 18155968d..dd512b992 100644 --- a/backend/src/entities/company-info/use-cases/verify-invite-user-in-company.use.case.ts +++ b/backend/src/entities/company-info/use-cases/verify-invite-user-in-company.use.case.ts @@ -69,7 +69,7 @@ export class VerifyInviteUserInCompanyAndConnectionGroupUseCase newUser.company = foundInvitation.company; const savedUser = await this._dbContext.userRepository.saveUserEntity(newUser); if (groupId) { - const foundGroup = await this._dbContext.groupRepository.findGroupById(groupId); + const foundGroup = await this._dbContext.groupRepository.findGroupByIdWithConnectionAndUsers(groupId); if (!foundGroup) { throw new HttpException( { diff --git a/backend/src/entities/group/repository/group-custom-repository-extension.ts b/backend/src/entities/group/repository/group-custom-repository-extension.ts index 1816c1603..798069af3 100644 --- a/backend/src/entities/group/repository/group-custom-repository-extension.ts +++ b/backend/src/entities/group/repository/group-custom-repository-extension.ts @@ -46,7 +46,7 @@ export const groupCustomRepositoryExtension: IGroupRepository = { return await qb.getMany(); }, - async findGroupById(groupId: string): Promise { + async findGroupByIdWithConnectionAndUsers(groupId: string): Promise { const qb = this.createQueryBuilder('group') .leftJoinAndSelect('group.connection', 'connection') .leftJoinAndSelect('group.users', 'user') diff --git a/backend/src/entities/group/repository/group.repository.interface.ts b/backend/src/entities/group/repository/group.repository.interface.ts index 109085f7d..bf27a94c3 100644 --- a/backend/src/entities/group/repository/group.repository.interface.ts +++ b/backend/src/entities/group/repository/group.repository.interface.ts @@ -15,7 +15,7 @@ export interface IGroupRepository { findAllUserGroupsInConnection(connectionId: string, cognitoUserName: string): Promise>; - findGroupById(groupId: string): Promise; + findGroupByIdWithConnectionAndUsers(groupId: string): Promise; findAllUserGroups(userId: string): Promise>; diff --git a/backend/src/entities/group/use-cases/delete-group.use.case.ts b/backend/src/entities/group/use-cases/delete-group.use.case.ts index afe868d8e..a9894aa6b 100644 --- a/backend/src/entities/group/use-cases/delete-group.use.case.ts +++ b/backend/src/entities/group/use-cases/delete-group.use.case.ts @@ -16,7 +16,7 @@ export class DeleteGroupUseCase extends AbstractUseCase { - const groupToDelete = await this._dbContext.groupRepository.findGroupById(groupId); + const groupToDelete = await this._dbContext.groupRepository.findGroupByIdWithConnectionAndUsers(groupId); if (groupToDelete.isMain) { throw new HttpException( { diff --git a/backend/src/entities/group/use-cases/remove-user-from-group.use.case.ts b/backend/src/entities/group/use-cases/remove-user-from-group.use.case.ts index d517412ab..4c82d58c0 100644 --- a/backend/src/entities/group/use-cases/remove-user-from-group.use.case.ts +++ b/backend/src/entities/group/use-cases/remove-user-from-group.use.case.ts @@ -31,7 +31,7 @@ export class RemoveUserFromGroupUseCase HttpStatus.BAD_REQUEST, ); } - const groupToUpdate = await this._dbContext.groupRepository.findGroupById(groupId); + const groupToUpdate = await this._dbContext.groupRepository.findGroupByIdWithConnectionAndUsers(groupId); if (groupToUpdate.isMain && groupToUpdate.users.length <= 1) { throw new HttpException( { diff --git a/backend/src/entities/group/use-cases/saas-add-user-in-group-v2.use.case.ts b/backend/src/entities/group/use-cases/saas-add-user-in-group-v2.use.case.ts index 2748fe03e..0a8df6d50 100644 --- a/backend/src/entities/group/use-cases/saas-add-user-in-group-v2.use.case.ts +++ b/backend/src/entities/group/use-cases/saas-add-user-in-group-v2.use.case.ts @@ -7,11 +7,11 @@ import { AddedUserInGroupDs } from '../application/data-sctructures/added-user-i import { IAddUserInGroup } from './use-cases.interfaces.js'; import { Messages } from '../../../exceptions/text/messages.js'; import { SaasCompanyGatewayService } from '../../../microservices/gateways/saas-gateway.ts/saas-company-gateway.service.js'; -import { ConnectionEntity } from '../../connection/connection.entity.js'; -import { UserEntity } from '../../user/user.entity.js'; import { sendEmailConfirmation, sendInvitationToGroup } from '../../email/send-email.js'; import { UserInvitationEntity } from '../../user/user-invitation/user-invitation.entity.js'; import { buildFoundGroupResponseDto } from '../utils/biuld-found-group-response.dto.js'; +import { slackPostMessage } from '../../../helpers/index.js'; +import { isSaaS } from '../../../helpers/app/is-saas.js'; export class AddUserInGroupUseCase extends AbstractUseCase @@ -27,7 +27,8 @@ export class AddUserInGroupUseCase protected async implementation(inputData: AddUserInGroupWithSaaSDs): Promise { const { email, groupId, inviterId } = inputData; - const foundGroup = await this._dbContext.groupRepository.findGroupById(groupId); + const foundGroup = await this._dbContext.groupRepository.findGroupByIdWithConnectionAndUsers(groupId); + const foundConnection = await this._dbContext.connectionRepository.getConnectionByGroupIdWithCompanyAndUsersInCompany(groupId); if (!foundConnection) { @@ -39,39 +40,46 @@ export class AddUserInGroupUseCase ); } - if (!foundConnection.company) { + if (!foundConnection.company || !foundConnection.company.id) { throw new HttpException( { message: Messages.COMPANY_NOT_EXISTS_IN_CONNECTION, }, - HttpStatus.NOT_FOUND, + HttpStatus.INTERNAL_SERVER_ERROR, ); } - const foundUser = - await this._dbContext.userRepository.findUserByEmailEndCompanyIdWithEmailVerificationAndInvitation( - email, - foundConnection.company.id, - ); + const companyWithUsers = await this._dbContext.companyInfoRepository.findCompanyInfoWithUsersById( + foundConnection.company.id, + ); - if (!foundUser) { + if (!companyWithUsers) { throw new HttpException( { - message: Messages.USER_NOT_INVITED_IN_COMPANY(email), + message: Messages.COMPANY_NOT_EXISTS_IN_CONNECTION, }, - HttpStatus.BAD_REQUEST, + HttpStatus.INTERNAL_SERVER_ERROR, ); } - const isUserInCompany = this.isUserAlreadyInCompany(foundConnection, foundUser); - const canInviteMoreUsers = await this.saasCompanyGatewayService.canInviteMoreUsers(foundConnection.company.id); - if (!canInviteMoreUsers && !isUserInCompany) { + + const foundUser = companyWithUsers.users.find((u) => u.email === email); + if (!foundUser) { throw new HttpException( { - message: Messages.MAXIMUM_FREE_INVITATION_REACHED, + message: Messages.USER_NOT_INVITED_IN_COMPANY(email), }, - HttpStatus.PAYMENT_REQUIRED, + HttpStatus.BAD_REQUEST, ); } + //todo remove in future + if (isSaaS()) { + const saasFoundCompany = await this.saasCompanyGatewayService.getCompanyInfo(foundConnection.company.id); + const saasFoundUserInCompany = saasFoundCompany?.users.find((u) => u.email === email); + + if (foundUser && !saasFoundUserInCompany) { + await slackPostMessage('probable desynchronization of users (adding a user to a group)'); + } + } if (foundUser && foundUser.isActive) { const userAlreadyAdded = !!foundGroup.users.find((u) => u.id === foundUser.id); @@ -86,7 +94,6 @@ export class AddUserInGroupUseCase foundGroup.users.push(foundUser); const savedGroup = await this._dbContext.groupRepository.saveNewOrUpdatedGroup(foundGroup); - delete savedGroup.connection; return { group: buildFoundGroupResponseDto(savedGroup), message: Messages.USER_ADDED_IN_GROUP(foundUser.email), @@ -110,7 +117,7 @@ export class AddUserInGroupUseCase foundGroup.users.push(foundUser); } const savedGroup = await this._dbContext.groupRepository.saveNewOrUpdatedGroup(foundGroup); - delete savedGroup.connection; + const newEmailVerification = await this._dbContext.emailVerificationRepository.createOrUpdateEmailVerification(foundUser); const confiramtionMailResult = await sendEmailConfirmation( @@ -151,17 +158,4 @@ export class AddUserInGroupUseCase }; } } - - private isUserAlreadyInCompany(connectionWithCompanyAndUsers: ConnectionEntity, foundUser: UserEntity): boolean { - if ( - !connectionWithCompanyAndUsers.company || - !connectionWithCompanyAndUsers.company.users || - !connectionWithCompanyAndUsers.company.users.length || - !foundUser - ) { - return false; - } - const foundUserInCompany = connectionWithCompanyAndUsers.company.users.find((u) => u.id === foundUser.id); - return !!foundUserInCompany; - } } diff --git a/backend/src/entities/group/use-cases/update-group-title.use.case.ts b/backend/src/entities/group/use-cases/update-group-title.use.case.ts index 4c55e1c64..0d09b22bd 100644 --- a/backend/src/entities/group/use-cases/update-group-title.use.case.ts +++ b/backend/src/entities/group/use-cases/update-group-title.use.case.ts @@ -21,7 +21,7 @@ export class UpdateGroupTitleUseCase protected async implementation(groupData: UpdateGroupTitleDto): Promise { const { groupId, title } = groupData; - const groupToUpdate = await this._dbContext.groupRepository.findGroupById(groupId); + const groupToUpdate = await this._dbContext.groupRepository.findGroupByIdWithConnectionAndUsers(groupId); if (!groupToUpdate) { throw new HttpException( { diff --git a/backend/src/entities/group/use-cases/verify-add-user-in-group.use.case.ts b/backend/src/entities/group/use-cases/verify-add-user-in-group.use.case.ts index 0061d0db1..b70ffaed3 100644 --- a/backend/src/entities/group/use-cases/verify-add-user-in-group.use.case.ts +++ b/backend/src/entities/group/use-cases/verify-add-user-in-group.use.case.ts @@ -6,7 +6,6 @@ import { Messages } from '../../../exceptions/text/messages.js'; import { Constants } from '../../../helpers/constants/constants.js'; import { Encryptor } from '../../../helpers/encryption/encryptor.js'; import { ValidationHelper } from '../../../helpers/validators/validation-helper.js'; -import { UserHelperService } from '../../user/user-helper.service.js'; import { generateGwtToken, IToken } from '../../user/utils/generate-gwt-token.js'; import { VerifyAddUserInGroupDs } from '../application/data-sctructures/verify-add-user-in-group.ds.js'; import { IVerifyAddUserInGroup } from './use-cases.interfaces.js'; @@ -20,7 +19,6 @@ export class VerifyAddUserInGroupUseCase constructor( @Inject(BaseType.GLOBAL_DB_CONTEXT) protected _dbContext: IGlobalDatabaseContext, - private readonly userHelperService: UserHelperService, ) { super(); } diff --git a/backend/src/entities/user/repository/user-custom-repository-extension.ts b/backend/src/entities/user/repository/user-custom-repository-extension.ts index 04bd8f867..17260b5fc 100644 --- a/backend/src/entities/user/repository/user-custom-repository-extension.ts +++ b/backend/src/entities/user/repository/user-custom-repository-extension.ts @@ -66,16 +66,14 @@ export const userCustomRepositoryExtension: IUserRepository = { async findUserByEmailEndCompanyIdWithEmailVerificationAndInvitation( email: string, - companyId?: string, + companyId: string, ): Promise { const usersQb = this.createQueryBuilder('user') .leftJoinAndSelect('user.email_verification', 'email_verification') .leftJoinAndSelect('user.user_invitation', 'user_invitation') .leftJoinAndSelect('user.company', 'company') - .where('user.email = :userEmail', { userEmail: email }); - if (companyId) { - usersQb.andWhere('company.id = :companyId', { companyId: companyId }); - } + .where('user.email = :userEmail', { userEmail: email }) + .andWhere('company.id = :companyId', { companyId: companyId }); return await usersQb.getOne(); }, diff --git a/backend/src/entities/user/repository/user.repository.interface.ts b/backend/src/entities/user/repository/user.repository.interface.ts index d9fa06a16..90f32192c 100644 --- a/backend/src/entities/user/repository/user.repository.interface.ts +++ b/backend/src/entities/user/repository/user.repository.interface.ts @@ -28,7 +28,7 @@ export interface IUserRepository { findOneUserWithEmailVerification(userId: string): Promise; - findUserByEmailEndCompanyIdWithEmailVerificationAndInvitation(email: string, companyId?: string): Promise; + findUserByEmailEndCompanyIdWithEmailVerificationAndInvitation(email: string, companyId: string): Promise; deleteUserEntity(user: UserEntity): Promise;