Refactor character to types
This commit is contained in:
11
db/db.go
11
db/db.go
@@ -3,6 +3,7 @@ package db
|
|||||||
import (
|
import (
|
||||||
"go-eve-pi/esi"
|
"go-eve-pi/esi"
|
||||||
"go-eve-pi/options"
|
"go-eve-pi/options"
|
||||||
|
"go-eve-pi/types"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
@@ -14,8 +15,8 @@ import (
|
|||||||
type DB interface {
|
type DB interface {
|
||||||
DB() *gorm.DB
|
DB() *gorm.DB
|
||||||
Raw(sql string, args ...any) *gorm.DB
|
Raw(sql string, args ...any) *gorm.DB
|
||||||
GetCharacterByName(characterName string) (*esi.Character, error)
|
GetCharacterByName(characterName string) (*types.Character, error)
|
||||||
SaveCharacter(character *esi.Character) error
|
SaveCharacter(character *types.Character) error
|
||||||
AutoMigrate(dst ...interface{}) error
|
AutoMigrate(dst ...interface{}) error
|
||||||
GetCacheEntry(urlHash string) (*esi.CacheEntry, error)
|
GetCacheEntry(urlHash string) (*esi.CacheEntry, error)
|
||||||
SaveCacheEntry(entry *esi.CacheEntry) error
|
SaveCacheEntry(entry *esi.CacheEntry) error
|
||||||
@@ -59,9 +60,9 @@ func (db *DBWrapper) DB() *gorm.DB {
|
|||||||
return db.db
|
return db.db
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DBWrapper) GetCharacterByName(characterName string) (*esi.Character, error) {
|
func (db *DBWrapper) GetCharacterByName(characterName string) (*types.Character, error) {
|
||||||
logger.Debug("Fetching token for character %s from database", characterName)
|
logger.Debug("Fetching token for character %s from database", characterName)
|
||||||
var char esi.Character
|
var char types.Character
|
||||||
err := db.db.Where("character_name = ?", characterName).First(&char).Error
|
err := db.db.Where("character_name = ?", characterName).First(&char).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug("No token found for character %s: %v", characterName, err)
|
logger.Debug("No token found for character %s: %v", characterName, err)
|
||||||
@@ -71,7 +72,7 @@ func (db *DBWrapper) GetCharacterByName(characterName string) (*esi.Character, e
|
|||||||
return &char, nil
|
return &char, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DBWrapper) SaveCharacter(character *esi.Character) error {
|
func (db *DBWrapper) SaveCharacter(character *types.Character) error {
|
||||||
logger.Debug("Saving token for character %s to database", character.CharacterName)
|
logger.Debug("Saving token for character %s to database", character.CharacterName)
|
||||||
err := db.db.Save(character).Error
|
err := db.db.Save(character).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
42
esi/sso.go
42
esi/sso.go
@@ -16,6 +16,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go-eve-pi/types"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
logger "git.site.quack-lab.dev/dave/cylogger"
|
logger "git.site.quack-lab.dev/dave/cylogger"
|
||||||
@@ -28,14 +29,11 @@ const (
|
|||||||
issuerTokenURL = "https://login.eveonline.com/v2/oauth/token"
|
issuerTokenURL = "https://login.eveonline.com/v2/oauth/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Character struct {
|
// DB interface for database operations
|
||||||
ID int64 `gorm:"primaryKey"` // EVE character ID from JWT token
|
type DB interface {
|
||||||
CharacterName string `gorm:"uniqueIndex"`
|
GetCharacterByName(characterName string) (*types.Character, error)
|
||||||
AccessToken string
|
SaveCharacter(character *types.Character) error
|
||||||
RefreshToken string
|
AutoMigrate(dst ...interface{}) error
|
||||||
ExpiresAt time.Time
|
|
||||||
UpdatedAt time.Time
|
|
||||||
CreatedAt time.Time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SSO struct {
|
type SSO struct {
|
||||||
@@ -54,15 +52,9 @@ type SSO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSSO creates a new SSO instance
|
// NewSSO creates a new SSO instance
|
||||||
func NewSSO(clientID, redirectURI string, scopes []string) (*SSO, error) {
|
func NewSSO(clientID, redirectURI string, scopes []string, db DB) (*SSO, error) {
|
||||||
logger.Info("Creating new SSO instance for clientID %s with redirectURI %s and scopes %v", clientID, redirectURI, scopes)
|
logger.Info("Creating new SSO instance for clientID %s with redirectURI %s and scopes %v", clientID, redirectURI, scopes)
|
||||||
|
|
||||||
db, err := GetDB()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to get database connection %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &SSO{
|
s := &SSO{
|
||||||
clientID: clientID,
|
clientID: clientID,
|
||||||
redirectURI: redirectURI,
|
redirectURI: redirectURI,
|
||||||
@@ -88,7 +80,7 @@ func (s *SSO) SetRouter(r *router.Router) {
|
|||||||
|
|
||||||
func (s *SSO) initDB() error {
|
func (s *SSO) initDB() error {
|
||||||
logger.Debug("Initializing SSO database schema")
|
logger.Debug("Initializing SSO database schema")
|
||||||
err := s.db.AutoMigrate(&Character{})
|
err := s.db.AutoMigrate(&types.Character{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to migrate Token table %v", err)
|
logger.Error("Failed to migrate Token table %v", err)
|
||||||
return err
|
return err
|
||||||
@@ -100,7 +92,7 @@ func (s *SSO) initDB() error {
|
|||||||
// GetCharacter returns a valid character object for the given character name
|
// GetCharacter returns a valid character object for the given character name
|
||||||
// If no token exists, it will start the OAuth flow
|
// If no token exists, it will start the OAuth flow
|
||||||
// If token is expired, it will refresh it automatically
|
// If token is expired, it will refresh it automatically
|
||||||
func (s *SSO) GetCharacter(ctx context.Context, characterName string) (Character, error) {
|
func (s *SSO) GetCharacter(ctx context.Context, characterName string) (types.Character, error) {
|
||||||
logger.Debug("Getting token for character %s", characterName)
|
logger.Debug("Getting token for character %s", characterName)
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
@@ -112,16 +104,16 @@ func (s *SSO) GetCharacter(ctx context.Context, characterName string) (Character
|
|||||||
logger.Info("No existing token found for character %s, starting authentication flow", characterName)
|
logger.Info("No existing token found for character %s, starting authentication flow", characterName)
|
||||||
// No token exists, need to authenticate
|
// No token exists, need to authenticate
|
||||||
if err := s.startAuthFlow(ctx, characterName); err != nil {
|
if err := s.startAuthFlow(ctx, characterName); err != nil {
|
||||||
return Character{}, err
|
return types.Character{}, err
|
||||||
}
|
}
|
||||||
// After authentication, fetch the token from DB
|
// After authentication, fetch the token from DB
|
||||||
char, err = s.db.GetCharacterByName(characterName)
|
char, err = s.db.GetCharacterByName(characterName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Character{}, err
|
return types.Character{}, err
|
||||||
}
|
}
|
||||||
logger.Info("Successfully authenticated character %s", characterName)
|
logger.Info("Successfully authenticated character %s", characterName)
|
||||||
} else {
|
} else {
|
||||||
return Character{}, err
|
return types.Character{}, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Debug("Found existing token for character %s, expires at %v", characterName, char.ExpiresAt)
|
logger.Debug("Found existing token for character %s, expires at %v", characterName, char.ExpiresAt)
|
||||||
@@ -148,12 +140,12 @@ func (s *SSO) GetCharacter(ctx context.Context, characterName string) (Character
|
|||||||
logger.Warning("Token refresh failed for character %s, re-authenticating: %v", characterName, err)
|
logger.Warning("Token refresh failed for character %s, re-authenticating: %v", characterName, err)
|
||||||
// Refresh failed, need to re-authenticate
|
// Refresh failed, need to re-authenticate
|
||||||
if err := s.startAuthFlow(ctx, characterName); err != nil {
|
if err := s.startAuthFlow(ctx, characterName); err != nil {
|
||||||
return Character{}, err
|
return types.Character{}, err
|
||||||
}
|
}
|
||||||
// After re-authentication, fetch the token from DB
|
// After re-authentication, fetch the token from DB
|
||||||
char, err = s.db.GetCharacterByName(characterName)
|
char, err = s.db.GetCharacterByName(characterName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Character{}, err
|
return types.Character{}, err
|
||||||
}
|
}
|
||||||
logger.Info("Successfully re-authenticated character %s", characterName)
|
logger.Info("Successfully re-authenticated character %s", characterName)
|
||||||
} else {
|
} else {
|
||||||
@@ -320,7 +312,7 @@ func (s *SSO) waitForCallback() (code, state string, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SSO) exchangeCodeForToken(ctx context.Context, code, verifier string) (*Character, error) {
|
func (s *SSO) exchangeCodeForToken(ctx context.Context, code, verifier string) (*types.Character, error) {
|
||||||
logger.Debug("Exchanging authorization code for access token")
|
logger.Debug("Exchanging authorization code for access token")
|
||||||
form := url.Values{}
|
form := url.Values{}
|
||||||
form.Set("grant_type", "authorization_code")
|
form.Set("grant_type", "authorization_code")
|
||||||
@@ -356,7 +348,7 @@ func (s *SSO) exchangeCodeForToken(ctx context.Context, code, verifier string) (
|
|||||||
name, _ := parseTokenCharacter(tr.AccessToken)
|
name, _ := parseTokenCharacter(tr.AccessToken)
|
||||||
logger.Info("Successfully exchanged code for token, character: %s", name)
|
logger.Info("Successfully exchanged code for token, character: %s", name)
|
||||||
|
|
||||||
return &Character{
|
return &types.Character{
|
||||||
CharacterName: name,
|
CharacterName: name,
|
||||||
AccessToken: tr.AccessToken,
|
AccessToken: tr.AccessToken,
|
||||||
RefreshToken: tr.RefreshToken,
|
RefreshToken: tr.RefreshToken,
|
||||||
@@ -364,7 +356,7 @@ func (s *SSO) exchangeCodeForToken(ctx context.Context, code, verifier string) (
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SSO) refreshToken(ctx context.Context, char *Character) error {
|
func (s *SSO) refreshToken(ctx context.Context, char *types.Character) error {
|
||||||
logger.Debug("Refreshing token for character %s", char.CharacterName)
|
logger.Debug("Refreshing token for character %s", char.CharacterName)
|
||||||
form := url.Values{}
|
form := url.Values{}
|
||||||
form.Set("grant_type", "refresh_token")
|
form.Set("grant_type", "refresh_token")
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
|
||||||
|
|
||||||
"go-eve-pi/esi"
|
"go-eve-pi/esi"
|
||||||
|
"go-eve-pi/types"
|
||||||
wh "go-eve-pi/webhook"
|
wh "go-eve-pi/webhook"
|
||||||
|
|
||||||
logger "git.site.quack-lab.dev/dave/cylogger"
|
logger "git.site.quack-lab.dev/dave/cylogger"
|
||||||
@@ -23,18 +23,7 @@ type RouteHandler struct {
|
|||||||
|
|
||||||
// SSOInterface defines the interface for SSO operations
|
// SSOInterface defines the interface for SSO operations
|
||||||
type SSOInterface interface {
|
type SSOInterface interface {
|
||||||
GetCharacter(ctx context.Context, characterName string) (Character, error)
|
GetCharacter(ctx context.Context, characterName string) (types.Character, error)
|
||||||
}
|
|
||||||
|
|
||||||
// Character represents a character with authentication info
|
|
||||||
type Character struct {
|
|
||||||
ID int64 `gorm:"primaryKey"`
|
|
||||||
CharacterName string `gorm:"uniqueIndex"`
|
|
||||||
AccessToken string
|
|
||||||
RefreshToken string
|
|
||||||
ExpiresAt time.Time
|
|
||||||
UpdatedAt time.Time
|
|
||||||
CreatedAt time.Time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouteHandler creates a new route handler with dependencies
|
// NewRouteHandler creates a new route handler with dependencies
|
||||||
|
|||||||
14
types/character.go
Normal file
14
types/character.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Character represents a character with authentication info
|
||||||
|
type Character struct {
|
||||||
|
ID int64 `gorm:"primaryKey"` // EVE character ID from JWT token
|
||||||
|
CharacterName string `gorm:"uniqueIndex"`
|
||||||
|
AccessToken string
|
||||||
|
RefreshToken string
|
||||||
|
ExpiresAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
CreatedAt time.Time
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user