- Create packages/emails/ with EmailClient interface abstraction - Wrap Postmark ServerClient in adapter for clean typing - Add createLoggingEmailClient for dev mode (logs to console) - Split email templates into individual files with full test coverage - Update api-server to use new package via context injection - Remove EMAIL_DEV_MODE - now uses POSTMARK_API_KEY presence - Delete apps/api-server/src/utils/email.ts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
/**
|
|
* Resend email verification to authenticated user
|
|
* Requires authentication
|
|
*
|
|
* Flow:
|
|
* 1. Check if email is already verified (return early if so)
|
|
* 2. Delete any existing verification tokens for this user
|
|
* 3. Generate new secure base58 token
|
|
* 4. Create new email_verifications record with 24 hour expiry
|
|
* 5. Send verification email (stubbed)
|
|
*/
|
|
|
|
import { sendVerificationEmail } from "@reviq/emails";
|
|
import { TOKEN_DURATIONS } from "../../utils/cookies.js";
|
|
import {
|
|
generateExpiry,
|
|
generateSecureBase58Token,
|
|
} from "../../utils/crypto.js";
|
|
import { authMiddleware, os } from "../base.js";
|
|
|
|
export const resendVerificationEmail = os.auth.resendVerificationEmail
|
|
.use(authMiddleware)
|
|
.handler(async ({ context }) => {
|
|
// Check if email is already verified
|
|
if (context.user.emailVerifiedAt !== null) {
|
|
// Email already verified, return early
|
|
return { success: true };
|
|
}
|
|
|
|
// Delete any existing verification tokens for this user
|
|
await context.db
|
|
.deleteFrom("email_verifications")
|
|
.where("user_id", "=", context.user.id)
|
|
.execute();
|
|
|
|
// Generate new secure base58 token
|
|
const token = generateSecureBase58Token();
|
|
const expiresAt = generateExpiry(TOKEN_DURATIONS.EMAIL_VERIFICATION);
|
|
|
|
// Create new verification record
|
|
await context.db
|
|
.insertInto("email_verifications")
|
|
.values({
|
|
user_id: context.user.id,
|
|
token,
|
|
expires_at: expiresAt,
|
|
})
|
|
.execute();
|
|
|
|
// Send verification email
|
|
await sendVerificationEmail({
|
|
client: context.email.client,
|
|
fromAddress: context.email.fromAddress,
|
|
baseUrl: context.email.baseUrl,
|
|
email: context.user.email,
|
|
token,
|
|
expiryHours: 24,
|
|
});
|
|
|
|
return { success: true };
|
|
});
|