@@ -526,22 +526,30 @@ async function getAuthenticatedUser(c: Context) {
526526}
527527
528528async function getUserMiningSources ( authorization : string ) {
529- const supabase = createSupabaseClient ( authorization ) ;
530- const { data, error } = await supabase
531- . schema ( "private" )
532- . rpc ( "get_user_mining_source_credentials" , {
533- _encryption_key : LEADMINER_API_HASH_SECRET ,
534- } ) ;
529+ const response = await fetch ( `${ SUPABASE_URL } /functions/v1/fetch-mining-source` , {
530+ method : "POST" ,
531+ headers : {
532+ "Content-Type" : "application/json" ,
533+ "Authorization" : authorization ,
534+ } ,
535+ body : JSON . stringify ( { email : "all" } ) ,
536+ } ) ;
535537
536- if ( error ) {
537- throw new Error ( `Unable to fetch mining credentials: ${ error . message } ` ) ;
538+ if ( ! response . ok ) {
539+ const errorText = await response . text ( ) ;
540+ throw new Error ( `Failed to fetch mining sources: ${ response . status } ${ errorText } ` ) ;
538541 }
539542
540- return ( data ?? [ ] ) as {
541- email : string ;
542- type : string ;
543- credentials : Record < string , unknown > ;
544- } [ ] ;
543+ const result = await response . json ( ) as {
544+ sources : { email : string ; type : string ; credentials : Record < string , unknown > } [ ] ;
545+ refreshed : string [ ] ;
546+ } ;
547+
548+ if ( result . refreshed . length > 0 ) {
549+ logger . info ( "Tokens refreshed via central function" , { emails : result . refreshed } ) ;
550+ }
551+
552+ return result . sources ;
545553}
546554
547555async function guessCustomSmtpHost ( email : string ) {
@@ -635,43 +643,11 @@ async function resolveSenderOptions(authorization: string, userEmail: string) {
635643 const transportBySender : Record < string , Transport | null > = {
636644 [ fallbackSenderEmail ] : null ,
637645 } ;
638- const supabaseAdmin = createSupabaseAdmin ( ) ;
639646
640647 const sources = listUniqueSenderSources (
641648 await getUserMiningSources ( authorization ) ,
642649 ) ;
643650
644- // Refresh expired OAuth tokens
645- for ( let i = 0 ; i < sources . length ; i ++ ) {
646- const source = sources [ i ] ;
647- const credentialIssue = getSenderCredentialIssue ( source ) ;
648-
649- if ( credentialIssue ?. includes ( "expired" ) ) {
650- try {
651- const refreshed = await refreshOAuthToken ( source ) ;
652- if ( refreshed ) {
653- const updated = await updateMiningSourceCredentials (
654- supabaseAdmin ,
655- source . email ,
656- refreshed . credentials ,
657- ) ;
658- if ( updated ) {
659- sources [ i ] = refreshed ;
660- }
661- } else {
662- logger . warn ( "Could not refresh token, source will remain unavailable" , {
663- email : source . email ,
664- } ) ;
665- }
666- } catch ( error ) {
667- logger . error ( "Failed to refresh token for source" , {
668- email : source . email ,
669- error : error instanceof Error ? error . message : String ( error ) ,
670- } ) ;
671- }
672- }
673- }
674-
675651 for ( const source of sources ) {
676652 const nowMs = Date . now ( ) ;
677653 const expired = isTokenExpired ( source . credentials , nowMs ) ;
@@ -2068,9 +2044,9 @@ app.get("/unsubscribe/:token", async (c: Context) => {
20682044 status : 302 ,
20692045 headers : {
20702046 ...corsHeaders ,
2071- Location : success } ) ;
2072- } ) ; Url ,
2047+ Location : successUrl ,
20732048 } ,
2049+ } ) ;
20742050
20752051
20762052app . get ( "/track/open/:token" , async ( c : Context ) => {
0 commit comments