mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 11:04:55 +00:00
Merge pull request #181 from SyncrowIOT/SP-933-be-implement-email-existence-validation-invite-user
Sp 933 be implement email existence validation invite user
This commit is contained in:
@ -733,6 +733,10 @@ export class ControllerRoute {
|
|||||||
|
|
||||||
public static readonly CREATE_USER_INVITATION_DESCRIPTION =
|
public static readonly CREATE_USER_INVITATION_DESCRIPTION =
|
||||||
'This endpoint creates an invitation for a user to assign to role and spaces.';
|
'This endpoint creates an invitation for a user to assign to role and spaces.';
|
||||||
|
public static readonly CHECK_EMAIL_SUMMARY = 'Check email';
|
||||||
|
|
||||||
|
public static readonly CHECK_EMAIL_DESCRIPTION =
|
||||||
|
'This endpoint checks if an email already exists and have a project in the system.';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
static PERMISSION = class {
|
static PERMISSION = class {
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { UserEntity } from '../../user/entities';
|
|||||||
import { SpaceEntity } from '../../space/entities';
|
import { SpaceEntity } from '../../space/entities';
|
||||||
import { RoleType } from '@app/common/constants/role.type.enum';
|
import { RoleType } from '@app/common/constants/role.type.enum';
|
||||||
import { InviteUserDto, InviteUserSpaceDto } from '../dtos';
|
import { InviteUserDto, InviteUserSpaceDto } from '../dtos';
|
||||||
|
import { ProjectEntity } from '../../project/entities';
|
||||||
|
|
||||||
@Entity({ name: 'invite-user' })
|
@Entity({ name: 'invite-user' })
|
||||||
@Unique(['email', 'invitationCode'])
|
@Unique(['email', 'invitationCode'])
|
||||||
@ -91,6 +92,13 @@ export class InviteUserEntity extends AbstractEntity<InviteUserDto> {
|
|||||||
(inviteUserSpace) => inviteUserSpace.inviteUser,
|
(inviteUserSpace) => inviteUserSpace.inviteUser,
|
||||||
)
|
)
|
||||||
spaces: InviteUserSpaceEntity[];
|
spaces: InviteUserSpaceEntity[];
|
||||||
|
|
||||||
|
@ManyToOne(() => ProjectEntity, (project) => project.invitedUsers, {
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
@JoinColumn({ name: 'project_uuid' })
|
||||||
|
public project: ProjectEntity;
|
||||||
|
|
||||||
constructor(partial: Partial<InviteUserEntity>) {
|
constructor(partial: Partial<InviteUserEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { ProjectDto } from '../dtos';
|
|||||||
import { CommunityEntity } from '../../community/entities';
|
import { CommunityEntity } from '../../community/entities';
|
||||||
import { SpaceModelEntity } from '../../space-model';
|
import { SpaceModelEntity } from '../../space-model';
|
||||||
import { UserEntity } from '../../user/entities';
|
import { UserEntity } from '../../user/entities';
|
||||||
|
import { InviteUserEntity } from '../../Invite-user/entities';
|
||||||
|
|
||||||
@Entity({ name: 'project' })
|
@Entity({ name: 'project' })
|
||||||
@Unique(['name'])
|
@Unique(['name'])
|
||||||
@ -32,6 +33,9 @@ export class ProjectEntity extends AbstractEntity<ProjectDto> {
|
|||||||
@OneToMany(() => UserEntity, (user) => user.project)
|
@OneToMany(() => UserEntity, (user) => user.project)
|
||||||
public users: UserEntity[];
|
public users: UserEntity[];
|
||||||
|
|
||||||
|
@OneToMany(() => InviteUserEntity, (inviteUser) => inviteUser.project)
|
||||||
|
public invitedUsers: InviteUserEntity[];
|
||||||
|
|
||||||
constructor(partial: Partial<ProjectEntity>) {
|
constructor(partial: Partial<ProjectEntity>) {
|
||||||
super();
|
super();
|
||||||
Object.assign(this, partial);
|
Object.assign(this, partial);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export class SpaceProductEntity extends AbstractEntity<SpaceProductEntity> {
|
|||||||
product: ProductEntity;
|
product: ProductEntity;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
nullable: false,
|
nullable: true,
|
||||||
type: 'int',
|
type: 'int',
|
||||||
})
|
})
|
||||||
productCount: number;
|
productCount: number;
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import { ControllerRoute } from '@app/common/constants/controller-route';
|
|||||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||||
import { PermissionsGuard } from 'src/guards/permissions.guard';
|
import { PermissionsGuard } from 'src/guards/permissions.guard';
|
||||||
import { Permissions } from 'src/decorators/permissions.decorator';
|
import { Permissions } from 'src/decorators/permissions.decorator';
|
||||||
|
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||||
|
import { CheckEmailDto } from '../dtos/check-email.dto';
|
||||||
|
|
||||||
@ApiTags('Invite User Module')
|
@ApiTags('Invite User Module')
|
||||||
@Controller({
|
@Controller({
|
||||||
@ -34,4 +36,19 @@ export class InviteUserController {
|
|||||||
user.role.type,
|
user.role.type,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
@Post('check-email')
|
||||||
|
@ApiOperation({
|
||||||
|
summary: ControllerRoute.INVITE_USER.ACTIONS.CHECK_EMAIL_SUMMARY,
|
||||||
|
description: ControllerRoute.INVITE_USER.ACTIONS.CHECK_EMAIL_DESCRIPTION,
|
||||||
|
})
|
||||||
|
async checkEmailAndProject(
|
||||||
|
@Body() addUserInvitationDto: CheckEmailDto,
|
||||||
|
): Promise<BaseResponseDto> {
|
||||||
|
return await this.inviteUserService.checkEmailAndProject(
|
||||||
|
addUserInvitationDto,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,14 @@ export class AddUserInvitationDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
public roleUuid: string;
|
public roleUuid: string;
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The project uuid of the user',
|
||||||
|
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
public projectUuid: string;
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'The array of space UUIDs (at least one required)',
|
description: 'The array of space UUIDs (at least one required)',
|
||||||
example: ['b5f3c9d2-58b7-4377-b3f7-60acb711d5d9'],
|
example: ['b5f3c9d2-58b7-4377-b3f7-60acb711d5d9'],
|
||||||
|
|||||||
16
src/invite-user/dtos/check-email.dto.ts
Normal file
16
src/invite-user/dtos/check-email.dto.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { IsEmail, IsNotEmpty } from 'class-validator';
|
||||||
|
|
||||||
|
export class CheckEmailDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: 'The email of the user',
|
||||||
|
example: 'OqM9A@example.com',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
@IsEmail()
|
||||||
|
@IsNotEmpty()
|
||||||
|
email: string;
|
||||||
|
constructor(dto: Partial<CheckEmailDto>) {
|
||||||
|
Object.assign(this, dto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,11 +12,14 @@ import {
|
|||||||
InviteUserRepository,
|
InviteUserRepository,
|
||||||
InviteUserSpaceRepository,
|
InviteUserSpaceRepository,
|
||||||
} from '@app/common/modules/Invite-user/repositiories';
|
} from '@app/common/modules/Invite-user/repositiories';
|
||||||
|
import { CheckEmailDto } from '../dtos/check-email.dto';
|
||||||
|
import { UserRepository } from '@app/common/modules/user/repositories';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InviteUserService {
|
export class InviteUserService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly inviteUserRepository: InviteUserRepository,
|
private readonly inviteUserRepository: InviteUserRepository,
|
||||||
|
private readonly userRepository: UserRepository,
|
||||||
private readonly inviteUserSpaceRepository: InviteUserSpaceRepository,
|
private readonly inviteUserSpaceRepository: InviteUserSpaceRepository,
|
||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
) {}
|
) {}
|
||||||
@ -33,6 +36,7 @@ export class InviteUserService {
|
|||||||
phoneNumber,
|
phoneNumber,
|
||||||
roleUuid,
|
roleUuid,
|
||||||
spaceUuids,
|
spaceUuids,
|
||||||
|
projectUuid,
|
||||||
} = dto;
|
} = dto;
|
||||||
|
|
||||||
const invitationCode = generateRandomString(6);
|
const invitationCode = generateRandomString(6);
|
||||||
@ -67,6 +71,7 @@ export class InviteUserService {
|
|||||||
status: UserStatusEnum.INVITED,
|
status: UserStatusEnum.INVITED,
|
||||||
invitationCode,
|
invitationCode,
|
||||||
invitedBy: roleType,
|
invitedBy: roleType,
|
||||||
|
project: { uuid: projectUuid },
|
||||||
});
|
});
|
||||||
|
|
||||||
const invitedUser = await queryRunner.manager.save(inviteUser);
|
const invitedUser = await queryRunner.manager.save(inviteUser);
|
||||||
@ -105,4 +110,46 @@ export class InviteUserService {
|
|||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async checkEmailAndProject(dto: CheckEmailDto): Promise<BaseResponseDto> {
|
||||||
|
const { email } = dto;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await this.userRepository.findOne({
|
||||||
|
where: { email },
|
||||||
|
relations: ['project'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user?.project) {
|
||||||
|
throw new HttpException(
|
||||||
|
'This email already has a project',
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const invitedUser = await this.inviteUserRepository.findOne({
|
||||||
|
where: { email },
|
||||||
|
relations: ['project'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (invitedUser?.project) {
|
||||||
|
throw new HttpException(
|
||||||
|
'This email already has a project',
|
||||||
|
HttpStatus.BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SuccessResponseDto({
|
||||||
|
statusCode: HttpStatus.OK,
|
||||||
|
success: true,
|
||||||
|
message: 'Valid email',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking email and project:', error);
|
||||||
|
throw new HttpException(
|
||||||
|
error.message ||
|
||||||
|
'An unexpected error occurred while checking the email',
|
||||||
|
error.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user