@nauth-toolkit/core 0.1.0 → 0.1.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.
- package/LICENSE +90 -0
- package/README.md +30 -0
- package/package.json +7 -2
- package/jest.config.js +0 -15
- package/jest.setup.ts +0 -6
- package/src/adapters/database-columns.ts +0 -165
- package/src/adapters/express.adapter.ts +0 -385
- package/src/adapters/fastify.adapter.ts +0 -416
- package/src/adapters/index.ts +0 -16
- package/src/adapters/storage.factory.ts +0 -143
- package/src/bootstrap.ts +0 -374
- package/src/dto/auth-challenge.dto.ts +0 -231
- package/src/dto/auth-response.dto.ts +0 -253
- package/src/dto/challenge-response.dto.ts +0 -234
- package/src/dto/change-password-request.dto.ts +0 -50
- package/src/dto/change-password-response.dto.ts +0 -29
- package/src/dto/change-password.dto.ts +0 -57
- package/src/dto/error-response.dto.ts +0 -136
- package/src/dto/get-available-methods.dto.ts +0 -55
- package/src/dto/get-challenge-data-response.dto.ts +0 -28
- package/src/dto/get-challenge-data.dto.ts +0 -69
- package/src/dto/get-client-info.dto.ts +0 -104
- package/src/dto/get-device-token-response.dto.ts +0 -25
- package/src/dto/get-events-by-type.dto.ts +0 -76
- package/src/dto/get-ip-address-response.dto.ts +0 -24
- package/src/dto/get-mfa-status.dto.ts +0 -94
- package/src/dto/get-risk-assessment-history.dto.ts +0 -39
- package/src/dto/get-session-id-response.dto.ts +0 -25
- package/src/dto/get-setup-data-response.dto.ts +0 -31
- package/src/dto/get-setup-data.dto.ts +0 -75
- package/src/dto/get-suspicious-activity.dto.ts +0 -42
- package/src/dto/get-user-agent-response.dto.ts +0 -23
- package/src/dto/get-user-auth-history.dto.ts +0 -95
- package/src/dto/get-user-by-email.dto.ts +0 -61
- package/src/dto/get-user-by-id.dto.ts +0 -46
- package/src/dto/get-user-devices.dto.ts +0 -53
- package/src/dto/get-user-response.dto.ts +0 -17
- package/src/dto/has-provider.dto.ts +0 -56
- package/src/dto/index.ts +0 -57
- package/src/dto/is-trusted-device-response.dto.ts +0 -34
- package/src/dto/list-providers-response.dto.ts +0 -23
- package/src/dto/login.dto.ts +0 -95
- package/src/dto/logout-all-response.dto.ts +0 -24
- package/src/dto/logout-all.dto.ts +0 -65
- package/src/dto/logout-response.dto.ts +0 -25
- package/src/dto/logout.dto.ts +0 -64
- package/src/dto/refresh-token.dto.ts +0 -36
- package/src/dto/remove-devices.dto.ts +0 -85
- package/src/dto/resend-code-response.dto.ts +0 -32
- package/src/dto/resend-code.dto.ts +0 -51
- package/src/dto/reset-password.dto.ts +0 -115
- package/src/dto/respond-challenge.dto.ts +0 -272
- package/src/dto/set-mfa-exemption.dto.ts +0 -112
- package/src/dto/set-must-change-password-response.dto.ts +0 -27
- package/src/dto/set-must-change-password.dto.ts +0 -46
- package/src/dto/set-preferred-method.dto.ts +0 -80
- package/src/dto/setup-mfa.dto.ts +0 -98
- package/src/dto/signup.dto.ts +0 -174
- package/src/dto/social-auth.dto.ts +0 -422
- package/src/dto/trust-device-response.dto.ts +0 -30
- package/src/dto/trust-device.dto.ts +0 -9
- package/src/dto/update-user-attributes-request.dto.ts +0 -51
- package/src/dto/user-response.dto.ts +0 -138
- package/src/dto/user-update.dto.ts +0 -222
- package/src/dto/verify-email.dto.ts +0 -313
- package/src/dto/verify-mfa-code.dto.ts +0 -103
- package/src/dto/verify-phone-by-sub.dto.ts +0 -78
- package/src/dto/verify-phone.dto.ts +0 -245
- package/src/entities/auth-audit.entity.ts +0 -232
- package/src/entities/challenge-session.entity.ts +0 -116
- package/src/entities/index.ts +0 -29
- package/src/entities/login-attempt.entity.ts +0 -64
- package/src/entities/mfa-device.entity.ts +0 -151
- package/src/entities/rate-limit.entity.ts +0 -44
- package/src/entities/session.entity.ts +0 -180
- package/src/entities/social-account.entity.ts +0 -96
- package/src/entities/storage-lock.entity.ts +0 -39
- package/src/entities/trusted-device.entity.ts +0 -112
- package/src/entities/user.entity.ts +0 -243
- package/src/entities/verification-token.entity.ts +0 -141
- package/src/enums/auth-audit-event-type.enum.ts +0 -360
- package/src/enums/error-codes.enum.ts +0 -420
- package/src/enums/mfa-method.enum.ts +0 -97
- package/src/enums/risk-factor.enum.ts +0 -111
- package/src/exceptions/nauth.exception.ts +0 -231
- package/src/handlers/auth.handler.ts +0 -260
- package/src/handlers/client-info.handler.ts +0 -101
- package/src/handlers/csrf.handler.ts +0 -156
- package/src/handlers/token-delivery.handler.ts +0 -118
- package/src/index.ts +0 -118
- package/src/interfaces/client-info.interface.ts +0 -85
- package/src/interfaces/config.interface.ts +0 -2135
- package/src/interfaces/entities.interface.ts +0 -226
- package/src/interfaces/index.ts +0 -15
- package/src/interfaces/logger.interface.ts +0 -283
- package/src/interfaces/mfa-provider.interface.ts +0 -154
- package/src/interfaces/oauth.interface.ts +0 -148
- package/src/interfaces/provider.interface.ts +0 -47
- package/src/interfaces/social-auth-provider.interface.ts +0 -131
- package/src/interfaces/storage-adapter.interface.ts +0 -82
- package/src/interfaces/template.interface.ts +0 -510
- package/src/interfaces/token-verifier.interface.ts +0 -110
- package/src/internal.ts +0 -178
- package/src/platform/interfaces.ts +0 -299
- package/src/schemas/auth-config.schema.ts +0 -646
- package/src/services/adaptive-mfa-decision.service.spec.ts +0 -1058
- package/src/services/adaptive-mfa-decision.service.ts +0 -457
- package/src/services/auth-audit.service.spec.ts +0 -675
- package/src/services/auth-audit.service.ts +0 -558
- package/src/services/auth-challenge-helper.service.spec.ts +0 -3227
- package/src/services/auth-challenge-helper.service.ts +0 -825
- package/src/services/auth-flow-context-builder.service.ts +0 -520
- package/src/services/auth-flow-rules.ts +0 -202
- package/src/services/auth-flow-state-definitions.ts +0 -190
- package/src/services/auth-flow-state-machine.service.ts +0 -207
- package/src/services/auth-flow-state-machine.types.ts +0 -316
- package/src/services/auth.service.spec.ts +0 -4195
- package/src/services/auth.service.ts +0 -3727
- package/src/services/challenge.service.spec.ts +0 -1363
- package/src/services/challenge.service.ts +0 -696
- package/src/services/client-info.service.spec.ts +0 -572
- package/src/services/client-info.service.ts +0 -374
- package/src/services/csrf.service.ts +0 -54
- package/src/services/email-verification.service.spec.ts +0 -1229
- package/src/services/email-verification.service.ts +0 -578
- package/src/services/geo-location.service.spec.ts +0 -603
- package/src/services/geo-location.service.ts +0 -599
- package/src/services/index.ts +0 -13
- package/src/services/jwt.service.spec.ts +0 -882
- package/src/services/jwt.service.ts +0 -621
- package/src/services/mfa-base.service.spec.ts +0 -246
- package/src/services/mfa-base.service.ts +0 -611
- package/src/services/mfa.service.spec.ts +0 -693
- package/src/services/mfa.service.ts +0 -960
- package/src/services/password.service.spec.ts +0 -166
- package/src/services/password.service.ts +0 -309
- package/src/services/phone-verification.service.spec.ts +0 -1120
- package/src/services/phone-verification.service.ts +0 -751
- package/src/services/risk-detection.service.spec.ts +0 -1292
- package/src/services/risk-detection.service.ts +0 -1012
- package/src/services/risk-scoring.service.spec.ts +0 -204
- package/src/services/risk-scoring.service.ts +0 -131
- package/src/services/session.service.spec.ts +0 -1293
- package/src/services/session.service.ts +0 -803
- package/src/services/social-account.service.spec.ts +0 -725
- package/src/services/social-auth-base.service.spec.ts +0 -418
- package/src/services/social-auth-base.service.ts +0 -581
- package/src/services/social-auth.service.spec.ts +0 -238
- package/src/services/social-auth.service.ts +0 -436
- package/src/services/social-provider-registry.service.spec.ts +0 -238
- package/src/services/social-provider-registry.service.ts +0 -122
- package/src/services/trusted-device.service.spec.ts +0 -505
- package/src/services/trusted-device.service.ts +0 -339
- package/src/storage/account-lockout-storage.service.spec.ts +0 -310
- package/src/storage/account-lockout-storage.service.ts +0 -89
- package/src/storage/index.ts +0 -3
- package/src/storage/memory-storage.adapter.ts +0 -443
- package/src/storage/rate-limit-storage.service.spec.ts +0 -247
- package/src/storage/rate-limit-storage.service.ts +0 -38
- package/src/templates/html-template.engine.spec.ts +0 -161
- package/src/templates/html-template.engine.ts +0 -688
- package/src/templates/index.ts +0 -7
- package/src/utils/common-passwords.spec.ts +0 -230
- package/src/utils/common-passwords.ts +0 -170
- package/src/utils/context-storage.ts +0 -188
- package/src/utils/cookie-names.util.ts +0 -67
- package/src/utils/cookies.util.ts +0 -94
- package/src/utils/index.ts +0 -12
- package/src/utils/ip-extractor.spec.ts +0 -330
- package/src/utils/ip-extractor.ts +0 -220
- package/src/utils/nauth-logger.spec.ts +0 -388
- package/src/utils/nauth-logger.ts +0 -215
- package/src/utils/pii-redactor.spec.ts +0 -130
- package/src/utils/pii-redactor.ts +0 -288
- package/src/utils/setup/get-repositories.ts +0 -140
- package/src/utils/setup/init-services.ts +0 -422
- package/src/utils/setup/init-social.ts +0 -189
- package/src/utils/setup/init-storage.ts +0 -94
- package/src/utils/setup/register-mfa.ts +0 -165
- package/src/utils/setup/run-nauth-migrations.ts +0 -61
- package/src/utils/token-delivery-policy.ts +0 -38
- package/src/validators/template.validator.ts +0 -219
- package/tsconfig.json +0 -37
- package/tsconfig.lint.json +0 -6
|
@@ -1,688 +0,0 @@
|
|
|
1
|
-
import { TemplateEngine, TemplateType, TemplateVariables, EmailTemplate } from '../interfaces/template.interface';
|
|
2
|
-
import { NAuthException } from '../exceptions/nauth.exception';
|
|
3
|
-
import { AuthErrorCode } from '../enums/error-codes.enum';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* HTML Template Engine
|
|
7
|
-
*
|
|
8
|
-
* Simple yet powerful template engine for email templates using HTML with placeholder tokens.
|
|
9
|
-
* Supports {{variable}} syntax for variable injection.
|
|
10
|
-
*
|
|
11
|
-
* Features:
|
|
12
|
-
* - Simple {{variable}} placeholder syntax
|
|
13
|
-
* - Built-in default templates for all email types
|
|
14
|
-
* - Custom template registration
|
|
15
|
-
* - Automatic HTML entity escaping for security
|
|
16
|
-
* - Plain text generation from HTML
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* const engine = new HtmlTemplateEngine();
|
|
21
|
-
* const result = await engine.render(
|
|
22
|
-
* TemplateType.VERIFICATION,
|
|
23
|
-
* { userName: 'John', code: '123456', expiryMinutes: 60 }
|
|
24
|
-
* );
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
export class HtmlTemplateEngine implements TemplateEngine {
|
|
28
|
-
/**
|
|
29
|
-
* Storage for registered templates
|
|
30
|
-
* Maps template type to template definition
|
|
31
|
-
*/
|
|
32
|
-
private templates: Map<string, EmailTemplate> = new Map();
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Constructor
|
|
36
|
-
* Initializes the engine with default templates
|
|
37
|
-
*/
|
|
38
|
-
constructor() {
|
|
39
|
-
this.registerDefaultTemplates();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Render a template with variables
|
|
44
|
-
*
|
|
45
|
-
* Replaces all {{variable}} placeholders with actual values.
|
|
46
|
-
* Variables are HTML-escaped for security.
|
|
47
|
-
* Handles firstName/username fallback for greetings.
|
|
48
|
-
*
|
|
49
|
-
* @param type - Template type to render
|
|
50
|
-
* @param variables - Variables to inject
|
|
51
|
-
* @returns Rendered email template
|
|
52
|
-
* @throws {Error} If template type not found
|
|
53
|
-
*/
|
|
54
|
-
async render(type: TemplateType | string, variables: TemplateVariables): Promise<EmailTemplate> {
|
|
55
|
-
const template = this.templates.get(type);
|
|
56
|
-
|
|
57
|
-
if (!template) {
|
|
58
|
-
throw new NAuthException(
|
|
59
|
-
AuthErrorCode.INTERNAL_ERROR,
|
|
60
|
-
`Template "${type}" not found. Available templates: ${Array.from(this.templates.keys()).join(', ')}`,
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Merge with default variables and add greeting name
|
|
65
|
-
const allVariables: TemplateVariables = {
|
|
66
|
-
currentYear: new Date().getFullYear(),
|
|
67
|
-
...variables,
|
|
68
|
-
greetingName: this.getGreetingName(variables),
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
// Render subject and HTML
|
|
72
|
-
const subject = this.replaceVariables(template.subject, allVariables);
|
|
73
|
-
const html = this.replaceVariables(template.html, allVariables);
|
|
74
|
-
|
|
75
|
-
// Generate plain text if not provided
|
|
76
|
-
const text = template.text ? this.replaceVariablesForText(template.text, allVariables) : this.htmlToText(html);
|
|
77
|
-
|
|
78
|
-
return { subject, html, text };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Register a custom template
|
|
83
|
-
*
|
|
84
|
-
* @param type - Template type identifier
|
|
85
|
-
* @param template - Template definition
|
|
86
|
-
*/
|
|
87
|
-
registerTemplate(type: TemplateType | string, template: EmailTemplate): void {
|
|
88
|
-
this.templates.set(type, template);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Get all available template types
|
|
93
|
-
*
|
|
94
|
-
* @returns Array of template type identifiers
|
|
95
|
-
*/
|
|
96
|
-
getAvailableTemplates(): string[] {
|
|
97
|
-
return Array.from(this.templates.keys());
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Check if a template exists
|
|
102
|
-
*
|
|
103
|
-
* @param type - Template type to check
|
|
104
|
-
* @returns True if template is registered
|
|
105
|
-
*/
|
|
106
|
-
hasTemplate(type: TemplateType | string): boolean {
|
|
107
|
-
return this.templates.has(type);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Replace {{variable}} placeholders with values
|
|
112
|
-
*
|
|
113
|
-
* Escapes HTML entities in variables for security.
|
|
114
|
-
* Handles missing variables gracefully (replaces with empty string).
|
|
115
|
-
* Supports firstName/username fallback logic and simple conditionals.
|
|
116
|
-
*
|
|
117
|
-
* @param template - Template string with {{placeholders}}
|
|
118
|
-
* @param variables - Variables to inject
|
|
119
|
-
* @returns Template with variables replaced
|
|
120
|
-
* @private
|
|
121
|
-
*/
|
|
122
|
-
private replaceVariables(template: string, variables: TemplateVariables): string {
|
|
123
|
-
let result = template;
|
|
124
|
-
|
|
125
|
-
// Handle simple conditionals like {{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
126
|
-
result = result.replace(
|
|
127
|
-
/\{\{#if (\w+)\}\}(.*?)\{\{else\}\}(.*?)\{\{\/if\}\}/g,
|
|
128
|
-
(_match, key, ifContent, elseContent) => {
|
|
129
|
-
const value = variables[key];
|
|
130
|
-
if (value && value !== '') {
|
|
131
|
-
return ifContent;
|
|
132
|
-
} else {
|
|
133
|
-
return elseContent;
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
// Replace regular variables
|
|
139
|
-
result = result.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
140
|
-
const value = variables[key];
|
|
141
|
-
|
|
142
|
-
// Return empty string if variable is undefined
|
|
143
|
-
if (value === undefined || value === null) {
|
|
144
|
-
return '';
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Convert to string and escape HTML entities
|
|
148
|
-
return this.escapeHtml(String(value));
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
return result;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Replace {{variable}} placeholders with values for text content
|
|
156
|
-
*
|
|
157
|
-
* Similar to replaceVariables but doesn't escape HTML entities for plain text.
|
|
158
|
-
*
|
|
159
|
-
* @param template - Template string with {{placeholders}}
|
|
160
|
-
* @param variables - Variables to inject
|
|
161
|
-
* @returns Template with variables replaced
|
|
162
|
-
* @private
|
|
163
|
-
*/
|
|
164
|
-
private replaceVariablesForText(template: string, variables: TemplateVariables): string {
|
|
165
|
-
let result = template;
|
|
166
|
-
|
|
167
|
-
// Handle simple conditionals like {{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
168
|
-
result = result.replace(
|
|
169
|
-
/\{\{#if (\w+)\}\}(.*?)\{\{else\}\}(.*?)\{\{\/if\}\}/g,
|
|
170
|
-
(_match, key, ifContent, elseContent) => {
|
|
171
|
-
const value = variables[key];
|
|
172
|
-
if (value && value !== '') {
|
|
173
|
-
return ifContent;
|
|
174
|
-
} else {
|
|
175
|
-
return elseContent;
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
// Replace regular variables without HTML escaping
|
|
181
|
-
result = result.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
182
|
-
const value = variables[key];
|
|
183
|
-
|
|
184
|
-
// Return empty string if variable is undefined
|
|
185
|
-
if (value === undefined || value === null) {
|
|
186
|
-
return '';
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Convert to string without escaping HTML entities for text
|
|
190
|
-
return String(value);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
return result;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Get greeting name with firstName/username fallback logic
|
|
198
|
-
*
|
|
199
|
-
* @param variables - Template variables
|
|
200
|
-
* @returns Greeting name or empty string
|
|
201
|
-
* @private
|
|
202
|
-
*/
|
|
203
|
-
private getGreetingName(variables: TemplateVariables): string {
|
|
204
|
-
if (variables.firstName) {
|
|
205
|
-
return variables.firstName;
|
|
206
|
-
}
|
|
207
|
-
if (variables.userName) {
|
|
208
|
-
return variables.userName;
|
|
209
|
-
}
|
|
210
|
-
return '';
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Escape HTML entities to prevent XSS
|
|
215
|
-
*
|
|
216
|
-
* @param text - Text to escape
|
|
217
|
-
* @returns HTML-safe text
|
|
218
|
-
* @private
|
|
219
|
-
*/
|
|
220
|
-
private escapeHtml(text: string): string {
|
|
221
|
-
const map: Record<string, string> = {
|
|
222
|
-
'&': '&',
|
|
223
|
-
'<': '<',
|
|
224
|
-
'>': '>',
|
|
225
|
-
'"': '"',
|
|
226
|
-
"'": ''',
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
return text.replace(/[&<>"']/g, (char) => map[char] || char);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Convert HTML to plain text
|
|
234
|
-
*
|
|
235
|
-
* Simple conversion: strips HTML tags and decodes entities.
|
|
236
|
-
*
|
|
237
|
-
* @param html - HTML content
|
|
238
|
-
* @returns Plain text
|
|
239
|
-
* @private
|
|
240
|
-
*/
|
|
241
|
-
private htmlToText(html: string): string {
|
|
242
|
-
// Strip HTML tags
|
|
243
|
-
let text = html.replace(/<[^>]*>/g, '');
|
|
244
|
-
|
|
245
|
-
// Decode common HTML entities
|
|
246
|
-
text = text.replace(/ /g, ' ');
|
|
247
|
-
text = text.replace(/</g, '<');
|
|
248
|
-
text = text.replace(/>/g, '>');
|
|
249
|
-
text = text.replace(/"/g, '"');
|
|
250
|
-
text = text.replace(/'/g, "'");
|
|
251
|
-
text = text.replace(/&/g, '&');
|
|
252
|
-
|
|
253
|
-
// Normalize whitespace
|
|
254
|
-
text = text.replace(/\s+/g, ' ').trim();
|
|
255
|
-
|
|
256
|
-
return text;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Register default templates for all email types
|
|
261
|
-
*
|
|
262
|
-
* These templates can be overridden using registerTemplate().
|
|
263
|
-
* @private
|
|
264
|
-
*/
|
|
265
|
-
private registerDefaultTemplates(): void {
|
|
266
|
-
// ============================================================================
|
|
267
|
-
// Email Verification Template
|
|
268
|
-
// ============================================================================
|
|
269
|
-
this.registerTemplate(TemplateType.VERIFICATION, {
|
|
270
|
-
subject: 'Email Verification - {{appName}}',
|
|
271
|
-
html: `
|
|
272
|
-
<!DOCTYPE html>
|
|
273
|
-
<html>
|
|
274
|
-
<head>
|
|
275
|
-
<meta charset="UTF-8">
|
|
276
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
277
|
-
<title>Email Verification</title>
|
|
278
|
-
<style>
|
|
279
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
280
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
281
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
282
|
-
p { margin: 0 0 15px 0; }
|
|
283
|
-
.code { font-size: 24px; font-weight: bold; letter-spacing: 3px; margin: 20px 0; }
|
|
284
|
-
</style>
|
|
285
|
-
</head>
|
|
286
|
-
<body>
|
|
287
|
-
<div class="container">
|
|
288
|
-
<h1>Email Verification</h1>
|
|
289
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
290
|
-
<p>Thank you for signing up! Please verify your email address to activate your account.</p>
|
|
291
|
-
|
|
292
|
-
<p>Your Verification Code:</p>
|
|
293
|
-
<div class="code">{{code}}</div>
|
|
294
|
-
|
|
295
|
-
<p>Or click the link below to verify:</p>
|
|
296
|
-
<p><a href="{{link}}">Verify Email Address</a></p>
|
|
297
|
-
|
|
298
|
-
<p>This code expires in {{expiryMinutes}} minutes.</p>
|
|
299
|
-
<p>If you didn't request this verification, please ignore this email.</p>
|
|
300
|
-
</div>
|
|
301
|
-
</body>
|
|
302
|
-
</html>
|
|
303
|
-
`,
|
|
304
|
-
text: `
|
|
305
|
-
Email Verification
|
|
306
|
-
|
|
307
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
308
|
-
|
|
309
|
-
Thank you for signing up! Please verify your email address to activate your account.
|
|
310
|
-
|
|
311
|
-
Your Verification Code: {{code}}
|
|
312
|
-
|
|
313
|
-
Or use this link: {{link}}
|
|
314
|
-
|
|
315
|
-
This code expires in {{expiryMinutes}} minutes.
|
|
316
|
-
|
|
317
|
-
If you didn't request this verification, please ignore this email.
|
|
318
|
-
`,
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
// ============================================================================
|
|
322
|
-
// Password Reset Template
|
|
323
|
-
// ============================================================================
|
|
324
|
-
this.registerTemplate(TemplateType.PASSWORD_RESET, {
|
|
325
|
-
subject: 'Password Reset - {{appName}}',
|
|
326
|
-
html: `
|
|
327
|
-
<!DOCTYPE html>
|
|
328
|
-
<html>
|
|
329
|
-
<head>
|
|
330
|
-
<meta charset="UTF-8">
|
|
331
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
332
|
-
<title>Password Reset</title>
|
|
333
|
-
<style>
|
|
334
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
335
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
336
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
337
|
-
p { margin: 0 0 15px 0; }
|
|
338
|
-
</style>
|
|
339
|
-
</head>
|
|
340
|
-
<body>
|
|
341
|
-
<div class="container">
|
|
342
|
-
<h1>Password Reset</h1>
|
|
343
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
344
|
-
<p>We received a request to reset your password. Click the link below to create a new password:</p>
|
|
345
|
-
|
|
346
|
-
<p><a href="{{link}}">Reset Your Password</a></p>
|
|
347
|
-
|
|
348
|
-
<p>This link expires in {{expiryMinutes}} minutes.</p>
|
|
349
|
-
<p>If you didn't request a password reset, your account is secure and you can ignore this email.</p>
|
|
350
|
-
|
|
351
|
-
<p>If the link doesn't work, copy and paste this URL into your browser:</p>
|
|
352
|
-
<p>{{link}}</p>
|
|
353
|
-
</div>
|
|
354
|
-
</body>
|
|
355
|
-
</html>
|
|
356
|
-
`,
|
|
357
|
-
text: `
|
|
358
|
-
Password Reset
|
|
359
|
-
|
|
360
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
361
|
-
|
|
362
|
-
We received a request to reset your password. Use the link below to create a new password:
|
|
363
|
-
|
|
364
|
-
{{link}}
|
|
365
|
-
|
|
366
|
-
This link expires in {{expiryMinutes}} minutes.
|
|
367
|
-
|
|
368
|
-
If you didn't request a password reset, your account is secure and you can ignore this email.
|
|
369
|
-
`,
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
// ============================================================================
|
|
373
|
-
// Welcome Email Template
|
|
374
|
-
// ============================================================================
|
|
375
|
-
this.registerTemplate(TemplateType.WELCOME, {
|
|
376
|
-
subject: 'Welcome to {{appName}}!',
|
|
377
|
-
html: `
|
|
378
|
-
<!DOCTYPE html>
|
|
379
|
-
<html>
|
|
380
|
-
<head>
|
|
381
|
-
<meta charset="UTF-8">
|
|
382
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
383
|
-
<title>Welcome</title>
|
|
384
|
-
<style>
|
|
385
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
386
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
387
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
388
|
-
p { margin: 0 0 15px 0; }
|
|
389
|
-
</style>
|
|
390
|
-
</head>
|
|
391
|
-
<body>
|
|
392
|
-
<div class="container">
|
|
393
|
-
<h1>Welcome</h1>
|
|
394
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
395
|
-
<p>We're excited to have you with us! Your account has been successfully created and you're ready to get started.</p>
|
|
396
|
-
|
|
397
|
-
<p><a href="{{dashboardUrl}}">Get Started</a></p>
|
|
398
|
-
|
|
399
|
-
<p>If you have any questions or need assistance, feel free to reach out to our support team at {{supportEmail}}.</p>
|
|
400
|
-
|
|
401
|
-
<p>Happy exploring!</p>
|
|
402
|
-
</div>
|
|
403
|
-
</body>
|
|
404
|
-
</html>
|
|
405
|
-
`,
|
|
406
|
-
text: `
|
|
407
|
-
Welcome to {{appName}}!
|
|
408
|
-
|
|
409
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
410
|
-
|
|
411
|
-
We're excited to have you with us! Your account has been successfully created and you're ready to get started.
|
|
412
|
-
|
|
413
|
-
Visit: {{dashboardUrl}}
|
|
414
|
-
|
|
415
|
-
If you have any questions or need assistance, reach out to our support team at {{supportEmail}}.
|
|
416
|
-
|
|
417
|
-
Happy exploring!
|
|
418
|
-
`,
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
// ============================================================================
|
|
422
|
-
// Account Lockout Template
|
|
423
|
-
// ============================================================================
|
|
424
|
-
this.registerTemplate(TemplateType.ACCOUNT_LOCKOUT, {
|
|
425
|
-
subject: 'Account Locked - {{appName}}',
|
|
426
|
-
html: `
|
|
427
|
-
<!DOCTYPE html>
|
|
428
|
-
<html>
|
|
429
|
-
<head>
|
|
430
|
-
<meta charset="UTF-8">
|
|
431
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
432
|
-
<title>Account Lockout</title>
|
|
433
|
-
<style>
|
|
434
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
435
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
436
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
437
|
-
p { margin: 0 0 15px 0; }
|
|
438
|
-
ul { margin: 0 0 15px 0; }
|
|
439
|
-
</style>
|
|
440
|
-
</head>
|
|
441
|
-
<body>
|
|
442
|
-
<div class="container">
|
|
443
|
-
<h1>Account Locked</h1>
|
|
444
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
445
|
-
<p>Your account has been temporarily locked for security reasons.</p>
|
|
446
|
-
|
|
447
|
-
<p><strong>Reason:</strong> {{reason}}</p>
|
|
448
|
-
<p><strong>Duration:</strong> Your account will be automatically unlocked in {{durationMinutes}} minutes.</p>
|
|
449
|
-
|
|
450
|
-
<p><strong>What happened?</strong></p>
|
|
451
|
-
<p>We detected multiple failed login attempts or suspicious activity on your account. As a security measure, we've temporarily locked your account to protect it.</p>
|
|
452
|
-
|
|
453
|
-
<p><strong>What should I do?</strong></p>
|
|
454
|
-
<ul>
|
|
455
|
-
<li>Wait {{durationMinutes}} minutes for automatic unlock</li>
|
|
456
|
-
<li>If this was you, try logging in again after the lockout period</li>
|
|
457
|
-
<li>If this wasn't you, please contact support immediately at {{supportEmail}}</li>
|
|
458
|
-
<li>Consider changing your password after unlock</li>
|
|
459
|
-
</ul>
|
|
460
|
-
</div>
|
|
461
|
-
</body>
|
|
462
|
-
</html>
|
|
463
|
-
`,
|
|
464
|
-
text: `
|
|
465
|
-
Account Locked
|
|
466
|
-
|
|
467
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
468
|
-
|
|
469
|
-
Your account has been temporarily locked for security reasons.
|
|
470
|
-
|
|
471
|
-
Reason: {{reason}}
|
|
472
|
-
Duration: Your account will be automatically unlocked in {{durationMinutes}} minutes.
|
|
473
|
-
|
|
474
|
-
What happened?
|
|
475
|
-
We detected multiple failed login attempts or suspicious activity on your account.
|
|
476
|
-
|
|
477
|
-
What should I do?
|
|
478
|
-
- Wait {{durationMinutes}} minutes for automatic unlock
|
|
479
|
-
- If this was you, try logging in again after the lockout period
|
|
480
|
-
- If this wasn't you, contact support at {{supportEmail}}
|
|
481
|
-
- Consider changing your password after unlock
|
|
482
|
-
`,
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
// ============================================================================
|
|
486
|
-
// New Device Login Template
|
|
487
|
-
// ============================================================================
|
|
488
|
-
this.registerTemplate(TemplateType.NEW_DEVICE, {
|
|
489
|
-
subject: 'New Device Login - {{appName}}',
|
|
490
|
-
html: `
|
|
491
|
-
<!DOCTYPE html>
|
|
492
|
-
<html>
|
|
493
|
-
<head>
|
|
494
|
-
<meta charset="UTF-8">
|
|
495
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
496
|
-
<title>New Device Login</title>
|
|
497
|
-
<style>
|
|
498
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
499
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
500
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
501
|
-
p { margin: 0 0 15px 0; }
|
|
502
|
-
ul { margin: 0 0 15px 0; }
|
|
503
|
-
</style>
|
|
504
|
-
</head>
|
|
505
|
-
<body>
|
|
506
|
-
<div class="container">
|
|
507
|
-
<h1>New Device Login</h1>
|
|
508
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
509
|
-
<p>We detected a login to your account from a new device.</p>
|
|
510
|
-
|
|
511
|
-
<p><strong>Device:</strong> {{deviceName}}</p>
|
|
512
|
-
<p><strong>Type:</strong> {{deviceType}}</p>
|
|
513
|
-
<p><strong>IP Address:</strong> {{ipAddress}}</p>
|
|
514
|
-
<p><strong>Location:</strong> {{location}}</p>
|
|
515
|
-
<p><strong>Time:</strong> {{timestamp}}</p>
|
|
516
|
-
|
|
517
|
-
<p><strong>Was this you?</strong></p>
|
|
518
|
-
<p>If you recognize this login, no action is needed. Your account is secure.</p>
|
|
519
|
-
|
|
520
|
-
<p><strong>Not you?</strong></p>
|
|
521
|
-
<p>If you don't recognize this activity, please secure your account immediately:</p>
|
|
522
|
-
<ul>
|
|
523
|
-
<li>Change your password</li>
|
|
524
|
-
<li>Review your recent account activity</li>
|
|
525
|
-
<li>Contact support at {{supportEmail}}</li>
|
|
526
|
-
</ul>
|
|
527
|
-
</div>
|
|
528
|
-
</body>
|
|
529
|
-
</html>
|
|
530
|
-
`,
|
|
531
|
-
text: `
|
|
532
|
-
New Device Login
|
|
533
|
-
|
|
534
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
535
|
-
|
|
536
|
-
We detected a login to your account from a new device.
|
|
537
|
-
|
|
538
|
-
Device: {{deviceName}}
|
|
539
|
-
Type: {{deviceType}}
|
|
540
|
-
IP Address: {{ipAddress}}
|
|
541
|
-
Location: {{location}}
|
|
542
|
-
Time: {{timestamp}}
|
|
543
|
-
|
|
544
|
-
Was this you?
|
|
545
|
-
If you recognize this login, no action is needed.
|
|
546
|
-
|
|
547
|
-
Not you?
|
|
548
|
-
If you don't recognize this activity, secure your account immediately:
|
|
549
|
-
- Change your password
|
|
550
|
-
- Review your recent account activity
|
|
551
|
-
- Contact support at {{supportEmail}}
|
|
552
|
-
`,
|
|
553
|
-
});
|
|
554
|
-
// Password Changed Template
|
|
555
|
-
// ============================================================================
|
|
556
|
-
this.registerTemplate(TemplateType.PASSWORD_CHANGED, {
|
|
557
|
-
subject: 'Password Changed - {{appName}}',
|
|
558
|
-
html: `
|
|
559
|
-
<!DOCTYPE html>
|
|
560
|
-
<html>
|
|
561
|
-
<head>
|
|
562
|
-
<meta charset="UTF-8">
|
|
563
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
564
|
-
<title>Password Changed</title>
|
|
565
|
-
<style>
|
|
566
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
567
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
568
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
569
|
-
p { margin: 0 0 15px 0; }
|
|
570
|
-
</style>
|
|
571
|
-
</head>
|
|
572
|
-
<body>
|
|
573
|
-
<div class="container">
|
|
574
|
-
<h1>Password Changed</h1>
|
|
575
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
576
|
-
<p>Your password has been successfully changed.</p>
|
|
577
|
-
|
|
578
|
-
<p>If you made this change, no further action is required.</p>
|
|
579
|
-
|
|
580
|
-
<p>If you didn't make this change, please contact support immediately at {{supportEmail}}.</p>
|
|
581
|
-
</div>
|
|
582
|
-
</body>
|
|
583
|
-
</html>
|
|
584
|
-
`,
|
|
585
|
-
text: `
|
|
586
|
-
Password Changed
|
|
587
|
-
|
|
588
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
589
|
-
|
|
590
|
-
Your password has been successfully changed.
|
|
591
|
-
|
|
592
|
-
If you made this change, no further action is required.
|
|
593
|
-
|
|
594
|
-
If you didn't make this change, please contact support immediately at {{supportEmail}}.
|
|
595
|
-
`,
|
|
596
|
-
});
|
|
597
|
-
|
|
598
|
-
// ============================================================================
|
|
599
|
-
// Email Changed Template
|
|
600
|
-
// ============================================================================
|
|
601
|
-
this.registerTemplate(TemplateType.EMAIL_CHANGED, {
|
|
602
|
-
subject: 'Email Address Changed - {{appName}}',
|
|
603
|
-
html: `
|
|
604
|
-
<!DOCTYPE html>
|
|
605
|
-
<html>
|
|
606
|
-
<head>
|
|
607
|
-
<meta charset="UTF-8">
|
|
608
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
609
|
-
<title>Email Changed</title>
|
|
610
|
-
<style>
|
|
611
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
612
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
613
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
614
|
-
p { margin: 0 0 15px 0; }
|
|
615
|
-
</style>
|
|
616
|
-
</head>
|
|
617
|
-
<body>
|
|
618
|
-
<div class="container">
|
|
619
|
-
<h1>Email Address Changed</h1>
|
|
620
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
621
|
-
<p>Your email address has been successfully changed to {{userEmail}}.</p>
|
|
622
|
-
|
|
623
|
-
<p>If you made this change, no further action is required.</p>
|
|
624
|
-
|
|
625
|
-
<p>If you didn't make this change, please contact support immediately at {{supportEmail}}.</p>
|
|
626
|
-
</div>
|
|
627
|
-
</body>
|
|
628
|
-
</html>
|
|
629
|
-
`,
|
|
630
|
-
text: `
|
|
631
|
-
Email Address Changed
|
|
632
|
-
|
|
633
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
634
|
-
|
|
635
|
-
Your email address has been successfully changed to {{userEmail}}.
|
|
636
|
-
|
|
637
|
-
If you made this change, no further action is required.
|
|
638
|
-
|
|
639
|
-
If you didn't make this change, please contact support immediately at {{supportEmail}}.
|
|
640
|
-
`,
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
// ============================================================================
|
|
644
|
-
// MFA Enabled Template
|
|
645
|
-
// ============================================================================
|
|
646
|
-
this.registerTemplate(TemplateType.MFA_ENABLED, {
|
|
647
|
-
subject: 'Two-Factor Authentication Enabled - {{appName}}',
|
|
648
|
-
html: `
|
|
649
|
-
<!DOCTYPE html>
|
|
650
|
-
<html>
|
|
651
|
-
<head>
|
|
652
|
-
<meta charset="UTF-8">
|
|
653
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
654
|
-
<title>MFA Enabled</title>
|
|
655
|
-
<style>
|
|
656
|
-
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 20px; }
|
|
657
|
-
.container { max-width: 600px; margin: 0 auto; }
|
|
658
|
-
h1 { font-size: 24px; margin: 0 0 20px 0; }
|
|
659
|
-
p { margin: 0 0 15px 0; }
|
|
660
|
-
</style>
|
|
661
|
-
</head>
|
|
662
|
-
<body>
|
|
663
|
-
<div class="container">
|
|
664
|
-
<h1>Two-Factor Authentication Enabled</h1>
|
|
665
|
-
<p>{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}</p>
|
|
666
|
-
<p>Two-factor authentication has been successfully enabled for your account.</p>
|
|
667
|
-
|
|
668
|
-
<p>Your account is now more secure. You'll need to provide both your password and a verification code when logging in.</p>
|
|
669
|
-
|
|
670
|
-
<p>If you didn't enable this feature, please contact support immediately at {{supportEmail}}.</p>
|
|
671
|
-
</div>
|
|
672
|
-
</body>
|
|
673
|
-
</html>
|
|
674
|
-
`,
|
|
675
|
-
text: `
|
|
676
|
-
Two-Factor Authentication Enabled
|
|
677
|
-
|
|
678
|
-
{{#if greetingName}}Hi {{greetingName}},{{else}}Hi,{{/if}}
|
|
679
|
-
|
|
680
|
-
Two-factor authentication has been successfully enabled for your account.
|
|
681
|
-
|
|
682
|
-
Your account is now more secure. You'll need to provide both your password and a verification code when logging in.
|
|
683
|
-
|
|
684
|
-
If you didn't enable this feature, please contact support immediately at {{supportEmail}}.
|
|
685
|
-
`,
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
}
|