ultisuite-backend/internal/migration/oauth_refresh.go
R3D347HR4Y 7143a36c19
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run
feat(mail): integrate Stalwart hosted mail and migration features
- Added configuration options for Stalwart hosted mail in .env.example.
- Updated Docker Compose to include Stalwart service with health checks.
- Introduced new API endpoints for managing mail domains and migration projects.
- Enhanced Authentik blueprints for user enrollment and post-migration security.
- Updated OAuth handling for Google and Microsoft migration processes.
- Improved error handling and response structures in the mail API.
- Added integration tests for email claiming and migration workflows.
2026-06-13 12:47:08 +02:00

79 lines
2.2 KiB
Go

package migration
import (
"context"
"fmt"
"time"
"golang.org/x/oauth2"
"github.com/ultisuite/ulti-backend/internal/mail/credentials"
)
// RefreshCredential refreshes an expired migration OAuth token and persists it.
func (s *Service) RefreshCredential(
ctx context.Context,
oauth *OAuthService,
userID, projectID, provider string,
cred credentials.Credential,
) (credentials.Credential, error) {
if oauth == nil {
return cred, fmt.Errorf("migration oauth not configured")
}
if !cred.NeedsRefresh() {
return cred, nil
}
if cred.RefreshToken == "" {
return cred, fmt.Errorf("migration refresh token missing; re-run OAuth consent")
}
token, err := oauth.Refresh(ctx, Provider(provider), cred.RefreshToken)
if err != nil {
return cred, fmt.Errorf("refresh migration token: %w", err)
}
updated := applyOAuthTokenFromOAuth2(cred, token)
if err := s.SaveCredential(ctx, userID, projectID, provider, updated); err != nil {
return cred, err
}
return updated, nil
}
// SaveCredential encrypts and stores migration OAuth credentials.
func (s *Service) SaveCredential(ctx context.Context, userID, projectID, provider string, cred credentials.Credential) error {
if s.creds == nil {
return fmt.Errorf("credential manager not configured")
}
cred.AuthType = credentials.AuthOAuth2
cred.OAuthProvider = provider
enc, err := s.creds.EncryptCredential(cred)
if err != nil {
return err
}
var expiresAt *time.Time
if !cred.Expiry.IsZero() {
expiresAt = &cred.Expiry
}
_, err = s.db.Exec(ctx, `
UPDATE migration_credentials SET
encrypted_token = $4,
expires_at = $5,
revoked_at = NULL
WHERE user_id = $1::uuid AND project_id = $2::uuid AND provider = $3
`, userID, projectID, provider, enc, expiresAt)
return err
}
func (s *Service) MicrosoftAdminConsentURL(tenant, projectID string) (string, error) {
if s.oauth == nil {
return "", fmt.Errorf("migration oauth not configured")
}
return s.oauth.AdminConsentURL(tenant, EncodeAdminConsentState(projectID))
}
func applyOAuthTokenFromOAuth2(cred credentials.Credential, token *oauth2.Token) credentials.Credential {
return applyOAuthToken(cred, &oauthToken{
AccessToken: token.AccessToken,
RefreshToken: token.RefreshToken,
Expiry: token.Expiry,
})
}