feat: extend equipment and workout models with service tracking
This commit is contained in:
93
internal/integration/repository.go
Normal file
93
internal/integration/repository.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"rideaware/pkg/database"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Repository struct{}
|
||||
|
||||
func NewRepository() *Repository {
|
||||
return &Repository{}
|
||||
}
|
||||
|
||||
// UpsertConnection creates or updates an OAuth connection for a user+provider pair.
|
||||
func (r *Repository) UpsertConnection(conn *OAuthConnection) error {
|
||||
var existing OAuthConnection
|
||||
err := database.DB.Where("user_id = ? AND provider = ?", conn.UserID, conn.Provider).
|
||||
First(&existing).Error
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return database.DB.Create(conn).Error
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
existing.AccessToken = conn.AccessToken
|
||||
existing.RefreshToken = conn.RefreshToken
|
||||
existing.TokenExpiresAt = conn.TokenExpiresAt
|
||||
existing.ProviderUserID = conn.ProviderUserID
|
||||
existing.Scopes = conn.Scopes
|
||||
existing.Status = "active"
|
||||
|
||||
conn.ID = existing.ID
|
||||
return database.DB.Save(&existing).Error
|
||||
}
|
||||
|
||||
// GetConnection retrieves an active OAuth connection for a user+provider pair.
|
||||
func (r *Repository) GetConnection(userID uint, provider string) (*OAuthConnection, error) {
|
||||
var conn OAuthConnection
|
||||
if err := database.DB.Where("user_id = ? AND provider = ?", userID, provider).
|
||||
First(&conn).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("no " + provider + " connection found")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &conn, nil
|
||||
}
|
||||
|
||||
// UpdateConnection updates an existing OAuth connection.
|
||||
func (r *Repository) UpdateConnection(conn *OAuthConnection) error {
|
||||
return database.DB.Save(conn).Error
|
||||
}
|
||||
|
||||
// DeleteConnection removes an OAuth connection.
|
||||
func (r *Repository) DeleteConnection(userID uint, provider string) error {
|
||||
return database.DB.Where("user_id = ? AND provider = ?", userID, provider).
|
||||
Delete(&OAuthConnection{}).Error
|
||||
}
|
||||
|
||||
// CreateState stores an OAuth state token for CSRF protection.
|
||||
func (r *Repository) CreateState(state *OAuthState) error {
|
||||
return database.DB.Create(state).Error
|
||||
}
|
||||
|
||||
// GetAndDeleteState retrieves and deletes an OAuth state token. Returns error if expired or not found.
|
||||
func (r *Repository) GetAndDeleteState(stateToken string) (*OAuthState, error) {
|
||||
var state OAuthState
|
||||
if err := database.DB.Where("state = ?", stateToken).First(&state).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("invalid or expired state token")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete the state immediately (single-use)
|
||||
database.DB.Delete(&state)
|
||||
|
||||
if time.Now().After(state.ExpiresAt) {
|
||||
return nil, errors.New("state token has expired")
|
||||
}
|
||||
|
||||
return &state, nil
|
||||
}
|
||||
|
||||
// CleanupExpiredStates removes expired OAuth state tokens.
|
||||
func (r *Repository) CleanupExpiredStates() error {
|
||||
return database.DB.Where("expires_at < ?", time.Now()).Delete(&OAuthState{}).Error
|
||||
}
|
||||
Reference in New Issue
Block a user