This commit is contained in:
zramsay 2025-03-12 10:29:56 -04:00
parent 1aacb2b381
commit b779662245
3 changed files with 125 additions and 46 deletions

View File

@ -67,11 +67,47 @@ const authOptions = {
console.log("Initial sign-in, storing profile data in token");
token.userId = token.sub; // Use sub as the primary userId
token.email = profile.email;
// Register user with Supabase immediately after successful authentication
try {
const { ensureUserExists } = require('../../../../services/userPointsService');
console.log("Registering user in Supabase:", { userId: token.userId, email: token.email });
if (token.userId && token.email) {
const userUuid = await ensureUserExists(
token.userId,
token.email,
profile.name
);
console.log("User registered in Supabase:", userUuid);
} else {
console.warn("Missing user data for Supabase registration");
}
} catch (err) {
console.error("Error registering user in Supabase:", err);
// Continue with auth flow even if registration fails
}
} else if (user) {
// If we have user but no profile, make sure to keep the user data
console.log("User data available, storing in token");
token.userId = token.sub || user.id;
token.email = token.email || user.email;
// Also ensure user exists in Supabase on non-initial sign-ins
try {
const { ensureUserExists } = require('../../../../services/userPointsService');
console.log("Ensuring user exists in Supabase (non-initial sign-in)");
if (token.userId && token.email) {
await ensureUserExists(
token.userId,
token.email,
token.name
);
}
} catch (err) {
console.error("Error ensuring user exists in Supabase:", err);
}
} else {
// Ensure email is always available for user identification
console.log("No profile or user, using token defaults");
@ -110,6 +146,30 @@ const authOptions = {
session.user.email = token.email;
console.log("Added missing email to session from token:", token.email);
}
// Also ensure user exists in Supabase when session is accessed
// This provides yet another safety check for user registration
try {
if (session.user.id && session.user.email) {
const { ensureUserExists } = require('../../../../services/userPointsService');
console.log("Ensuring user exists in Supabase (from session callback)");
const userUuid = await ensureUserExists(
session.user.id,
session.user.email,
session.user.name
);
// If the ensured UUID is different from session user ID, update session
if (userUuid && userUuid !== session.user.id) {
console.log(`Session user ID (${session.user.id}) doesn't match Supabase user ID (${userUuid}), updating session`);
session.user.id = userUuid;
}
}
} catch (err) {
console.error("Error ensuring user exists during session callback:", err);
// Continue returning session even if this fails
}
}
// Detailed logging of the session we're returning

View File

