nuxt-supabase-team-auth
Version:
Drop-in Nuxt 3 module for team-based authentication with Supabase
79 lines (78 loc) • 2.74 kB
JavaScript
import { defineEventHandler, readBody, createError } from "h3";
import { createSessionFromMagicLink } from "../utils/magicLinkSession.js";
import { serverSupabaseServiceRole } from "#supabase/server";
export default defineEventHandler(async (event) => {
try {
console.log("=== PROCESS INVITATION API ===");
const body = await readBody(event);
const { access_token, refresh_token } = body;
if (!access_token || !refresh_token) {
throw createError({
statusCode: 400,
statusMessage: "Missing access_token or refresh_token"
});
}
const adminClient = serverSupabaseServiceRole(event);
const { data: { user }, error: userError } = await adminClient.auth.getUser(access_token);
if (userError || !user) {
console.error("Invalid invitation token:", userError);
throw createError({
statusCode: 401,
statusMessage: "Invalid or expired invitation token"
});
}
console.log("Processing invitation for user:", user.email);
const metadata = user.user_metadata;
const teamId = metadata?.team_id;
const teamName = metadata?.team_name;
const inviteRole = metadata?.role || "member";
if (!teamId) {
throw createError({
statusCode: 400,
statusMessage: "Invalid invitation: missing team information"
});
}
const { session, user: sessionUser } = await createSessionFromMagicLink(
adminClient,
user.email,
{
// Preserve invitation metadata
team_id: teamId,
team_name: teamName,
role: inviteRole,
invited_by: metadata?.invited_by,
invited_by_email: metadata?.invited_by_email,
email_verified: true
}
);
let finalTeamName = teamName;
if (!finalTeamName) {
const { data: team } = await adminClient.from("teams").select("name").eq("id", teamId).single();
if (team) {
finalTeamName = team.name;
}
}
const { data: membership } = await adminClient.from("team_members").select("id").eq("user_id", sessionUser.id).eq("team_id", teamId).maybeSingle();
return {
success: true,
session,
user: sessionUser,
team: {
id: teamId,
name: finalTeamName
},
isExistingMember: !!membership,
needsPasswordSetup: !user.email_confirmed_at || new Date(user.email_confirmed_at).getTime() - new Date(user.created_at).getTime() < 5 * 60 * 1e3
};
} catch (error) {
console.error("Process invitation error:", error);
const errorObj = error;
if (errorObj.statusCode) {
throw error;
}
throw createError({
statusCode: 500,
statusMessage: errorObj.message || "Failed to process invitation"
});
}
});