import { NextResponse } from "next/server"; import { getSupabaseAdmin } from "@/lib/admin"; export async function GET(request: Request) { try { const url = new URL(request.url); const organizationId = url.searchParams.get("organizationId"); const userId = url.searchParams.get("userId"); if (!organizationId || !userId) { return NextResponse.json({ error: "Organization ID and User ID are required" }, { status: 400 }); } // Verify user has access to this organization const { data: userOrg, error: accessError } = await getSupabaseAdmin() .from("users") .select("organization_id, role") .eq("id", userId) .eq("organization_id", organizationId) .single(); if (accessError || !userOrg) { return NextResponse.json({ error: "Access denied" }, { status: 403 }); } // Get all members of the organization const { data: members, error: membersError } = await getSupabaseAdmin() .from("users") .select("id, name, email, role, created_at") .eq("organization_id", organizationId) .order("created_at", { ascending: true }); if (membersError) { console.error("Error fetching members:", membersError); return NextResponse.json({ error: "Failed to fetch members" }, { status: 500 }); } return NextResponse.json({ members }); } catch (error) { console.error("Error in members GET:", error); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } } export async function POST(request: Request) { try { const { organizationId, email, role, invitedBy } = await request.json(); if (!organizationId || !email || !role || !invitedBy) { return NextResponse.json({ error: "Organization ID, email, role, and inviter ID are required" }, { status: 400 }); } // Verify inviter has permission (must be owner or admin) const { data: inviter, error: inviterError } = await getSupabaseAdmin() .from("users") .select("organization_id, role") .eq("id", invitedBy) .eq("organization_id", organizationId) .single(); if (inviterError || !inviter) { return NextResponse.json({ error: "Access denied" }, { status: 403 }); } if (inviter.role !== "owner" && inviter.role !== "admin") { return NextResponse.json({ error: "Only owners and admins can invite members" }, { status: 403 }); } // Check if user already exists in the system const { data: existingUsers, error: userCheckError } = await getSupabaseAdmin() .auth.admin.listUsers(); if (userCheckError) { console.error("Error checking existing users:", userCheckError); return NextResponse.json({ error: "Failed to check existing users" }, { status: 500 }); } const existingUser = existingUsers.users.find(u => u.email === email); if (existingUser) { // Check if user is already in an organization const { data: userRecord } = await getSupabaseAdmin() .from("users") .select("organization_id") .eq("id", existingUser.id) .single(); if (userRecord?.organization_id) { if (userRecord.organization_id === organizationId) { return NextResponse.json({ error: "User is already a member of this organization" }, { status: 400 }); } else { return NextResponse.json({ error: "User is already a member of another organization" }, { status: 400 }); } } // Add existing user to organization const { error: updateError } = await getSupabaseAdmin() .from("users") .update({ organization_id: organizationId, role }) .eq("id", existingUser.id); if (updateError) { console.error("Error adding existing user to organization:", updateError); return NextResponse.json({ error: "Failed to add user to organization" }, { status: 500 }); } // Get updated user data const { data: updatedUser } = await getSupabaseAdmin() .from("users") .select("id, name, email, role, created_at") .eq("id", existingUser.id) .single(); return NextResponse.json({ member: updatedUser, message: "Existing user added to organization" }); } else { // Create invitation record for new user // Note: In a real app, you'd send an email invitation here // For now, we'll just create a placeholder record return NextResponse.json({ message: "Invitation would be sent to new user", action: "invitation_sent" }); } } catch (error) { console.error("Error in members POST:", error); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } } export async function PUT(request: Request) { try { const { memberId, role, updatedBy, organizationId } = await request.json(); if (!memberId || !role || !updatedBy || !organizationId) { return NextResponse.json({ error: "Member ID, role, updater ID, and organization ID are required" }, { status: 400 }); } // Verify updater has permission (must be owner) const { data: updater, error: updaterError } = await getSupabaseAdmin() .from("users") .select("organization_id, role") .eq("id", updatedBy) .eq("organization_id", organizationId) .single(); if (updaterError || !updater) { return NextResponse.json({ error: "Access denied" }, { status: 403 }); } if (updater.role !== "owner") { return NextResponse.json({ error: "Only owners can update member roles" }, { status: 403 }); } // Don't allow changing the role of the organization owner const { data: targetMember } = await getSupabaseAdmin() .from("users") .select("role") .eq("id", memberId) .single(); if (targetMember?.role === "owner" && role !== "owner") { return NextResponse.json({ error: "Cannot change the role of the organization owner" }, { status: 400 }); } // Update member role const { data: updatedMember, error: updateError } = await getSupabaseAdmin() .from("users") .update({ role }) .eq("id", memberId) .eq("organization_id", organizationId) .select("id, name, email, role, created_at") .single(); if (updateError) { console.error("Error updating member role:", updateError); return NextResponse.json({ error: "Failed to update member role" }, { status: 500 }); } return NextResponse.json({ member: updatedMember }); } catch (error) { console.error("Error in members PUT:", error); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } } export async function DELETE(request: Request) { try { const url = new URL(request.url); const memberId = url.searchParams.get("memberId"); const removedBy = url.searchParams.get("removedBy"); const organizationId = url.searchParams.get("organizationId"); if (!memberId || !removedBy || !organizationId) { return NextResponse.json({ error: "Member ID, remover ID, and organization ID are required" }, { status: 400 }); } // Verify remover has permission (must be owner or admin) const { data: remover, error: removerError } = await getSupabaseAdmin() .from("users") .select("organization_id, role") .eq("id", removedBy) .eq("organization_id", organizationId) .single(); if (removerError || !remover) { return NextResponse.json({ error: "Access denied" }, { status: 403 }); } if (remover.role !== "owner" && remover.role !== "admin") { return NextResponse.json({ error: "Only owners and admins can remove members" }, { status: 403 }); } // Don't allow removing the organization owner const { data: targetMember } = await getSupabaseAdmin() .from("users") .select("role") .eq("id", memberId) .single(); if (targetMember?.role === "owner") { return NextResponse.json({ error: "Cannot remove the organization owner" }, { status: 400 }); } // Remove member from organization (set organization_id to null) const { error: removeError } = await getSupabaseAdmin() .from("users") .update({ organization_id: null, role: "member" }) .eq("id", memberId) .eq("organization_id", organizationId); if (removeError) { console.error("Error removing member:", removeError); return NextResponse.json({ error: "Failed to remove member" }, { status: 500 }); } return NextResponse.json({ success: true }); } catch (error) { console.error("Error in members DELETE:", error); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } }