ultisuite-backend/internal/mail/oauth/refresh.go
2026-05-24 00:03:36 +02:00

65 lines
1.7 KiB
Go

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
}