const express = require("express"); const { AlphaInvitation, User } = require("../models"); const { authenticateToken, optionalAuth } = require("../middleware/auth"); const { alphaCodeValidationLimiter } = require("../middleware/rateLimiter"); const logger = require("../utils/logger"); const crypto = require("crypto"); const router = express.Router(); // Helper function to check if user has alpha access async function checkAlphaAccess(req) { // Bypass alpha access check if feature is disabled if (process.env.ALPHA_TESTING_ENABLED !== 'true') { return true; } // Check 1: Valid alpha access cookie if (req.cookies && req.cookies.alphaAccessCode) { const { code } = req.cookies.alphaAccessCode; const invitation = await AlphaInvitation.findOne({ where: { code, status: ["pending", "active"] }, }); if (invitation) { return true; } } // Check 2: Authenticated user who has used an invitation if (req.user && req.user.id) { const invitation = await AlphaInvitation.findOne({ where: { usedBy: req.user.id }, }); if (invitation) { return true; } } return false; } /** * POST /api/alpha/validate-code * Validates an alpha invitation code and grants access */ router.post("/validate-code", alphaCodeValidationLimiter, async (req, res) => { try { const { code } = req.body; if (!code) { return res.status(400).json({ error: "Code is required", }); } // Normalize code (uppercase, trim) const normalizedCode = code.trim().toUpperCase(); // Validate code format if (!/^ALPHA-[A-Z0-9]{8}$/.test(normalizedCode)) { logger.warn(`Invalid code format attempted: ${code}`); return res.status(400).json({ error: "Invalid alpha code", }); } // Find invitation in database const invitation = await AlphaInvitation.findOne({ where: { code: normalizedCode }, }); // Generic error for invalid code (prevent enumeration) if (!invitation) { logger.warn(`Code not found: ${normalizedCode}`); return res.status(400).json({ error: "Invalid alpha code", }); } // Check if code is revoked if (invitation.status === "revoked") { logger.warn(`Revoked code attempted: ${normalizedCode}`); return res.status(400).json({ error: "Invalid alpha code", }); } // Set httpOnly cookie for alpha access const cookieData = { code: normalizedCode, validatedAt: new Date().toISOString(), }; res.cookie("alphaAccessCode", cookieData, { httpOnly: true, secure: ["production", "prod", "qa"].includes(process.env.NODE_ENV), sameSite: "strict", maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days }); logger.info(`Alpha code validated successfully: ${normalizedCode}`); res.json({ success: true, message: "Access granted", }); } catch (error) { logger.error(`Error validating alpha code: ${error.message}`, { error }); res.status(500).json({ error: "Server error", }); } }); /** * GET /api/alpha/verify-session * Checks if current session has alpha access */ router.get("/verify-session", optionalAuth, async (req, res) => { try { const hasAccess = await checkAlphaAccess(req); res.json({ hasAccess, }); } catch (error) { logger.error(`Error verifying alpha session: ${error.message}`, { error }); res.status(500).json({ error: "Server error", }); } }); module.exports = { router, checkAlphaAccess };