package oauth import ( "context" "fmt" "time" "github.com/jackc/pgx/v5/pgxpool" "golang.org/x/oauth2" mailcredentials "github.com/ultisuite/ulti-backend/internal/mail/credentials" ) // RefreshAccountCredential refreshes OAuth tokens when needed and persists updated credentials. func RefreshAccountCredential( ctx context.Context, db *pgxpool.Pool, manager *mailcredentials.Manager, oauthSvc *Service, accountID string, cred mailcredentials.Credential, ) (mailcredentials.Credential, error) { if !cred.IsOAuth() || !cred.NeedsRefresh() { return cred, nil } if oauthSvc == nil || cred.RefreshToken == "" { return cred, fmt.Errorf("oauth refresh unavailable") } token, err := oauthSvc.Refresh(ctx, cred.OAuthProvider, cred.RefreshToken) if err != nil { return cred, fmt.Errorf("refresh token: %w", err) } updated := applyToken(cred, token) blob, err := manager.EncryptCredential(updated) if err != nil { return cred, err } _, err = db.Exec(ctx, `UPDATE mail_accounts SET credentials = $1, updated_at = NOW() WHERE id = $2`, blob, accountID) if err != nil { return cred, err } return updated, nil } func CredentialFromToken(email, provider string, token *oauth2.Token) mailcredentials.Credential { return applyToken(mailcredentials.Credential{ AuthType: mailcredentials.AuthOAuth2, Username: email, OAuthProvider: provider, }, token) } func applyToken(c mailcredentials.Credential, token *oauth2.Token) mailcredentials.Credential { c.AccessToken = token.AccessToken if token.RefreshToken != "" { c.RefreshToken = token.RefreshToken } if !token.Expiry.IsZero() { c.Expiry = token.Expiry.UTC() } else if token.ExpiresIn > 0 { c.Expiry = time.Now().Add(time.Duration(token.ExpiresIn) * time.Second) } return c }