@nik2208/node-auth 1.0.2

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.
Files changed (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +636 -0
  3. package/dist/abstract/base-auth-strategy.abstract.d.ts +7 -0
  4. package/dist/abstract/base-auth-strategy.abstract.d.ts.map +1 -0
  5. package/dist/abstract/base-auth-strategy.abstract.js +7 -0
  6. package/dist/abstract/base-auth-strategy.abstract.js.map +1 -0
  7. package/dist/abstract/base-oauth-strategy.abstract.d.ts +26 -0
  8. package/dist/abstract/base-oauth-strategy.abstract.d.ts.map +1 -0
  9. package/dist/abstract/base-oauth-strategy.abstract.js +11 -0
  10. package/dist/abstract/base-oauth-strategy.abstract.js.map +1 -0
  11. package/dist/auth-configurator.d.ts +24 -0
  12. package/dist/auth-configurator.d.ts.map +1 -0
  13. package/dist/auth-configurator.js +42 -0
  14. package/dist/auth-configurator.js.map +1 -0
  15. package/dist/index.d.ts +25 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +36 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/interfaces/auth-strategy.interface.d.ts +6 -0
  20. package/dist/interfaces/auth-strategy.interface.d.ts.map +1 -0
  21. package/dist/interfaces/auth-strategy.interface.js +3 -0
  22. package/dist/interfaces/auth-strategy.interface.js.map +1 -0
  23. package/dist/interfaces/token-store.interface.d.ts +10 -0
  24. package/dist/interfaces/token-store.interface.d.ts.map +1 -0
  25. package/dist/interfaces/token-store.interface.js +3 -0
  26. package/dist/interfaces/token-store.interface.js.map +1 -0
  27. package/dist/interfaces/user-store.interface.d.ts +23 -0
  28. package/dist/interfaces/user-store.interface.d.ts.map +1 -0
  29. package/dist/interfaces/user-store.interface.js +3 -0
  30. package/dist/interfaces/user-store.interface.js.map +1 -0
  31. package/dist/middleware/auth.middleware.d.ts +12 -0
  32. package/dist/middleware/auth.middleware.d.ts.map +1 -0
  33. package/dist/middleware/auth.middleware.js +23 -0
  34. package/dist/middleware/auth.middleware.js.map +1 -0
  35. package/dist/models/auth-config.model.d.ts +96 -0
  36. package/dist/models/auth-config.model.d.ts.map +1 -0
  37. package/dist/models/auth-config.model.js +3 -0
  38. package/dist/models/auth-config.model.js.map +1 -0
  39. package/dist/models/errors.d.ts +6 -0
  40. package/dist/models/errors.d.ts.map +1 -0
  41. package/dist/models/errors.js +13 -0
  42. package/dist/models/errors.js.map +1 -0
  43. package/dist/models/token.model.d.ts +12 -0
  44. package/dist/models/token.model.d.ts.map +1 -0
  45. package/dist/models/token.model.js +3 -0
  46. package/dist/models/token.model.js.map +1 -0
  47. package/dist/models/user.model.d.ts +18 -0
  48. package/dist/models/user.model.d.ts.map +1 -0
  49. package/dist/models/user.model.js +3 -0
  50. package/dist/models/user.model.js.map +1 -0
  51. package/dist/router/auth.router.d.ts +13 -0
  52. package/dist/router/auth.router.d.ts.map +1 -0
  53. package/dist/router/auth.router.js +329 -0
  54. package/dist/router/auth.router.js.map +1 -0
  55. package/dist/services/mailer.service.d.ts +11 -0
  56. package/dist/services/mailer.service.d.ts.map +1 -0
  57. package/dist/services/mailer.service.js +138 -0
  58. package/dist/services/mailer.service.js.map +1 -0
  59. package/dist/services/password.service.d.ts +5 -0
  60. package/dist/services/password.service.d.ts.map +1 -0
  61. package/dist/services/password.service.js +17 -0
  62. package/dist/services/password.service.js.map +1 -0
  63. package/dist/services/sms.service.d.ts +14 -0
  64. package/dist/services/sms.service.d.ts.map +1 -0
  65. package/dist/services/sms.service.js +51 -0
  66. package/dist/services/sms.service.js.map +1 -0
  67. package/dist/services/token.service.d.ts +13 -0
  68. package/dist/services/token.service.d.ts.map +1 -0
  69. package/dist/services/token.service.js +78 -0
  70. package/dist/services/token.service.js.map +1 -0
  71. package/dist/strategies/local/local.strategy.d.ts +19 -0
  72. package/dist/strategies/local/local.strategy.d.ts.map +1 -0
  73. package/dist/strategies/local/local.strategy.js +29 -0
  74. package/dist/strategies/local/local.strategy.js.map +1 -0
  75. package/dist/strategies/magic-link/magic-link.strategy.d.ts +8 -0
  76. package/dist/strategies/magic-link/magic-link.strategy.d.ts.map +1 -0
  77. package/dist/strategies/magic-link/magic-link.strategy.js +50 -0
  78. package/dist/strategies/magic-link/magic-link.strategy.js.map +1 -0
  79. package/dist/strategies/oauth/github.strategy.d.ts +29 -0
  80. package/dist/strategies/oauth/github.strategy.d.ts.map +1 -0
  81. package/dist/strategies/oauth/github.strategy.js +69 -0
  82. package/dist/strategies/oauth/github.strategy.js.map +1 -0
  83. package/dist/strategies/oauth/google.strategy.d.ts +29 -0
  84. package/dist/strategies/oauth/google.strategy.d.ts.map +1 -0
  85. package/dist/strategies/oauth/google.strategy.js +61 -0
  86. package/dist/strategies/oauth/google.strategy.js.map +1 -0
  87. package/dist/strategies/sms/sms.strategy.d.ts +7 -0
  88. package/dist/strategies/sms/sms.strategy.d.ts.map +1 -0
  89. package/dist/strategies/sms/sms.strategy.js +39 -0
  90. package/dist/strategies/sms/sms.strategy.js.map +1 -0
  91. package/dist/strategies/two-factor/totp.strategy.d.ts +12 -0
  92. package/dist/strategies/two-factor/totp.strategy.d.ts.map +1 -0
  93. package/dist/strategies/two-factor/totp.strategy.js +32 -0
  94. package/dist/strategies/two-factor/totp.strategy.js.map +1 -0
  95. package/package.json +48 -0
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAuthRouter = createAuthRouter;
4
+ const express_1 = require("express");
5
+ const token_service_1 = require("../services/token.service");
6
+ const password_service_1 = require("../services/password.service");
7
+ const mailer_service_1 = require("../services/mailer.service");
8
+ const local_strategy_1 = require("../strategies/local/local.strategy");
9
+ const totp_strategy_1 = require("../strategies/two-factor/totp.strategy");
10
+ const magic_link_strategy_1 = require("../strategies/magic-link/magic-link.strategy");
11
+ const sms_strategy_1 = require("../strategies/sms/sms.strategy");
12
+ const auth_middleware_1 = require("../middleware/auth.middleware");
13
+ const errors_1 = require("../models/errors");
14
+ const tokenService = new token_service_1.TokenService();
15
+ const passwordService = new password_service_1.PasswordService();
16
+ const totpStrategy = new totp_strategy_1.TotpStrategy();
17
+ const magicLinkStrategy = new magic_link_strategy_1.MagicLinkStrategy();
18
+ const smsStrategy = new sms_strategy_1.SmsStrategy();
19
+ function handleError(res, err) {
20
+ if (err instanceof errors_1.AuthError) {
21
+ res.status(err.statusCode).json({ error: err.message, code: err.code });
22
+ }
23
+ else {
24
+ res.status(500).json({ error: 'Internal server error' });
25
+ }
26
+ }
27
+ function createAuthRouter(userStore, config, options = {}) {
28
+ const router = (0, express_1.Router)();
29
+ const authMiddleware = (0, auth_middleware_1.createAuthMiddleware)(config);
30
+ const localStrategy = new local_strategy_1.LocalStrategy(userStore, passwordService);
31
+ const rl = options.rateLimiter ? [options.rateLimiter] : [];
32
+ // POST /login
33
+ router.post('/login', ...rl, async (req, res) => {
34
+ try {
35
+ const { email, password } = req.body;
36
+ const user = await localStrategy.authenticate({ email, password }, config);
37
+ if (user.isTotpEnabled && user.totpSecret) {
38
+ // Issue a short-lived temp token for 2FA
39
+ const tempToken = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, { ...config, accessTokenExpiresIn: '5m', refreshTokenExpiresIn: '5m' }).accessToken;
40
+ res.json({ requiresTwoFactor: true, tempToken });
41
+ return;
42
+ }
43
+ const tokens = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, config);
44
+ const refreshExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
45
+ await userStore.updateRefreshToken(user.id, tokens.refreshToken, refreshExpiry);
46
+ tokenService.setTokenCookies(res, tokens, config);
47
+ res.json({ success: true });
48
+ }
49
+ catch (err) {
50
+ handleError(res, err);
51
+ }
52
+ });
53
+ // POST /logout
54
+ router.post('/logout', ...rl, authMiddleware, async (req, res) => {
55
+ try {
56
+ if (req.user?.sub) {
57
+ await userStore.updateRefreshToken(req.user.sub, null, null);
58
+ }
59
+ tokenService.clearTokenCookies(res);
60
+ res.json({ success: true });
61
+ }
62
+ catch (err) {
63
+ handleError(res, err);
64
+ }
65
+ });
66
+ // POST /refresh
67
+ router.post('/refresh', ...rl, async (req, res) => {
68
+ try {
69
+ const refreshToken = tokenService.extractTokenFromCookie(req, 'refreshToken');
70
+ if (!refreshToken) {
71
+ res.status(401).json({ error: 'No refresh token provided' });
72
+ return;
73
+ }
74
+ const payload = tokenService.verifyRefreshToken(refreshToken, config);
75
+ const user = await userStore.findById(payload.sub);
76
+ if (!user || user.refreshToken !== refreshToken) {
77
+ res.status(401).json({ error: 'Invalid refresh token' });
78
+ return;
79
+ }
80
+ const tokens = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, config);
81
+ const refreshExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
82
+ await userStore.updateRefreshToken(user.id, tokens.refreshToken, refreshExpiry);
83
+ tokenService.setTokenCookies(res, tokens, config);
84
+ res.json({ success: true });
85
+ }
86
+ catch (err) {
87
+ handleError(res, err);
88
+ }
89
+ });
90
+ // GET /me
91
+ router.get('/me', ...rl, authMiddleware, (req, res) => {
92
+ res.json(req.user);
93
+ });
94
+ // POST /forgot-password
95
+ router.post('/forgot-password', ...rl, async (req, res) => {
96
+ try {
97
+ const { email, emailLang } = req.body;
98
+ const user = await userStore.findByEmail(email);
99
+ if (user) {
100
+ const token = tokenService.generateSecureToken();
101
+ const expiry = new Date(Date.now() + 60 * 60 * 1000); // 1 hour
102
+ await userStore.updateResetToken(user.id, token, expiry);
103
+ const siteUrl = config.email?.siteUrl ?? '';
104
+ const link = `${siteUrl}/auth/reset-password?token=${token}`;
105
+ if (config.email?.sendPasswordReset) {
106
+ await config.email.sendPasswordReset(email, token, link, emailLang);
107
+ }
108
+ else if (config.email?.mailer) {
109
+ const mailer = new mailer_service_1.MailerService(config.email.mailer);
110
+ await mailer.sendPasswordReset(email, token, link, emailLang);
111
+ }
112
+ }
113
+ // Always return success to prevent email enumeration
114
+ res.json({ success: true });
115
+ }
116
+ catch (err) {
117
+ handleError(res, err);
118
+ }
119
+ });
120
+ // POST /reset-password
121
+ router.post('/reset-password', ...rl, async (req, res) => {
122
+ try {
123
+ const { token, password } = req.body;
124
+ if (!userStore.findByResetToken) {
125
+ res.status(500).json({ error: 'UserStore does not implement findByResetToken' });
126
+ return;
127
+ }
128
+ const user = await userStore.findByResetToken(token);
129
+ if (!user || !user.resetToken || user.resetToken !== token) {
130
+ res.status(400).json({ error: 'Invalid reset token' });
131
+ return;
132
+ }
133
+ if (user.resetTokenExpiry && new Date() > user.resetTokenExpiry) {
134
+ res.status(400).json({ error: 'Reset token has expired' });
135
+ return;
136
+ }
137
+ const hashed = await passwordService.hash(password, config.bcryptSaltRounds);
138
+ await userStore.updatePassword(user.id, hashed);
139
+ await userStore.updateResetToken(user.id, null, null);
140
+ res.json({ success: true });
141
+ }
142
+ catch (err) {
143
+ handleError(res, err);
144
+ }
145
+ });
146
+ // POST /2fa/setup
147
+ router.post('/2fa/setup', ...rl, authMiddleware, (req, res) => {
148
+ try {
149
+ const appName = config.twoFactor?.appName ?? 'node-auth';
150
+ const email = req.user.email;
151
+ const { secret, otpauthUrl, qrCode } = totpStrategy.generateSecret(email, appName);
152
+ // Return qrCode as a promise - resolve it
153
+ qrCode.then((dataUrl) => {
154
+ res.json({ secret, otpauthUrl, qrCode: dataUrl });
155
+ }).catch((err) => handleError(res, err));
156
+ }
157
+ catch (err) {
158
+ handleError(res, err);
159
+ }
160
+ });
161
+ // POST /2fa/verify-setup
162
+ router.post('/2fa/verify-setup', ...rl, authMiddleware, async (req, res) => {
163
+ try {
164
+ const { token, secret } = req.body;
165
+ const valid = await totpStrategy.verify(token, secret);
166
+ if (!valid) {
167
+ res.status(400).json({ error: 'Invalid TOTP code' });
168
+ return;
169
+ }
170
+ await totpStrategy.enable(req.user.sub, secret, userStore);
171
+ res.json({ success: true });
172
+ }
173
+ catch (err) {
174
+ handleError(res, err);
175
+ }
176
+ });
177
+ // POST /2fa/verify - after login with 2FA
178
+ router.post('/2fa/verify', ...rl, async (req, res) => {
179
+ try {
180
+ const { tempToken, totpCode } = req.body;
181
+ const payload = tokenService.verifyAccessToken(tempToken, config);
182
+ const user = await userStore.findById(payload.sub);
183
+ if (!user || !user.totpSecret) {
184
+ res.status(400).json({ error: 'User not found or 2FA not set up' });
185
+ return;
186
+ }
187
+ const valid = await totpStrategy.verify(totpCode, user.totpSecret);
188
+ if (!valid) {
189
+ res.status(401).json({ error: 'Invalid TOTP code' });
190
+ return;
191
+ }
192
+ const tokens = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, config);
193
+ const refreshExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
194
+ await userStore.updateRefreshToken(user.id, tokens.refreshToken, refreshExpiry);
195
+ tokenService.setTokenCookies(res, tokens, config);
196
+ res.json({ success: true });
197
+ }
198
+ catch (err) {
199
+ handleError(res, err);
200
+ }
201
+ });
202
+ // POST /2fa/disable
203
+ router.post('/2fa/disable', ...rl, authMiddleware, async (req, res) => {
204
+ try {
205
+ await totpStrategy.disable(req.user.sub, userStore);
206
+ res.json({ success: true });
207
+ }
208
+ catch (err) {
209
+ handleError(res, err);
210
+ }
211
+ });
212
+ // POST /magic-link/send
213
+ router.post('/magic-link/send', ...rl, async (req, res) => {
214
+ try {
215
+ const { email, emailLang } = req.body;
216
+ await magicLinkStrategy.sendMagicLink(email, userStore, config, emailLang);
217
+ res.json({ success: true });
218
+ }
219
+ catch (err) {
220
+ handleError(res, err);
221
+ }
222
+ });
223
+ // POST /magic-link/verify
224
+ router.post('/magic-link/verify', ...rl, async (req, res) => {
225
+ try {
226
+ const { token } = req.body;
227
+ const user = await magicLinkStrategy.verify(token, userStore);
228
+ const tokens = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, config);
229
+ const refreshExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
230
+ await userStore.updateRefreshToken(user.id, tokens.refreshToken, refreshExpiry);
231
+ tokenService.setTokenCookies(res, tokens, config);
232
+ res.json({ success: true });
233
+ }
234
+ catch (err) {
235
+ handleError(res, err);
236
+ }
237
+ });
238
+ // POST /sms/send
239
+ router.post('/sms/send', ...rl, async (req, res) => {
240
+ try {
241
+ const { phone, userId } = req.body;
242
+ await smsStrategy.sendCode(phone, userId, userStore, config);
243
+ res.json({ success: true });
244
+ }
245
+ catch (err) {
246
+ handleError(res, err);
247
+ }
248
+ });
249
+ // POST /sms/verify
250
+ router.post('/sms/verify', ...rl, async (req, res) => {
251
+ try {
252
+ const { userId, code } = req.body;
253
+ const valid = await smsStrategy.verify(userId, code, userStore);
254
+ if (!valid) {
255
+ res.status(401).json({ error: 'Invalid or expired SMS code' });
256
+ return;
257
+ }
258
+ const user = await userStore.findById(userId);
259
+ if (!user) {
260
+ res.status(404).json({ error: 'User not found' });
261
+ return;
262
+ }
263
+ const tokens = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, config);
264
+ const refreshExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
265
+ await userStore.updateRefreshToken(user.id, tokens.refreshToken, refreshExpiry);
266
+ tokenService.setTokenCookies(res, tokens, config);
267
+ res.json({ success: true });
268
+ }
269
+ catch (err) {
270
+ handleError(res, err);
271
+ }
272
+ });
273
+ // OAuth Google
274
+ if (options.googleStrategy) {
275
+ const googleStrategy = options.googleStrategy;
276
+ router.get('/oauth/google', (_req, res) => {
277
+ const state = tokenService.generateSecureToken(16);
278
+ const url = googleStrategy.getAuthorizationUrl(state);
279
+ res.redirect(url);
280
+ });
281
+ router.get('/oauth/google/callback', async (req, res) => {
282
+ try {
283
+ const { code, state } = req.query;
284
+ const user = await googleStrategy.handleCallback(code, state);
285
+ const tokens = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, config);
286
+ const refreshExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
287
+ await userStore.updateRefreshToken(user.id, tokens.refreshToken, refreshExpiry);
288
+ tokenService.setTokenCookies(res, tokens, config);
289
+ res.redirect(config.email?.siteUrl ?? '/');
290
+ }
291
+ catch (err) {
292
+ handleError(res, err);
293
+ }
294
+ });
295
+ }
296
+ else {
297
+ router.get('/oauth/google', (_req, res) => res.status(404).json({ error: 'Google OAuth not configured' }));
298
+ router.get('/oauth/google/callback', (_req, res) => res.status(404).json({ error: 'Google OAuth not configured' }));
299
+ }
300
+ // OAuth GitHub
301
+ if (options.githubStrategy) {
302
+ const githubStrategy = options.githubStrategy;
303
+ router.get('/oauth/github', (_req, res) => {
304
+ const state = tokenService.generateSecureToken(16);
305
+ const url = githubStrategy.getAuthorizationUrl(state);
306
+ res.redirect(url);
307
+ });
308
+ router.get('/oauth/github/callback', async (req, res) => {
309
+ try {
310
+ const { code, state } = req.query;
311
+ const user = await githubStrategy.handleCallback(code, state);
312
+ const tokens = tokenService.generateTokenPair({ sub: user.id, email: user.email, role: user.role }, config);
313
+ const refreshExpiry = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
314
+ await userStore.updateRefreshToken(user.id, tokens.refreshToken, refreshExpiry);
315
+ tokenService.setTokenCookies(res, tokens, config);
316
+ res.redirect(config.email?.siteUrl ?? '/');
317
+ }
318
+ catch (err) {
319
+ handleError(res, err);
320
+ }
321
+ });
322
+ }
323
+ else {
324
+ router.get('/oauth/github', (_req, res) => res.status(404).json({ error: 'GitHub OAuth not configured' }));
325
+ router.get('/oauth/github/callback', (_req, res) => res.status(404).json({ error: 'GitHub OAuth not configured' }));
326
+ }
327
+ return router;
328
+ }
329
+ //# sourceMappingURL=auth.router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.router.js","sourceRoot":"","sources":["../../src/router/auth.router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { MailerConfig } from '../models/auth-config.model';
2
+ export declare class MailerService {
3
+ private readonly config;
4
+ constructor(config: MailerConfig);
5
+ sendPasswordReset(to: string, _token: string, link: string, lang?: string): Promise<void>;
6
+ sendMagicLink(to: string, _token: string, link: string, lang?: string): Promise<void>;
7
+ sendWelcome(to: string, data: Record<string, unknown>, lang?: string): Promise<void>;
8
+ private resolveLang;
9
+ private send;
10
+ }
11
+ //# sourceMappingURL=mailer.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mailer.service.d.ts","sourceRoot":"","sources":["../../src/services/mailer.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAmG3D,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;IAI3C,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzF,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrF,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1F,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,IAAI;CA+Bb"}
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MailerService = void 0;
7
+ const https_1 = __importDefault(require("https"));
8
+ const http_1 = __importDefault(require("http"));
9
+ const url_1 = require("url");
10
+ function passwordResetTemplate(link, lang) {
11
+ if (lang === 'it') {
12
+ return {
13
+ subject: 'Reimposta la tua password',
14
+ html: `<p>Hai richiesto di reimpostare la tua password.</p>
15
+ <p>Clicca sul link seguente per procedere (valido 1 ora):</p>
16
+ <p><a href="${link}">${link}</a></p>
17
+ <p>Se non hai richiesto questo, ignora questa email.</p>`,
18
+ text: `Hai richiesto di reimpostare la tua password.\n\nClicca sul link seguente (valido 1 ora):\n${link}\n\nSe non hai richiesto questo, ignora questa email.`,
19
+ };
20
+ }
21
+ return {
22
+ subject: 'Reset your password',
23
+ html: `<p>You requested a password reset.</p>
24
+ <p>Click the link below to proceed (valid for 1 hour):</p>
25
+ <p><a href="${link}">${link}</a></p>
26
+ <p>If you did not request this, please ignore this email.</p>`,
27
+ text: `You requested a password reset.\n\nClick the link below (valid for 1 hour):\n${link}\n\nIf you did not request this, please ignore this email.`,
28
+ };
29
+ }
30
+ function magicLinkTemplate(link, lang) {
31
+ if (lang === 'it') {
32
+ return {
33
+ subject: 'Il tuo link di accesso',
34
+ html: `<p>Hai richiesto un link di accesso.</p>
35
+ <p>Clicca sul link seguente per accedere (valido 15 minuti):</p>
36
+ <p><a href="${link}">${link}</a></p>
37
+ <p>Se non hai richiesto questo, ignora questa email.</p>`,
38
+ text: `Hai richiesto un link di accesso.\n\nClicca sul link seguente (valido 15 minuti):\n${link}\n\nSe non hai richiesto questo, ignora questa email.`,
39
+ };
40
+ }
41
+ return {
42
+ subject: 'Your magic sign-in link',
43
+ html: `<p>You requested a sign-in link.</p>
44
+ <p>Click the link below to sign in (valid for 15 minutes):</p>
45
+ <p><a href="${link}">${link}</a></p>
46
+ <p>If you did not request this, please ignore this email.</p>`,
47
+ text: `You requested a sign-in link.\n\nClick the link below (valid for 15 minutes):\n${link}\n\nIf you did not request this, please ignore this email.`,
48
+ };
49
+ }
50
+ function welcomeTemplate(data, lang) {
51
+ const loginUrl = data['loginUrl'] ?? '';
52
+ const tempPassword = data['tempPassword'];
53
+ if (lang === 'it') {
54
+ const passwordLine = tempPassword
55
+ ? `<p>Password temporanea: <strong>${tempPassword}</strong></p>`
56
+ : '';
57
+ const passwordText = tempPassword ? `Password temporanea: ${tempPassword}\n` : '';
58
+ return {
59
+ subject: 'Benvenuto! Il tuo account è stato creato',
60
+ html: `<p>Il tuo account è stato creato con successo.</p>
61
+ ${passwordLine}
62
+ <p>Accedi qui: <a href="${loginUrl}">${loginUrl}</a></p>`,
63
+ text: `Il tuo account è stato creato con successo.\n${passwordText}Accedi qui: ${loginUrl}`,
64
+ };
65
+ }
66
+ const passwordLine = tempPassword
67
+ ? `<p>Temporary password: <strong>${tempPassword}</strong></p>`
68
+ : '';
69
+ const passwordText = tempPassword ? `Temporary password: ${tempPassword}\n` : '';
70
+ return {
71
+ subject: 'Welcome! Your account has been created',
72
+ html: `<p>Your account has been created successfully.</p>
73
+ ${passwordLine}
74
+ <p>Sign in here: <a href="${loginUrl}">${loginUrl}</a></p>`,
75
+ text: `Your account has been created successfully.\n${passwordText}Sign in here: ${loginUrl}`,
76
+ };
77
+ }
78
+ class MailerService {
79
+ constructor(config) {
80
+ this.config = config;
81
+ }
82
+ // ---- Public helpers -------------------------------------------------------
83
+ async sendPasswordReset(to, _token, link, lang) {
84
+ const l = this.resolveLang(lang);
85
+ const tpl = passwordResetTemplate(link, l);
86
+ await this.send({ to, ...tpl, from: this.config.from, fromName: this.config.fromName });
87
+ }
88
+ async sendMagicLink(to, _token, link, lang) {
89
+ const l = this.resolveLang(lang);
90
+ const tpl = magicLinkTemplate(link, l);
91
+ await this.send({ to, ...tpl, from: this.config.from, fromName: this.config.fromName });
92
+ }
93
+ async sendWelcome(to, data, lang) {
94
+ const l = this.resolveLang(lang);
95
+ const tpl = welcomeTemplate(data, l);
96
+ await this.send({ to, ...tpl, from: this.config.from, fromName: this.config.fromName });
97
+ }
98
+ // ---- Transport ------------------------------------------------------------
99
+ resolveLang(lang) {
100
+ if (lang === 'it')
101
+ return 'it';
102
+ if (lang === 'en')
103
+ return 'en';
104
+ return this.config.defaultLang ?? 'en';
105
+ }
106
+ send(payload) {
107
+ return new Promise((resolve, reject) => {
108
+ const url = new url_1.URL(this.config.endpoint);
109
+ const body = JSON.stringify(payload);
110
+ const options = {
111
+ hostname: url.hostname,
112
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
113
+ path: url.pathname + (url.search || ''),
114
+ method: 'POST',
115
+ headers: {
116
+ 'Content-Type': 'application/json',
117
+ 'Content-Length': Buffer.byteLength(body),
118
+ 'X-API-Key': this.config.apiKey,
119
+ },
120
+ };
121
+ const transport = url.protocol === 'https:' ? https_1.default : http_1.default;
122
+ const req = transport.request(options, (res) => {
123
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
124
+ resolve();
125
+ }
126
+ else {
127
+ reject(new Error(`Mailer request failed with status ${res.statusCode}`));
128
+ }
129
+ res.resume();
130
+ });
131
+ req.on('error', reject);
132
+ req.write(body);
133
+ req.end();
134
+ });
135
+ }
136
+ }
137
+ exports.MailerService = MailerService;
138
+ //# sourceMappingURL=mailer.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mailer.service.js","sourceRoot":"","sources":["../../src/services/mailer.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare class PasswordService {
2
+ hash(password: string, saltRounds?: number): Promise<string>;
3
+ compare(password: string, hash: string): Promise<boolean>;
4
+ }
5
+ //# sourceMappingURL=password.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.service.d.ts","sourceRoot":"","sources":["../../src/services/password.service.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAe;IACpB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAIhE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGhE"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PasswordService = void 0;
7
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
8
+ class PasswordService {
9
+ async hash(password, saltRounds = 12) {
10
+ return bcryptjs_1.default.hash(password, saltRounds);
11
+ }
12
+ async compare(password, hash) {
13
+ return bcryptjs_1.default.compare(password, hash);
14
+ }
15
+ }
16
+ exports.PasswordService = PasswordService;
17
+ //# sourceMappingURL=password.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password.service.js","sourceRoot":"","sources":["../../src/services/password.service.ts"],"names":[],"mappings":";;;;;;AAAA,wDAA8B;AAE9B,MAAa,eAAe;IAC1B,KAAK,CAAC,IAAI,CAAC,QAAgB,EAAE,aAAqB,EAAE;QAClD,OAAO,kBAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,IAAY;QAC1C,OAAO,kBAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxC,CAAC;CACF;AARD,0CAQC"}
@@ -0,0 +1,14 @@
1
+ export interface SmsConfig {
2
+ endpoint: string;
3
+ apiKey: string;
4
+ username: string;
5
+ password: string;
6
+ codeExpiresInMinutes?: number;
7
+ }
8
+ export declare class SmsService {
9
+ private readonly config;
10
+ constructor(config: SmsConfig);
11
+ sendSms(phone: string, message: string): Promise<void>;
12
+ generateCode(digits?: number): string;
13
+ }
14
+ //# sourceMappingURL=sms.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sms.service.d.ts","sourceRoot":"","sources":["../../src/services/sms.service.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAE9C,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCtD,YAAY,CAAC,MAAM,GAAE,MAAU,GAAG,MAAM;CAKzC"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SmsService = void 0;
7
+ const https_1 = __importDefault(require("https"));
8
+ const http_1 = __importDefault(require("http"));
9
+ const url_1 = require("url");
10
+ class SmsService {
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ sendSms(phone, message) {
15
+ return new Promise((resolve, reject) => {
16
+ const url = new url_1.URL(this.config.endpoint);
17
+ url.searchParams.set('username', this.config.username);
18
+ url.searchParams.set('password', this.config.password);
19
+ url.searchParams.set('phone', phone);
20
+ url.searchParams.set('message', message);
21
+ const options = {
22
+ hostname: url.hostname,
23
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
24
+ path: `${url.pathname}?${url.searchParams.toString()}`,
25
+ method: 'GET',
26
+ headers: {
27
+ 'X-API-Key': this.config.apiKey,
28
+ },
29
+ };
30
+ const transport = url.protocol === 'https:' ? https_1.default : http_1.default;
31
+ const req = transport.request(options, (res) => {
32
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
33
+ resolve();
34
+ }
35
+ else {
36
+ reject(new Error(`SMS send failed with status ${res.statusCode}`));
37
+ }
38
+ res.resume();
39
+ });
40
+ req.on('error', reject);
41
+ req.end();
42
+ });
43
+ }
44
+ generateCode(digits = 6) {
45
+ const max = Math.pow(10, digits);
46
+ const min = Math.pow(10, digits - 1);
47
+ return String(Math.floor(min + Math.random() * (max - min)));
48
+ }
49
+ }
50
+ exports.SmsService = SmsService;
51
+ //# sourceMappingURL=sms.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sms.service.js","sourceRoot":"","sources":["../../src/services/sms.service.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,gDAAwB;AACxB,6BAA0B;AAU1B,MAAa,UAAU;IACrB,YAA6B,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAElD,OAAO,CAAC,KAAa,EAAE,OAAe;QACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,IAAI,SAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC1C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACvD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACrC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAEzC,MAAM,OAAO,GAAG;gBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxD,IAAI,EAAE,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE;gBACtD,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;iBAChC;aACF,CAAC;YAEF,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAK,CAAC,CAAC,CAAC,cAAI,CAAC;YAC3D,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC7C,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;oBACpE,OAAO,EAAE,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,KAAK,CAAC,+BAA+B,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBACrE,CAAC;gBACD,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACxB,GAAG,CAAC,GAAG,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,SAAiB,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;CACF;AAxCD,gCAwCC"}
@@ -0,0 +1,13 @@
1
+ import { Request, Response } from 'express';
2
+ import { AccessTokenPayload, TokenPair } from '../models/token.model';
3
+ import { AuthConfig } from '../models/auth-config.model';
4
+ export declare class TokenService {
5
+ generateTokenPair(payload: AccessTokenPayload, config: AuthConfig): TokenPair;
6
+ verifyAccessToken(token: string, config: AuthConfig): AccessTokenPayload;
7
+ verifyRefreshToken(token: string, config: AuthConfig): AccessTokenPayload;
8
+ setTokenCookies(res: Response, tokens: TokenPair, config: AuthConfig): void;
9
+ clearTokenCookies(res: Response): void;
10
+ generateSecureToken(bytes?: number): string;
11
+ extractTokenFromCookie(req: Request, cookieName: string): string | null;
12
+ }
13
+ //# sourceMappingURL=token.service.d.ts.map