// middleware/projectAuth.js const httpStatus = require("http-status"); const supabase = require("../config/supabaseClient"); const AppError = require("../errors/AppError"); const catchAsync = require("../utils/catchAsync"); const { verifyToken } = require("../utils/jwt"); const projectCustomerAuth = () => { return catchAsync(async (req, res, next) => { const token = req.headers.authorization?.split(" ")[1]; if (!token) { throw new AppError(httpStatus.UNAUTHORIZED, "Access token required"); } try { const decoded = verifyToken(token); if (decoded.type !== "project_member") { throw new AppError(httpStatus.UNAUTHORIZED, "Invalid token type"); } const { userId, projectId } = decoded; const { data: user, error: userError } = await supabase .from("users") .select("*") .eq("id", userId) .single(); if (userError || !user) { throw new AppError(httpStatus.UNAUTHORIZED, "User not found"); } const { data: project, error: projectError } = await supabase .from("projects") .select("*") .eq("id", projectId) .eq("is_published", true) .single(); if (projectError || !project) { throw new AppError( httpStatus.NOT_FOUND, "Project not found or not available" ); } const { data: membership, error: memberError } = await supabase .from("project_members") .select("*") .eq("project_id", projectId) .eq("user_id", userId) .single(); if (memberError || !membership) { throw new AppError( httpStatus.FORBIDDEN, "Not a member of this project" ); } if (!user.is_verified) { throw new AppError(httpStatus.FORBIDDEN, "Email not verified"); } if (user.status !== "active") { throw new AppError(httpStatus.FORBIDDEN, "Account not active"); } req.user = { userId: user.id, email: user.email, name: user.name, role: user.role, projectId: projectId, projectRole: membership.role, }; req.project = { id: project.id, name: project.name, domain: project.domain, subdomain: project.subdomain, }; next(); } catch (error) { if (error instanceof AppError) { throw error; } throw new AppError(httpStatus.UNAUTHORIZED, "Invalid token"); } }); }; module.exports = { projectCustomerAuth, };