diff --git a/.replit b/.replit index 4fa2a248..fc81a45d 100644 --- a/.replit +++ b/.replit @@ -33,7 +33,3 @@ outputType = "webview" [[ports]] localPort = 5000 externalPort = 80 - -[[ports]] -localPort = 45303 -externalPort = 3000 diff --git a/supabase/functions/cancel-email-change/index.ts b/supabase/functions/cancel-email-change/index.ts index 3276f49d..a97f6959 100644 --- a/supabase/functions/cancel-email-change/index.ts +++ b/supabase/functions/cancel-email-change/index.ts @@ -5,31 +5,6 @@ const corsHeaders = { 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }; -// Helper function to decode JWT and extract user ID -// Properly handles base64url encoding used by JWTs -function decodeJWT(token: string): { sub: string } | null { - try { - const parts = token.split('.'); - if (parts.length !== 3) return null; - - // JWT uses base64url encoding, convert to standard base64 - let base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/'); - - // Add padding if needed - while (base64.length % 4) { - base64 += '='; - } - - // Decode and parse the payload - const decoded = atob(base64); - const payload = JSON.parse(decoded); - return payload; - } catch (error) { - console.error('JWT decode error:', error); - return null; - } -} - Deno.serve(async (req) => { // Handle CORS preflight requests if (req.method === 'OPTIONS') { @@ -37,18 +12,6 @@ Deno.serve(async (req) => { } try { - // Create admin client with service role key - const supabaseAdmin = createClient( - Deno.env.get('SUPABASE_URL') ?? '', - Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '', - { - auth: { - autoRefreshToken: false, - persistSession: false - } - } - ); - // Get the user from the authorization header const authHeader = req.headers.get('Authorization'); if (!authHeader) { @@ -56,17 +19,35 @@ Deno.serve(async (req) => { throw new Error('No authorization header provided. Please ensure you are logged in.'); } + // Extract the JWT token from the Authorization header const token = authHeader.replace('Bearer ', ''); - console.log('Extracting user ID from JWT token...'); + + // Create admin client with service role key (no user token in global headers) + // This ensures all DB operations run with full admin privileges + const supabaseUrl = Deno.env.get('SUPABASE_URL'); + const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY'); - // Parse JWT token to get user ID directly - const payload = decodeJWT(token); - if (!payload || !payload.sub) { - console.error('Invalid JWT token structure'); + if (!supabaseUrl || !supabaseServiceKey) { + throw new Error('Missing Supabase configuration'); + } + + const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey, { + auth: { + autoRefreshToken: false, + persistSession: false + } + }); + + // Verify the user's JWT token by passing it explicitly to getUser() + // Note: verify_jwt = true in config.toml means Supabase has already validated the JWT + const { data: { user }, error: authError } = await supabaseAdmin.auth.getUser(token); + + if (authError || !user) { + console.error('Auth verification failed:', authError); throw new Error('Invalid session token. Please refresh the page and try again.'); } - const userId = payload.sub; + const userId = user.id; console.log(`Cancelling email change for user ${userId}`); // Call the database function to clear email change fields diff --git a/supabase/functions/detect-location/index.ts b/supabase/functions/detect-location/index.ts index 66811457..5acd45b0 100644 --- a/supabase/functions/detect-location/index.ts +++ b/supabase/functions/detect-location/index.ts @@ -25,10 +25,14 @@ serve(async (req) => { console.log('Detecting location for IP:', clientIP); - // Use a free IP geolocation service with proper error handling + // Use configurable geolocation service with proper error handling + // Defaults to ip-api.com if not configured + const geoApiUrl = Deno.env.get('GEOLOCATION_API_URL') || 'http://ip-api.com/json'; + const geoApiFields = Deno.env.get('GEOLOCATION_API_FIELDS') || 'status,country,countryCode'; + let geoResponse; try { - geoResponse = await fetch(`http://ip-api.com/json/${clientIP}?fields=status,country,countryCode`); + geoResponse = await fetch(`${geoApiUrl}/${clientIP}?fields=${geoApiFields}`); } catch (fetchError) { console.error('Network error fetching location data:', fetchError); throw new Error('Network error: Unable to reach geolocation service');