Compare commits
No commits in common. "04c0b05aae4b4c06f15e60e5ada42b1c586aed03" and "135c7c22551f6f63b122b1e83a7059547c900ea9" have entirely different histories.
04c0b05aae
...
135c7c2255
@ -1,10 +0,0 @@
|
|||||||
import { Module } from '@nestjs/common';
|
|
||||||
import { MailService } from './mail.service';
|
|
||||||
import { AppConfigModule } from '../config/config.module';
|
|
||||||
|
|
||||||
@Module({
|
|
||||||
imports: [AppConfigModule],
|
|
||||||
providers: [MailService],
|
|
||||||
exports: [MailService],
|
|
||||||
})
|
|
||||||
export class MailModule {}
|
|
||||||
@ -1,100 +0,0 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
|
||||||
import { AppConfigService } from '../config/config.service';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MailService {
|
|
||||||
private readonly logger = new Logger(MailService.name);
|
|
||||||
|
|
||||||
constructor(private readonly configService: AppConfigService) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Envoi d'un email générique
|
|
||||||
* @param to Destinataire
|
|
||||||
* @param subject Sujet
|
|
||||||
* @param html Contenu HTML
|
|
||||||
* @param text Contenu texte (optionnel)
|
|
||||||
*/
|
|
||||||
async sendEmail(to: string, subject: string, html: string, text?: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
// Récupération de la configuration SMTP
|
|
||||||
const smtpHost = this.configService.get<string>('smtp_host');
|
|
||||||
const smtpPort = this.configService.get<number>('smtp_port');
|
|
||||||
const smtpSecure = this.configService.get<boolean>('smtp_secure');
|
|
||||||
const smtpAuthRequired = this.configService.get<boolean>('smtp_auth_required');
|
|
||||||
const smtpUser = this.configService.get<string>('smtp_user');
|
|
||||||
const smtpPassword = this.configService.get<string>('smtp_password');
|
|
||||||
const emailFromName = this.configService.get<string>('email_from_name');
|
|
||||||
const emailFromAddress = this.configService.get<string>('email_from_address');
|
|
||||||
|
|
||||||
// Import dynamique de nodemailer
|
|
||||||
const nodemailer = await import('nodemailer');
|
|
||||||
|
|
||||||
// Configuration du transporteur
|
|
||||||
const transportConfig: any = {
|
|
||||||
host: smtpHost,
|
|
||||||
port: smtpPort,
|
|
||||||
secure: smtpSecure,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (smtpAuthRequired && smtpUser && smtpPassword) {
|
|
||||||
transportConfig.auth = {
|
|
||||||
user: smtpUser,
|
|
||||||
pass: smtpPassword,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport(transportConfig);
|
|
||||||
|
|
||||||
// Envoi de l'email
|
|
||||||
await transporter.sendMail({
|
|
||||||
from: `"${emailFromName}" <${emailFromAddress}>`,
|
|
||||||
to,
|
|
||||||
subject,
|
|
||||||
text: text || html.replace(/<[^>]*>?/gm, ''), // Fallback texte simple
|
|
||||||
html,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.logger.log(`📧 Email envoyé à ${to} : ${subject}`);
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error(`❌ Erreur lors de l'envoi de l'email à ${to}`, error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Envoi de l'email de bienvenue pour un gestionnaire
|
|
||||||
* @param to Email du gestionnaire
|
|
||||||
* @param prenom Prénom
|
|
||||||
* @param nom Nom
|
|
||||||
* @param token Token de création de mot de passe (si applicable) ou mot de passe temporaire (si applicable)
|
|
||||||
* @note Pour l'instant, on suppose que le gestionnaire doit définir son mot de passe via "Mot de passe oublié" ou un lien d'activation
|
|
||||||
* Mais le ticket #17 parle de "Flag changement_mdp_obligatoire = TRUE", ce qui implique qu'on lui donne un mot de passe temporaire ou qu'on lui envoie un lien.
|
|
||||||
* Le ticket #24 parle de "API Création mot de passe" via token.
|
|
||||||
* Pour le ticket #17, on crée le gestionnaire avec un mot de passe (hashé).
|
|
||||||
* Si on suit le ticket #35 (Frontend), on saisit un mot de passe.
|
|
||||||
* Donc on envoie juste un email de confirmation de création de compte.
|
|
||||||
*/
|
|
||||||
async sendGestionnaireWelcomeEmail(to: string, prenom: string, nom: string): Promise<void> {
|
|
||||||
const appName = this.configService.get<string>('app_name', 'P\'titsPas');
|
|
||||||
const appUrl = this.configService.get<string>('app_url', 'https://app.ptits-pas.fr');
|
|
||||||
|
|
||||||
const subject = `Bienvenue sur ${appName}`;
|
|
||||||
const html = `
|
|
||||||
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
||||||
<h2 style="color: #4CAF50;">Bienvenue ${prenom} ${nom} !</h2>
|
|
||||||
<p>Votre compte gestionnaire sur <strong>${appName}</strong> a été créé avec succès.</p>
|
|
||||||
<p>Vous pouvez dès à présent vous connecter avec l'adresse email <strong>${to}</strong> et le mot de passe qui vous a été communiqué.</p>
|
|
||||||
<p>Lors de votre première connexion, il vous sera demandé de modifier votre mot de passe pour des raisons de sécurité.</p>
|
|
||||||
<div style="text-align: center; margin: 30px 0;">
|
|
||||||
<a href="${appUrl}" style="background-color: #4CAF50; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; font-weight: bold;">Accéder à l'application</a>
|
|
||||||
</div>
|
|
||||||
<hr style="border: 1px solid #eee; margin: 20px 0;">
|
|
||||||
<p style="color: #666; font-size: 12px;">
|
|
||||||
Cet email a été envoyé automatiquement. Merci de ne pas y répondre.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
await this.sendEmail(to, subject, html);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,13 +4,11 @@ import { GestionnairesController } from './gestionnaires.controller';
|
|||||||
import { Users } from 'src/entities/users.entity';
|
import { Users } from 'src/entities/users.entity';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { AuthModule } from 'src/routes/auth/auth.module';
|
import { AuthModule } from 'src/routes/auth/auth.module';
|
||||||
import { MailModule } from 'src/modules/mail/mail.module';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forFeature([Users]),
|
TypeOrmModule.forFeature([Users]),
|
||||||
AuthModule,
|
AuthModule,
|
||||||
MailModule,
|
|
||||||
],
|
],
|
||||||
controllers: [GestionnairesController],
|
controllers: [GestionnairesController],
|
||||||
providers: [GestionnairesService],
|
providers: [GestionnairesService],
|
||||||
|
|||||||
@ -9,14 +9,12 @@ import { RoleType, Users } from 'src/entities/users.entity';
|
|||||||
import { CreateGestionnaireDto } from '../dto/create_gestionnaire.dto';
|
import { CreateGestionnaireDto } from '../dto/create_gestionnaire.dto';
|
||||||
import { UpdateGestionnaireDto } from '../dto/update_gestionnaire.dto';
|
import { UpdateGestionnaireDto } from '../dto/update_gestionnaire.dto';
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
import { MailService } from 'src/modules/mail/mail.service';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GestionnairesService {
|
export class GestionnairesService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Users)
|
@InjectRepository(Users)
|
||||||
private readonly gestionnaireRepository: Repository<Users>,
|
private readonly gestionnaireRepository: Repository<Users>,
|
||||||
private readonly mailService: MailService,
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
// Création d’un gestionnaire
|
// Création d’un gestionnaire
|
||||||
@ -41,26 +39,11 @@ export class GestionnairesService {
|
|||||||
date_consentement_photo: dto.date_consentement_photo
|
date_consentement_photo: dto.date_consentement_photo
|
||||||
? new Date(dto.date_consentement_photo)
|
? new Date(dto.date_consentement_photo)
|
||||||
: undefined,
|
: undefined,
|
||||||
changement_mdp_obligatoire: true, // Forcé à true pour les nouveaux gestionnaires
|
changement_mdp_obligatoire: dto.changement_mdp_obligatoire ?? false,
|
||||||
role: RoleType.GESTIONNAIRE,
|
role: RoleType.GESTIONNAIRE,
|
||||||
relaisId: dto.relaisId,
|
relaisId: dto.relaisId,
|
||||||
});
|
});
|
||||||
|
return this.gestionnaireRepository.save(entity);
|
||||||
const savedUser = await this.gestionnaireRepository.save(entity);
|
|
||||||
|
|
||||||
// Envoi de l'email de bienvenue
|
|
||||||
try {
|
|
||||||
await this.mailService.sendGestionnaireWelcomeEmail(
|
|
||||||
savedUser.email,
|
|
||||||
savedUser.prenom || '',
|
|
||||||
savedUser.nom || '',
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
// On ne bloque pas la création si l'envoi d'email échoue, mais on log l'erreur
|
|
||||||
console.error('Erreur lors de l\'envoi de l\'email de bienvenue au gestionnaire', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return savedUser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Liste des gestionnaires
|
// Liste des gestionnaires
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user