65 lines
1.7 KiB
Go
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
|
|
}
|