mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 14:50:57 +00:00
60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
import { Injectable, Logger } from "@nestjs/common";
|
|
import { InjectRepository } from "@nestjs/typeorm";
|
|
import { Repository } from "typeorm";
|
|
|
|
import { ExternalProfile } from "../companies/entities/external-profile.entity";
|
|
import { ResetChannel } from "./dto/forgot-password.dto";
|
|
import { ForgotPasswordService } from "./forgot-password.service";
|
|
|
|
@Injectable()
|
|
export class CustomerResetService {
|
|
private readonly logger = new Logger(CustomerResetService.name);
|
|
|
|
constructor(
|
|
@InjectRepository(ExternalProfile)
|
|
private readonly externalProfileRepository: Repository<ExternalProfile>,
|
|
private readonly forgotPasswordService: ForgotPasswordService,
|
|
) {}
|
|
|
|
/**
|
|
* Send a reset code to the company's primary contact. Returns the masked
|
|
* destination, or null when there is no eligible account for that channel.
|
|
*
|
|
* Unlike the public flow this reports failure honestly — the caller is an
|
|
* authenticated staff member, so there is nothing to enumerate.
|
|
*/
|
|
async sendResetToCustomer(
|
|
companyId: string,
|
|
channel: ResetChannel,
|
|
): Promise<string | null> {
|
|
const profile = await this.externalProfileRepository.findOne({
|
|
where: { companyId, isPrimaryContact: true },
|
|
});
|
|
|
|
if (!profile) {
|
|
this.logger.warn(`Company ${companyId} has no primary contact profile`);
|
|
return null;
|
|
}
|
|
|
|
// Resolve through the same active-account gate the public flow uses, so a
|
|
// suspended customer cannot be reactivated by a staff-triggered reset.
|
|
const user = await this.forgotPasswordService.resolveActiveUserById(
|
|
profile.userId,
|
|
);
|
|
if (!user) {
|
|
this.logger.warn(
|
|
`Primary contact ${profile.userId} of company ${companyId} is not an active account`,
|
|
);
|
|
return null;
|
|
}
|
|
|
|
const target = await this.forgotPasswordService.requestReset(user, channel);
|
|
if (!target) return null;
|
|
|
|
this.logger.log(
|
|
`Staff-triggered ${channel} reset sent to user ${user.id} (company ${companyId})`,
|
|
);
|
|
return this.forgotPasswordService.maskTarget(target);
|
|
}
|
|
}
|