+15
scripts/clear-rate-limits.ts
+15
scripts/clear-rate-limits.ts
···+console.log(`✅ Successfully cleared ${deletedCount} rate limit attempt${deletedCount === 1 ? '' : 's'}`);
+12
-3
src/components/user-modal.ts
+12
-3
src/components/user-modal.ts
············<input type="email" id="new-email" class="form-input" placeholder="Enter new email" value=${this.user.email}>+<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer; font-size: 0.875rem;">
+50
-5
src/components/user-settings.ts
+50
-5
src/components/user-settings.ts
············+${this.pendingEmailChange ? html`<br><strong>New email:</strong> ${this.pendingEmailChange}` : ''}······
+19
src/db/schema.ts
+19
src/db/schema.ts
···
+80
-12
src/index.ts
+80
-12
src/index.ts
···············
+38
src/lib/auth.ts
+38
src/lib/auth.ts
···+"INSERT INTO email_change_tokens (id, user_id, new_email, token, expires_at) VALUES (?, ?, ?, ?, ?)",+export function verifyEmailChangeToken(token: string): { userId: number; newEmail: string } | null {
+96
src/lib/email-change.test.ts
+96
src/lib/email-change.test.ts
···+const user = await createUser(`test-email-change-${timestamp}@example.com`, "password123", "Test User");+const user = await createUser(`test-expire-${timestamp}@example.com`, "password123", "Test User");+const user = await createUser(`test-single-token-${timestamp}@example.com`, "password123", "Test User");
+61
src/lib/email-templates.ts
+61
src/lib/email-templates.ts
···+<a href="${options.verifyLink}" class="button" style="display: inline-block; background-color: #ef8354; color: #ffffff; text-decoration: none; padding: 0.75rem 1.5rem; border-radius: 6px; font-weight: 500; font-size: 1rem; margin: 0; border: 2px solid #ef8354;">Verify Email Change</a>+<a href="${options.verifyLink}" style="color: #4f5d75; word-break: break-all;">${options.verifyLink}</a>+<p>If you didn't request this change, please ignore this email and your email address will remain unchanged.</p>