mirror of
https://github.com/sstent/go-garth.git
synced 2026-01-25 16:42:28 +00:00
169 lines
4.0 KiB
Go
169 lines
4.0 KiB
Go
package garth
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// Unified Token Definitions
|
|
|
|
// OAuth1Token represents OAuth1 credentials
|
|
type OAuth1Token struct {
|
|
Token string
|
|
Secret string
|
|
}
|
|
|
|
// OAuth2Token represents OAuth2 credentials
|
|
type OAuth2Token struct {
|
|
AccessToken string `json:"access_token"`
|
|
TokenType string `json:"token_type"`
|
|
RefreshToken string `json:"refresh_token"`
|
|
ExpiresIn int `json:"expires_in"`
|
|
Expiry time.Time `json:"-"`
|
|
}
|
|
|
|
// IsExpired checks if the token has expired
|
|
func (t *OAuth2Token) IsExpired() bool {
|
|
return time.Now().After(t.Expiry)
|
|
}
|
|
|
|
// Token represents unified authentication credentials
|
|
type Token struct {
|
|
OAuth1 *OAuth1Token
|
|
OAuth2 *OAuth2Token
|
|
UserProfile *UserProfile
|
|
Domain string
|
|
}
|
|
|
|
// IsExpired checks if the OAuth2 token has expired
|
|
func (t *Token) IsExpired() bool {
|
|
if t.OAuth2 == nil {
|
|
return true
|
|
}
|
|
return t.OAuth2.IsExpired()
|
|
}
|
|
|
|
// NeedsRefresh checks if token needs refresh (within 5 min expiry window)
|
|
func (t *Token) NeedsRefresh() bool {
|
|
if t.OAuth2 == nil {
|
|
return true
|
|
}
|
|
return time.Now().Add(5 * time.Minute).After(t.OAuth2.Expiry)
|
|
}
|
|
|
|
// UserProfile represents Garmin user profile information
|
|
type UserProfile struct {
|
|
Username string
|
|
ProfileID string
|
|
DisplayName string
|
|
}
|
|
|
|
// ClientOptions contains configuration for the authenticator
|
|
type ClientOptions struct {
|
|
Storage TokenStorage
|
|
TokenURL string
|
|
Domain string // garmin.com or garmin.cn
|
|
Timeout time.Duration
|
|
}
|
|
|
|
// TokenStorage defines the interface for token storage
|
|
type TokenStorage interface {
|
|
StoreToken(token *Token) error
|
|
GetToken() (*Token, error)
|
|
ClearToken() error
|
|
}
|
|
|
|
// Error interface defines common error behavior for Garth
|
|
type Error interface {
|
|
error
|
|
GetStatusCode() int
|
|
GetType() string
|
|
GetCause() error
|
|
Unwrap() error
|
|
}
|
|
|
|
// ErrTokenNotFound is returned when a token is not available in storage
|
|
var ErrTokenNotFound = errors.New("token not found")
|
|
|
|
// AuthError represents Garmin authentication errors
|
|
type AuthError struct {
|
|
StatusCode int `json:"status_code"` // HTTP status code
|
|
Message string `json:"message"` // Human-readable error message
|
|
Type string `json:"type"` // Garmin error type identifier
|
|
Cause error `json:"cause"` // Underlying error
|
|
}
|
|
|
|
// GetStatusCode returns the HTTP status code
|
|
func (e *AuthError) GetStatusCode() int {
|
|
return e.StatusCode
|
|
}
|
|
|
|
// GetType returns the error category
|
|
func (e *AuthError) GetType() string {
|
|
return e.Type
|
|
}
|
|
|
|
// Error implements the error interface for AuthError
|
|
func (e *AuthError) Error() string {
|
|
msg := fmt.Sprintf("garmin auth error %d: %s", e.StatusCode, e.Message)
|
|
if e.Cause != nil {
|
|
msg += " (" + e.Cause.Error() + ")"
|
|
}
|
|
return msg
|
|
}
|
|
|
|
// Unwrap returns the underlying error
|
|
func (e *AuthError) Unwrap() error {
|
|
return e.Cause
|
|
}
|
|
|
|
// GetCause returns the underlying error (implements Error interface)
|
|
func (e *AuthError) GetCause() error {
|
|
return e.Cause
|
|
}
|
|
|
|
// APIError represents errors from API operations
|
|
type APIError struct {
|
|
StatusCode int // HTTP status code
|
|
Message string // Error description
|
|
Cause error // Underlying error
|
|
ErrorType string // Specific error category
|
|
}
|
|
|
|
// GetStatusCode returns the HTTP status code
|
|
func (e *APIError) GetStatusCode() int {
|
|
return e.StatusCode
|
|
}
|
|
|
|
// GetType returns the error category
|
|
func (e *APIError) GetType() string {
|
|
if e.ErrorType == "" {
|
|
return "api_error"
|
|
}
|
|
return e.ErrorType
|
|
}
|
|
|
|
// Error implements the error interface for APIError
|
|
func (e *APIError) Error() string {
|
|
if e.Cause != nil {
|
|
return fmt.Sprintf("API error (%d): %s: %v", e.StatusCode, e.Message, e.Cause)
|
|
}
|
|
return fmt.Sprintf("API error (%d): %s", e.StatusCode, e.Message)
|
|
}
|
|
|
|
// Unwrap returns the underlying error
|
|
func (e *APIError) Unwrap() error {
|
|
return e.Cause
|
|
}
|
|
|
|
// GetCause returns the underlying error (implements Error interface)
|
|
func (e *APIError) GetCause() error {
|
|
return e.Cause
|
|
}
|
|
|
|
// AuthenticatorSetter interface for storage that needs authenticator reference
|
|
type AuthenticatorSetter interface {
|
|
SetAuthenticator(a Authenticator)
|
|
}
|