Autenticate OAuth backends

This commit is contained in:
Philipp Wolfer 2023-11-21 17:51:13 +01:00
parent 94704f9cd0
commit fa7732c538
No known key found for this signature in database
GPG key ID: 8FDF744D4919943B
15 changed files with 61 additions and 20 deletions

View file

@ -28,7 +28,7 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uploadedlobster.com/scotty/models" "go.uploadedlobster.com/scotty/models"
"go.uploadedlobster.com/scotty/storage" "golang.org/x/oauth2"
) )
func BuildRedirectURL(config *viper.Viper, backend string) (*url.URL, error) { func BuildRedirectURL(config *viper.Viper, backend string) (*url.URL, error) {
@ -40,21 +40,15 @@ func BuildRedirectURL(config *viper.Viper, backend string) (*url.URL, error) {
return url.Parse("http://" + callbackHost + callbackPath) return url.Parse("http://" + callbackHost + callbackPath)
} }
func Authenticate(backend models.Backend, db storage.Database, config *viper.Viper) error { func Authenticate(backend models.Backend, token *oauth2.Token, config *viper.Viper) (bool, error) {
authenticator, auth := backend.(models.OAuth2Authenticator) authenticator, auth := backend.(models.OAuth2Authenticator)
if auth { if auth {
// FIXME // FIXME
backendName := "spotify" redirectURL, err := BuildRedirectURL(config, backend.Name())
redirectURL, err := BuildRedirectURL(config, backendName)
if err != nil { if err != nil {
return err return auth, err
}
// FIXME
token, err := db.GetOAuth2Token("spotify")
if err != nil {
return err
} }
authenticator.OAuth2Setup(redirectURL.String(), token) authenticator.OAuth2Setup(redirectURL.String(), token)
} }
return nil return auth, nil
} }

View file

@ -28,6 +28,8 @@ import (
type DumpBackend struct{} type DumpBackend struct{}
func (b *DumpBackend) Name() string { return "dump" }
func (b *DumpBackend) FromConfig(config *viper.Viper) models.Backend { func (b *DumpBackend) FromConfig(config *viper.Viper) models.Backend {
return b return b
} }

View file

@ -36,6 +36,8 @@ type FunkwhaleApiBackend struct {
username string username string
} }
func (b *FunkwhaleApiBackend) Name() string { return "funkwhale" }
func (b *FunkwhaleApiBackend) FromConfig(config *viper.Viper) models.Backend { func (b *FunkwhaleApiBackend) FromConfig(config *viper.Viper) models.Backend {
b.client = NewClient( b.client = NewClient(
config.GetString("server-url"), config.GetString("server-url"),

View file

@ -39,6 +39,8 @@ type JspfBackend struct {
tracks []Track tracks []Track
} }
func (b *JspfBackend) Name() string { return "jspf" }
func (b *JspfBackend) FromConfig(config *viper.Viper) models.Backend { func (b *JspfBackend) FromConfig(config *viper.Viper) models.Backend {
b.filePath = config.GetString("file-path") b.filePath = config.GetString("file-path")
b.title = config.GetString("title") b.title = config.GetString("title")

View file

@ -36,6 +36,8 @@ type ListenBrainzApiBackend struct {
existingMbids map[string]bool existingMbids map[string]bool
} }
func (b *ListenBrainzApiBackend) Name() string { return "listenbrainz" }
func (b *ListenBrainzApiBackend) FromConfig(config *viper.Viper) models.Backend { func (b *ListenBrainzApiBackend) FromConfig(config *viper.Viper) models.Backend {
b.client = NewClient(config.GetString("token")) b.client = NewClient(config.GetString("token"))
b.client.MaxResults = MaxItemsPerGet b.client.MaxResults = MaxItemsPerGet

View file

@ -36,6 +36,8 @@ type MalojaApiBackend struct {
nofix bool nofix bool
} }
func (b *MalojaApiBackend) Name() string { return "maloja" }
func (b *MalojaApiBackend) FromConfig(config *viper.Viper) models.Backend { func (b *MalojaApiBackend) FromConfig(config *viper.Viper) models.Backend {
b.client = NewClient( b.client = NewClient(
config.GetString("server-url"), config.GetString("server-url"),

View file

@ -37,6 +37,8 @@ type ScrobblerLogBackend struct {
log ScrobblerLog log ScrobblerLog
} }
func (b *ScrobblerLogBackend) Name() string { return "scrobbler-log" }
func (b *ScrobblerLogBackend) FromConfig(config *viper.Viper) models.Backend { func (b *ScrobblerLogBackend) FromConfig(config *viper.Viper) models.Backend {
b.filePath = config.GetString("file-path") b.filePath = config.GetString("file-path")
b.includeSkipped = config.GetBool("include-skipped") b.includeSkipped = config.GetBool("include-skipped")

View file

@ -40,6 +40,8 @@ type SpotifyApiBackend struct {
clientSecret string clientSecret string
} }
func (b *SpotifyApiBackend) Name() string { return "spotify" }
func (b *SpotifyApiBackend) FromConfig(config *viper.Viper) models.Backend { func (b *SpotifyApiBackend) FromConfig(config *viper.Viper) models.Backend {
b.clientId = config.GetString("client-id") b.clientId = config.GetString("client-id")
b.clientSecret = config.GetString("client-secret") b.clientSecret = config.GetString("client-secret")

View file

@ -36,6 +36,8 @@ type SubsonicApiBackend struct {
password string password string
} }
func (b *SubsonicApiBackend) Name() string { return "subsonic" }
func (b *SubsonicApiBackend) FromConfig(config *viper.Viper) models.Backend { func (b *SubsonicApiBackend) FromConfig(config *viper.Viper) models.Backend {
b.client = subsonic.Client{ b.client = subsonic.Client{
Client: &http.Client{}, Client: &http.Client{},

View file

@ -96,7 +96,7 @@ var authCmd = &cobra.Command{
db, err := storage.New(viper.GetString("database")) db, err := storage.New(viper.GetString("database"))
cobra.CheckErr(err) cobra.CheckErr(err)
err = db.SetOAuth2Token(serviceName, *tok) err = db.SetOAuth2Token(serviceName, tok)
cobra.CheckErr(err) cobra.CheckErr(err)
// oauth2.Token{ // oauth2.Token{

View file

@ -54,8 +54,21 @@ var listensCmd = &cobra.Command{
cobra.CheckErr(err) cobra.CheckErr(err)
// Authenticate backends, if needed // Authenticate backends, if needed
backends.Authenticate(exportBackend, db, viper.GetViper()) token, err := db.GetOAuth2Token(sourceName)
backends.Authenticate(importBackend, db, viper.GetViper()) cobra.CheckErr(err)
auth, err := backends.Authenticate(exportBackend, token, viper.GetViper())
cobra.CheckErr(err)
if auth {
db.SetOAuth2Token(sourceName, token)
}
token, err = db.GetOAuth2Token(targetName)
cobra.CheckErr(err)
auth, err = backends.Authenticate(importBackend, token, viper.GetViper())
cobra.CheckErr(err)
if auth {
defer db.SetOAuth2Token(targetName, token)
}
// Read timestamp // Read timestamp
timestamp := time.Unix(getInt64FromFlag(cmd, "timestamp"), 0) timestamp := time.Unix(getInt64FromFlag(cmd, "timestamp"), 0)

View file

@ -43,15 +43,32 @@ var lovesCmd = &cobra.Command{
targetName, targetConfig := getConfigFromFlag(cmd, "to") targetName, targetConfig := getConfigFromFlag(cmd, "to")
fmt.Printf("Transferring loves from %s to %s...\n", sourceName, targetName) fmt.Printf("Transferring loves from %s to %s...\n", sourceName, targetName)
// Setup database
db, err := storage.New(viper.GetString("database"))
cobra.CheckErr(err)
// Initialize backends // Initialize backends
exportBackend, err := backends.ResolveBackend[models.LovesExport](sourceConfig) exportBackend, err := backends.ResolveBackend[models.LovesExport](sourceConfig)
cobra.CheckErr(err) cobra.CheckErr(err)
importBackend, err := backends.ResolveBackend[models.LovesImport](targetConfig) importBackend, err := backends.ResolveBackend[models.LovesImport](targetConfig)
cobra.CheckErr(err) cobra.CheckErr(err)
// Setup database // Authenticate backends, if needed
db, err := storage.New(viper.GetString("database")) token, err := db.GetOAuth2Token(sourceName)
cobra.CheckErr(err) cobra.CheckErr(err)
auth, err := backends.Authenticate(exportBackend, token, viper.GetViper())
cobra.CheckErr(err)
if auth {
db.SetOAuth2Token(sourceName, token)
}
token, err = db.GetOAuth2Token(targetName)
cobra.CheckErr(err)
auth, err = backends.Authenticate(importBackend, token, viper.GetViper())
cobra.CheckErr(err)
if auth {
defer db.SetOAuth2Token(targetName, token)
}
// Read timestamp // Read timestamp
timestamp := time.Unix(getInt64FromFlag(cmd, "timestamp"), 0) timestamp := time.Unix(getInt64FromFlag(cmd, "timestamp"), 0)

View file

@ -31,6 +31,9 @@ import (
// A listen service backend. // A listen service backend.
// All listen services must implement this interface. // All listen services must implement this interface.
type Backend interface { type Backend interface {
// Return the name of the interface
Name() string
// Initialize the backend from a config. // Initialize the backend from a config.
FromConfig(config *viper.Viper) Backend FromConfig(config *viper.Viper) Backend
} }

View file

@ -24,7 +24,6 @@ package storage
import ( import (
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"os" "os"
"time" "time"
@ -95,11 +94,10 @@ func (db Database) GetOAuth2Token(service string) (*oauth2.Token, error) {
if result.Token != nil { if result.Token != nil {
err = json.Unmarshal(result.Token, &token) err = json.Unmarshal(result.Token, &token)
} }
fmt.Printf("TOK DEC: %v\n", token)
return &token, err return &token, err
} }
func (db Database) SetOAuth2Token(service string, token oauth2.Token) error { func (db Database) SetOAuth2Token(service string, token *oauth2.Token) error {
jsonTok, err := json.Marshal(token) jsonTok, err := json.Marshal(token)
if err != nil { if err != nil {
return err return err

View file

@ -64,7 +64,7 @@ func TestOAuth2TokenUpdate(t *testing.T) {
newToken := oauth2.Token{ newToken := oauth2.Token{
AccessToken: "thetoken", AccessToken: "thetoken",
} }
err = db.SetOAuth2Token(service, newToken) err = db.SetOAuth2Token(service, &newToken)
require.NoError(t, err) require.NoError(t, err)
token, err = db.GetOAuth2Token(service) token, err = db.GetOAuth2Token(service)