mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-10 07:07:21 +00:00
Add support for sending edit user email with template
This commit is contained in:
@ -58,6 +58,8 @@ MAILTRAP_API_TOKEN=
|
|||||||
|
|
||||||
MAILTRAP_INVITATION_TEMPLATE_UUID=
|
MAILTRAP_INVITATION_TEMPLATE_UUID=
|
||||||
|
|
||||||
|
MAILTRAP_EDIT_USER_TEMPLATE_UUID=
|
||||||
|
|
||||||
MAILTRAP_DISABLE_TEMPLATE_UUID=
|
MAILTRAP_DISABLE_TEMPLATE_UUID=
|
||||||
|
|
||||||
MAILTRAP_ENABLE_TEMPLATE_UUID=
|
MAILTRAP_ENABLE_TEMPLATE_UUID=
|
||||||
|
@ -17,5 +17,7 @@ export default registerAs(
|
|||||||
MAILTRAP_ENABLE_TEMPLATE_UUID: process.env.MAILTRAP_ENABLE_TEMPLATE_UUID,
|
MAILTRAP_ENABLE_TEMPLATE_UUID: process.env.MAILTRAP_ENABLE_TEMPLATE_UUID,
|
||||||
MAILTRAP_DELETE_USER_TEMPLATE_UUID:
|
MAILTRAP_DELETE_USER_TEMPLATE_UUID:
|
||||||
process.env.MAILTRAP_DELETE_USER_TEMPLATE_UUID,
|
process.env.MAILTRAP_DELETE_USER_TEMPLATE_UUID,
|
||||||
|
MAILTRAP_EDIT_USER_TEMPLATE_UUID:
|
||||||
|
process.env.MAILTRAP_EDIT_USER_TEMPLATE_UUID,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -138,4 +138,82 @@ export class EmailService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async sendEditUserEmailWithTemplate(
|
||||||
|
email: string,
|
||||||
|
emailEditData: any,
|
||||||
|
): Promise<void> {
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
const API_TOKEN = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_API_TOKEN',
|
||||||
|
);
|
||||||
|
const API_URL = isProduction
|
||||||
|
? SEND_EMAIL_API_URL_PROD
|
||||||
|
: SEND_EMAIL_API_URL_DEV;
|
||||||
|
const TEMPLATE_UUID = this.configService.get<string>(
|
||||||
|
'email-config.MAILTRAP_EDIT_USER_TEMPLATE_UUID',
|
||||||
|
);
|
||||||
|
|
||||||
|
const emailData = {
|
||||||
|
from: {
|
||||||
|
email: this.smtpConfig.sender,
|
||||||
|
},
|
||||||
|
to: [
|
||||||
|
{
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
template_uuid: TEMPLATE_UUID,
|
||||||
|
template_variables: emailEditData,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await axios.post(API_URL, emailData, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${API_TOKEN}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new HttpException(
|
||||||
|
error.response?.data?.message ||
|
||||||
|
'Error sending email using Mailtrap template',
|
||||||
|
error.response?.status || HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
generateUserChangesEmailBody(
|
||||||
|
addedSpaceNames: string[],
|
||||||
|
removedSpaceNames: string[],
|
||||||
|
oldRole: string,
|
||||||
|
newRole: string,
|
||||||
|
oldName: string,
|
||||||
|
newName: string,
|
||||||
|
) {
|
||||||
|
const addedSpaceNamesChanged =
|
||||||
|
addedSpaceNames.length > 0
|
||||||
|
? `Access to the following spaces were added: ${addedSpaceNames.join(', ')}`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const removedSpaceNamesChanged =
|
||||||
|
removedSpaceNames.length > 0
|
||||||
|
? `Access to the following spaces were deleted: ${removedSpaceNames.join(', ')}`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const roleChanged =
|
||||||
|
oldRole !== newRole
|
||||||
|
? `Your user role has been changed from [${oldRole}] to [${newRole}]`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const nameChanged =
|
||||||
|
oldName !== newName
|
||||||
|
? `The name associated with your account has changed from [${oldName}] to [${newName}]`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
addedSpaceNamesChanged,
|
||||||
|
removedSpaceNamesChanged,
|
||||||
|
roleChanged,
|
||||||
|
nameChanged,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import { UserDevicePermissionService } from 'src/user-device-permission/services
|
|||||||
import { DeviceUserPermissionRepository } from '@app/common/modules/device/repositories';
|
import { DeviceUserPermissionRepository } from '@app/common/modules/device/repositories';
|
||||||
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
import { PermissionTypeRepository } from '@app/common/modules/permission/repositories';
|
||||||
import { ProjectUserService } from 'src/project/services/project-user.service';
|
import { ProjectUserService } from 'src/project/services/project-user.service';
|
||||||
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule, InviteUserRepositoryModule],
|
imports: [ConfigModule, InviteUserRepositoryModule],
|
||||||
@ -49,6 +50,7 @@ import { ProjectUserService } from 'src/project/services/project-user.service';
|
|||||||
DeviceUserPermissionRepository,
|
DeviceUserPermissionRepository,
|
||||||
PermissionTypeRepository,
|
PermissionTypeRepository,
|
||||||
ProjectUserService,
|
ProjectUserService,
|
||||||
|
RoleTypeRepository,
|
||||||
],
|
],
|
||||||
exports: [InviteUserService],
|
exports: [InviteUserService],
|
||||||
})
|
})
|
||||||
|
@ -28,6 +28,7 @@ import {
|
|||||||
DisableUserInvitationDto,
|
DisableUserInvitationDto,
|
||||||
UpdateUserInvitationDto,
|
UpdateUserInvitationDto,
|
||||||
} from '../dtos/update.invite-user.dto';
|
} from '../dtos/update.invite-user.dto';
|
||||||
|
import { RoleTypeRepository } from '@app/common/modules/role-type/repositories';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InviteUserService {
|
export class InviteUserService {
|
||||||
@ -39,6 +40,7 @@ export class InviteUserService {
|
|||||||
private readonly userSpaceService: UserSpaceService,
|
private readonly userSpaceService: UserSpaceService,
|
||||||
private readonly spaceUserService: SpaceUserService,
|
private readonly spaceUserService: SpaceUserService,
|
||||||
private readonly spaceRepository: SpaceRepository,
|
private readonly spaceRepository: SpaceRepository,
|
||||||
|
private readonly roleTypeRepository: RoleTypeRepository,
|
||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -272,7 +274,7 @@ export class InviteUserService {
|
|||||||
dto: UpdateUserInvitationDto,
|
dto: UpdateUserInvitationDto,
|
||||||
invitedUserUuid: string,
|
invitedUserUuid: string,
|
||||||
): Promise<BaseResponseDto> {
|
): Promise<BaseResponseDto> {
|
||||||
const { projectUuid } = dto;
|
const { projectUuid, spaceUuids } = dto;
|
||||||
|
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
await queryRunner.startTransaction();
|
await queryRunner.startTransaction();
|
||||||
@ -281,6 +283,7 @@ export class InviteUserService {
|
|||||||
// Fetch the user's existing data in the project
|
// Fetch the user's existing data in the project
|
||||||
const userOldData = await this.inviteUserRepository.findOne({
|
const userOldData = await this.inviteUserRepository.findOne({
|
||||||
where: { uuid: invitedUserUuid, project: { uuid: projectUuid } },
|
where: { uuid: invitedUserUuid, project: { uuid: projectUuid } },
|
||||||
|
relations: ['project', 'spaces.space', 'roleType'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!userOldData) {
|
if (!userOldData) {
|
||||||
@ -294,7 +297,60 @@ export class InviteUserService {
|
|||||||
await this.updateWhenUserIsInvite(queryRunner, dto, invitedUserUuid);
|
await this.updateWhenUserIsInvite(queryRunner, dto, invitedUserUuid);
|
||||||
await this.updateWhenUserIsActive(queryRunner, dto, invitedUserUuid);
|
await this.updateWhenUserIsActive(queryRunner, dto, invitedUserUuid);
|
||||||
}
|
}
|
||||||
|
// Extract existing space UUIDs
|
||||||
|
const oldSpaceUuids = userOldData.spaces.map((space) => space.space.uuid);
|
||||||
|
|
||||||
|
// Compare spaces
|
||||||
|
const addedSpaces = spaceUuids.filter(
|
||||||
|
(uuid) => !oldSpaceUuids.includes(uuid),
|
||||||
|
);
|
||||||
|
const removedSpaces = oldSpaceUuids.filter(
|
||||||
|
(uuid) => !spaceUuids.includes(uuid),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fetch the space names for added and removed spaces
|
||||||
|
const spaceRepo = queryRunner.manager.getRepository(SpaceEntity);
|
||||||
|
const addedSpacesDetails = await spaceRepo.find({
|
||||||
|
where: {
|
||||||
|
uuid: In(addedSpaces),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const removedSpacesDetails = await spaceRepo.find({
|
||||||
|
where: {
|
||||||
|
uuid: In(removedSpaces),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract the names of the added and removed spaces
|
||||||
|
const addedSpaceNames = addedSpacesDetails.map(
|
||||||
|
(space) => space.spaceName,
|
||||||
|
);
|
||||||
|
const removedSpaceNames = removedSpacesDetails.map(
|
||||||
|
(space) => space.spaceName,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check for role and name change
|
||||||
|
const oldRole = userOldData.roleType.type;
|
||||||
|
const newRole = await this.getRoleTypeByUuid(dto.roleUuid);
|
||||||
|
const oldFullName = `${userOldData.firstName} ${userOldData.lastName}`;
|
||||||
|
const newFullName = `${dto.firstName} ${dto.lastName}`;
|
||||||
|
|
||||||
|
// Generate email body
|
||||||
|
const emailMessage = this.emailService.generateUserChangesEmailBody(
|
||||||
|
addedSpaceNames,
|
||||||
|
removedSpaceNames,
|
||||||
|
oldRole,
|
||||||
|
newRole,
|
||||||
|
oldFullName,
|
||||||
|
newFullName,
|
||||||
|
);
|
||||||
|
await this.emailService.sendEditUserEmailWithTemplate(
|
||||||
|
userOldData.email,
|
||||||
|
emailMessage,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Proceed with other updates (e.g., roles, names, etc.)
|
||||||
await queryRunner.commitTransaction();
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
return new SuccessResponseDto({
|
return new SuccessResponseDto({
|
||||||
@ -316,6 +372,13 @@ export class InviteUserService {
|
|||||||
await queryRunner.release();
|
await queryRunner.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private async getRoleTypeByUuid(roleUuid: string) {
|
||||||
|
const role = await this.roleTypeRepository.findOne({
|
||||||
|
where: { uuid: roleUuid },
|
||||||
|
});
|
||||||
|
|
||||||
|
return role.type;
|
||||||
|
}
|
||||||
|
|
||||||
private async updateWhenUserIsInvite(
|
private async updateWhenUserIsInvite(
|
||||||
queryRunner: QueryRunner,
|
queryRunner: QueryRunner,
|
||||||
|
Reference in New Issue
Block a user