nest-authme 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import { Injectable } from '@nestjs/common';
|
|
1
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
2
2
|
import { ConfigService } from '@nestjs/config';
|
|
3
3
|
import * as nodemailer from 'nodemailer';
|
|
4
4
|
|
|
5
5
|
@Injectable()
|
|
6
6
|
export class MailService {
|
|
7
|
+
private readonly logger = new Logger(MailService.name);
|
|
7
8
|
private transporter: nodemailer.Transporter;
|
|
9
|
+
private isConfigured: boolean;
|
|
8
10
|
|
|
9
11
|
constructor(private configService: ConfigService) {
|
|
12
|
+
const smtpUser = this.configService.get('SMTP_USER', '');
|
|
13
|
+
const smtpPass = this.configService.get('SMTP_PASS', '');
|
|
14
|
+
this.isConfigured = !!(smtpUser && smtpPass);
|
|
15
|
+
|
|
10
16
|
this.transporter = nodemailer.createTransport({
|
|
11
17
|
host: this.configService.get('SMTP_HOST', 'smtp.ethereal.email'),
|
|
12
18
|
port: parseInt(this.configService.get('SMTP_PORT', '587'), 10),
|
|
13
19
|
secure: false,
|
|
14
20
|
auth: {
|
|
15
|
-
user:
|
|
16
|
-
pass:
|
|
21
|
+
user: smtpUser,
|
|
22
|
+
pass: smtpPass,
|
|
17
23
|
},
|
|
18
24
|
});
|
|
19
25
|
}
|
|
@@ -33,17 +39,29 @@ export class MailService {
|
|
|
33
39
|
async sendVerificationEmail(to: string, token: string): Promise<void> {
|
|
34
40
|
const verifyUrl = `${this.appUrl}/auth/verify-email?token=${token}`;
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
if (!this.isConfigured) {
|
|
43
|
+
this.logger.warn(
|
|
44
|
+
`SMTP not configured. Verification email for ${to} not sent. Token: ${token}`,
|
|
45
|
+
);
|
|
46
|
+
this.logger.warn(`Verify URL: ${verifyUrl}`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
await this.transporter.sendMail({
|
|
52
|
+
from: this.mailFrom,
|
|
53
|
+
to,
|
|
54
|
+
subject: 'Verify your email address',
|
|
55
|
+
html: `
|
|
56
|
+
<h2>Email Verification</h2>
|
|
57
|
+
<p>Click the link below to verify your email address:</p>
|
|
58
|
+
<p><a href="${verifyUrl}">${verifyUrl}</a></p>
|
|
59
|
+
<p>If you did not create an account, please ignore this email.</p>
|
|
60
|
+
`,
|
|
61
|
+
});
|
|
62
|
+
} catch (error) {
|
|
63
|
+
this.logger.error(`Failed to send verification email to ${to}: ${error.message}`);
|
|
64
|
+
}
|
|
47
65
|
}
|
|
48
66
|
{{/if}}
|
|
49
67
|
|
|
@@ -54,18 +72,30 @@ export class MailService {
|
|
|
54
72
|
async sendResetPasswordEmail(to: string, token: string): Promise<void> {
|
|
55
73
|
const resetUrl = `${this.appUrl}/auth/reset-password?token=${token}`;
|
|
56
74
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
if (!this.isConfigured) {
|
|
76
|
+
this.logger.warn(
|
|
77
|
+
`SMTP not configured. Reset email for ${to} not sent. Token: ${token}`,
|
|
78
|
+
);
|
|
79
|
+
this.logger.warn(`Reset URL: ${resetUrl}`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
await this.transporter.sendMail({
|
|
85
|
+
from: this.mailFrom,
|
|
86
|
+
to,
|
|
87
|
+
subject: 'Reset your password',
|
|
88
|
+
html: `
|
|
89
|
+
<h2>Password Reset</h2>
|
|
90
|
+
<p>Click the link below to reset your password:</p>
|
|
91
|
+
<p><a href="${resetUrl}">${resetUrl}</a></p>
|
|
92
|
+
<p>This link expires in 1 hour.</p>
|
|
93
|
+
<p>If you did not request a password reset, please ignore this email.</p>
|
|
94
|
+
`,
|
|
95
|
+
});
|
|
96
|
+
} catch (error) {
|
|
97
|
+
this.logger.error(`Failed to send reset email to ${to}: ${error.message}`);
|
|
98
|
+
}
|
|
69
99
|
}
|
|
70
100
|
{{/if}}
|
|
71
101
|
}
|
|
@@ -333,7 +333,11 @@ describe('AuthService', () => {
|
|
|
333
333
|
|
|
334
334
|
const result = await authService.resendVerification('test@example.com');
|
|
335
335
|
|
|
336
|
+
{{#if features.emailService}}
|
|
337
|
+
expect(result.message).toBeDefined();
|
|
338
|
+
{{else}}
|
|
336
339
|
expect(result.verificationToken).toBeDefined();
|
|
340
|
+
{{/if}}
|
|
337
341
|
expect(mockUsersService.setVerificationToken).toHaveBeenCalled();
|
|
338
342
|
});
|
|
339
343
|
});
|
|
@@ -347,7 +351,11 @@ describe('AuthService', () => {
|
|
|
347
351
|
|
|
348
352
|
const result = await authService.forgotPassword({ email: 'test@example.com' });
|
|
349
353
|
|
|
354
|
+
{{#if features.emailService}}
|
|
355
|
+
expect(result.message).toBeDefined();
|
|
356
|
+
{{else}}
|
|
350
357
|
expect(result.resetToken).toBeDefined();
|
|
358
|
+
{{/if}}
|
|
351
359
|
expect(mockUsersService.setResetToken).toHaveBeenCalled();
|
|
352
360
|
});
|
|
353
361
|
|
|
@@ -107,7 +107,7 @@ export class UsersService {
|
|
|
107
107
|
roles: ['User'],
|
|
108
108
|
{{/if}}
|
|
109
109
|
} as any);
|
|
110
|
-
return await this.usersRepository.save(user) as User;
|
|
110
|
+
return await this.usersRepository.save(user) as unknown as User;
|
|
111
111
|
}
|
|
112
112
|
{{/if}}
|
|
113
113
|
{{else if (eq orm "prisma")}}
|