import jwt from "jsonwebtoken"; import Member from "../../models/member.js"; import { connectDB } from "../../utils/mongoose.js"; export default defineEventHandler(async (event) => { await connectDB(); // Check if user is authenticated (optional — works for public and authenticated users) const token = getCookie(event, "auth-token"); let isAuthenticated = false; if (token) { try { const decoded = jwt.verify(token, useRuntimeConfig().jwtSecret); if (decoded.memberId) { isAuthenticated = true; } } catch { // Invalid token, treat as public isAuthenticated = false; } } const id = event.context.params.id; try { const member = await Member.findOne({ _id: id, showInDirectory: true, status: "active", }) .select( "name pronouns timeZone avatar studio bio location socialLinks offering lookingFor privacy circle peerSupport createdAt", ) .lean(); if (!member) { throw createError({ statusCode: 404, message: "Member not found", }); } // Filter fields based on privacy settings const privacy = member.privacy || {}; const filtered = { _id: member._id, name: member.name, circle: member.circle, createdAt: member.createdAt, }; // Helper function to check if field should be visible const isVisible = (field) => { const privacySetting = privacy[field] || "members"; if (privacySetting === "public") return true; if (privacySetting === "members" && isAuthenticated) return true; if (privacySetting === "private") return false; return false; }; // Add fields based on privacy settings if (isVisible("avatar")) filtered.avatar = member.avatar; if (isVisible("pronouns")) filtered.pronouns = member.pronouns; if (isVisible("timeZone")) filtered.timeZone = member.timeZone; if (isVisible("studio")) filtered.studio = member.studio; if (isVisible("bio")) filtered.bio = member.bio; if (isVisible("location")) filtered.location = member.location; if (isVisible("socialLinks")) filtered.socialLinks = member.socialLinks; if (isVisible("offering")) filtered.offering = member.offering; if (isVisible("lookingFor")) filtered.lookingFor = member.lookingFor; // Peer support: expose only fields needed for matching/contact UX // slackUserId, slackDMChannelId, slackUsername, personalMessage are internal if (member.peerSupport?.enabled) { filtered.peerSupport = { enabled: true, skillTopics: member.peerSupport.skillTopics, supportTopics: member.peerSupport.supportTopics, availability: member.peerSupport.availability, }; } return { member: filtered }; } catch (error) { // Re-throw NuxtErrors (like the 404 above) if (error.statusCode) { throw error; } console.error("Member profile fetch error:", error); throw createError({ statusCode: 500, message: "Failed to fetch member profile", }); } });