@ -32,14 +32,22 @@ export default function PointsPage() {
useEffect(() => {
// Only load points if user is authenticated
if (isAuthenticated && session?.user) {
// Use email as fallback if id is missing
const userId = session.user.id || session.user.email;
if (userId) {
console.log('Loading points for user:', userId);
loadUserPoints(userId);
// ALWAYS use email for consistent user identification
// This ensures we always get the same user regardless of session ID changes
const userIdentifier = session.user.email;
if (userIdentifier) {
console.log('Loading points using email identifier:', userIdentifier);
loadUserPoints(userIdentifier);
} else {
setError('User ID or email not available');
setLoading(false);
// Fallback to ID if somehow email is missing
const userId = session.user.id;
if (userId) {
console.log('No email available, falling back to user ID:', userId);
loadUserPoints(userId);
} else {
setError('User ID or email not available');
setLoading(false);
}
}
} else if (status !== 'loading') {
// If user is not authenticated and we've finished loading auth status

View File

@ -319,8 +319,9 @@ export async function findUserByEmail(email: string) {
/**
* Get a user's total points
* This function is email-aware and will find the correct user by email
*/
export async function getUserPoints(userId: string) {
export async function getUserPoints(userIdOrEmail: string) {
try {
// Add safe mode to bypass database operations if needed
const safeMode = process.env.POINTS_SAFE_MODE === 'true';
@ -329,31 +330,33 @@ export async function getUserPoints(userId: string) {
return 1; // Return 1 as a default so UI shows something
}
if (!userId) {
console.warn('Cannot get points for undefined userId');
if (!userIdOrEmail) {
console.warn('Cannot get points for undefined userId/email');
return 0;
}
console.log('Fetching points for user:', userId);
console.log('Processing points request for:', userIdOrEmail);
// If the userId is not a UUID and looks like an email, try to find by email
if (!validateUuid(userId) && userId.includes('@')) {
const user = await findUserByEmail(userId);
// IMPORTANT: Always try to find by email first if it looks like an email
// This ensures consistent user identification regardless of the session ID
let userId = userIdOrEmail;
if (userIdOrEmail.includes('@')) {
console.log('Input looks like an email, finding consistent user ID');
const user = await findUserByEmail(userIdOrEmail);
if (user) {
userId = user.id;
console.log('Found user by email, using ID:', userId);
console.log('Found user by email, using consistent ID:', userId);
} else {
console.log('No user found by email, returning 0 points');
return 0;
}
}
// Validate final user ID format
if (!validateUuid(userId)) {
console.warn('Invalid UUID format for user:', userId);
} else if (!validateUuid(userIdOrEmail)) {
// If not email and not valid UUID, we can't proceed
console.warn('Invalid user identifier format:', userIdOrEmail);
return 0;
}
// At this point, userId should be a valid UUID
// Try getting total points using the RPC function
try {
const { data: totalPoints, error } = await supabaseAdmin.rpc('get_user_total_points', {
@ -394,8 +397,9 @@ export async function getUserPoints(userId: string) {
/**
* Get a user's point transaction history
* This function is email-aware and will find the correct user by email
*/
export async function getUserTransactions(userId: string) {
export async function getUserTransactions(userIdOrEmail: string) {
try {
// Add safe mode to bypass database operations if needed
const safeMode = process.env.POINTS_SAFE_MODE === 'true';
@ -404,7 +408,7 @@ export async function getUserTransactions(userId: string) {
// Return a sample transaction for UI display
return [{
id: 1,
user_id: userId,
user_id: userIdOrEmail,
points: 1,
transaction_type: 'image_upload',
image_hash: null,
@ -415,31 +419,33 @@ export async function getUserTransactions(userId: string) {
}];
}
if (!userId) {
console.warn('Cannot get transactions for undefined userId');
if (!userIdOrEmail) {
console.warn('Cannot get transactions for undefined userId/email');
return [];
}
console.log('Fetching transactions for user:', userId);
console.log('Processing transactions request for:', userIdOrEmail);
// If the userId is not a UUID and looks like an email, try to find by email
if (!validateUuid(userId) && userId.includes('@')) {
const user = await findUserByEmail(userId);
// IMPORTANT: Always try to find by email first if it looks like an email
// This ensures consistent user identification regardless of the session ID
let userId = userIdOrEmail;
if (userIdOrEmail.includes('@')) {
console.log('Input looks like an email, finding consistent user ID');
const user = await findUserByEmail(userIdOrEmail);
if (user) {
userId = user.id;
console.log('Found user by email, using ID:', userId);
console.log('Found user by email, using consistent ID:', userId);
} else {
console.log('No user found by email, returning empty transactions');
return [];
}
}
// Validate final user ID format
if (!validateUuid(userId)) {
console.warn('Invalid UUID format for user:', userId);
} else if (!validateUuid(userIdOrEmail)) {
// If not email and not valid UUID, we can't proceed
console.warn('Invalid user identifier format:', userIdOrEmail);
return [];
}
// At this point, userId should be a valid UUID
// Try the RPC function first
try {
const { data: transactions, error: rpcError } = await supabaseAdmin.rpc('get_user_transactions', {
@ -480,32 +486,37 @@ export async function getUserTransactions(userId: string) {
/**
* Get full user stats
* This function is email-aware and will find the correct user by email
*/
export async function getUserStats(userId: string) {
export async function getUserStats(userIdOrEmail: string) {
try {
if (!userId) {
console.warn('Cannot get stats for undefined userId');
if (!userIdOrEmail) {
console.warn('Cannot get stats for undefined userId/email');
return null;
}
// If the userId is not a UUID and looks like an email, try to find by email
if (!validateUuid(userId) && userId.includes('@')) {
const user = await findUserByEmail(userId);
console.log('Processing stats request for:', userIdOrEmail);
// IMPORTANT: Always try to find by email first if it looks like an email
// This ensures consistent user identification regardless of the session ID
let userId = userIdOrEmail;
if (userIdOrEmail.includes('@')) {
console.log('Input looks like an email, finding consistent user ID');
const user = await findUserByEmail(userIdOrEmail);
if (user) {
userId = user.id;
console.log('Found user by email, using ID:', userId);
console.log('Found user by email, using consistent ID:', userId);
} else {
console.log('No user found by email, returning null stats');
return null;
}
}
// Validate final user ID format
if (!validateUuid(userId)) {
console.warn('Invalid UUID format for user:', userId);
} else if (!validateUuid(userIdOrEmail)) {
// If not email and not valid UUID, we can't proceed
console.warn('Invalid user identifier format:', userIdOrEmail);
return null;
}
// At this point, userId should be a valid UUID
// Get user stats using the RPC function
const { data, error } = await supabaseAdmin.rpc('get_user_stats', {
user_id_param: userId