From fa7732c538223993cf3ada817d53f852965cfd46 Mon Sep 17 00:00:00 2001 From: Philipp Wolfer Date: Tue, 21 Nov 2023 17:51:13 +0100 Subject: [PATCH] Autenticate OAuth backends --- backends/auth.go | 16 +++++----------- backends/dump/dump.go | 2 ++ backends/funkwhale/funkwhale.go | 2 ++ backends/jspf/jspf.go | 2 ++ backends/listenbrainz/listenbrainz.go | 2 ++ backends/maloja/maloja.go | 2 ++ backends/scrobblerlog/scrobblerlog.go | 2 ++ backends/spotify/spotify.go | 2 ++ backends/subsonic/subsonic.go | 2 ++ cmd/auth.go | 2 +- cmd/listens.go | 17 +++++++++++++++-- cmd/loves.go | 21 +++++++++++++++++++-- models/interfaces.go | 3 +++ storage/database.go | 4 +--- storage/database_test.go | 2 +- 15 files changed, 61 insertions(+), 20 deletions(-) diff --git a/backends/auth.go b/backends/auth.go index 214379e..47d71a2 100644 --- a/backends/auth.go +++ b/backends/auth.go @@ -28,7 +28,7 @@ import ( "github.com/spf13/viper" "go.uploadedlobster.com/scotty/models" - "go.uploadedlobster.com/scotty/storage" + "golang.org/x/oauth2" ) 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) } -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) if auth { // FIXME - backendName := "spotify" - redirectURL, err := BuildRedirectURL(config, backendName) + redirectURL, err := BuildRedirectURL(config, backend.Name()) if err != nil { - return err - } - // FIXME - token, err := db.GetOAuth2Token("spotify") - if err != nil { - return err + return auth, err } authenticator.OAuth2Setup(redirectURL.String(), token) } - return nil + return auth, nil } diff --git a/backends/dump/dump.go b/backends/dump/dump.go index e81a1e8..3a9ef68 100644 --- a/backends/dump/dump.go +++ b/backends/dump/dump.go @@ -28,6 +28,8 @@ import ( type DumpBackend struct{} +func (b *DumpBackend) Name() string { return "dump" } + func (b *DumpBackend) FromConfig(config *viper.Viper) models.Backend { return b } diff --git a/backends/funkwhale/funkwhale.go b/backends/funkwhale/funkwhale.go index 1fb8baa..34d91c9 100644 --- a/backends/funkwhale/funkwhale.go +++ b/backends/funkwhale/funkwhale.go @@ -36,6 +36,8 @@ type FunkwhaleApiBackend struct { username string } +func (b *FunkwhaleApiBackend) Name() string { return "funkwhale" } + func (b *FunkwhaleApiBackend) FromConfig(config *viper.Viper) models.Backend { b.client = NewClient( config.GetString("server-url"), diff --git a/backends/jspf/jspf.go b/backends/jspf/jspf.go index f99f09d..12470be 100644 --- a/backends/jspf/jspf.go +++ b/backends/jspf/jspf.go @@ -39,6 +39,8 @@ type JspfBackend struct { tracks []Track } +func (b *JspfBackend) Name() string { return "jspf" } + func (b *JspfBackend) FromConfig(config *viper.Viper) models.Backend { b.filePath = config.GetString("file-path") b.title = config.GetString("title") diff --git a/backends/listenbrainz/listenbrainz.go b/backends/listenbrainz/listenbrainz.go index 971193c..8f63537 100644 --- a/backends/listenbrainz/listenbrainz.go +++ b/backends/listenbrainz/listenbrainz.go @@ -36,6 +36,8 @@ type ListenBrainzApiBackend struct { existingMbids map[string]bool } +func (b *ListenBrainzApiBackend) Name() string { return "listenbrainz" } + func (b *ListenBrainzApiBackend) FromConfig(config *viper.Viper) models.Backend { b.client = NewClient(config.GetString("token")) b.client.MaxResults = MaxItemsPerGet diff --git a/backends/maloja/maloja.go b/backends/maloja/maloja.go index 060fd3e..1f93583 100644 --- a/backends/maloja/maloja.go +++ b/backends/maloja/maloja.go @@ -36,6 +36,8 @@ type MalojaApiBackend struct { nofix bool } +func (b *MalojaApiBackend) Name() string { return "maloja" } + func (b *MalojaApiBackend) FromConfig(config *viper.Viper) models.Backend { b.client = NewClient( config.GetString("server-url"), diff --git a/backends/scrobblerlog/scrobblerlog.go b/backends/scrobblerlog/scrobblerlog.go index b6fd4a7..e373e0b 100644 --- a/backends/scrobblerlog/scrobblerlog.go +++ b/backends/scrobblerlog/scrobblerlog.go @@ -37,6 +37,8 @@ type ScrobblerLogBackend struct { log ScrobblerLog } +func (b *ScrobblerLogBackend) Name() string { return "scrobbler-log" } + func (b *ScrobblerLogBackend) FromConfig(config *viper.Viper) models.Backend { b.filePath = config.GetString("file-path") b.includeSkipped = config.GetBool("include-skipped") diff --git a/backends/spotify/spotify.go b/backends/spotify/spotify.go index d40db39..cd69696 100644 --- a/backends/spotify/spotify.go +++ b/backends/spotify/spotify.go @@ -40,6 +40,8 @@ type SpotifyApiBackend struct { clientSecret string } +func (b *SpotifyApiBackend) Name() string { return "spotify" } + func (b *SpotifyApiBackend) FromConfig(config *viper.Viper) models.Backend { b.clientId = config.GetString("client-id") b.clientSecret = config.GetString("client-secret") diff --git a/backends/subsonic/subsonic.go b/backends/subsonic/subsonic.go index 7f7e630..9a04251 100644 --- a/backends/subsonic/subsonic.go +++ b/backends/subsonic/subsonic.go @@ -36,6 +36,8 @@ type SubsonicApiBackend struct { password string } +func (b *SubsonicApiBackend) Name() string { return "subsonic" } + func (b *SubsonicApiBackend) FromConfig(config *viper.Viper) models.Backend { b.client = subsonic.Client{ Client: &http.Client{}, diff --git a/cmd/auth.go b/cmd/auth.go index c987d5a..d358cda 100644 --- a/cmd/auth.go +++ b/cmd/auth.go @@ -96,7 +96,7 @@ var authCmd = &cobra.Command{ db, err := storage.New(viper.GetString("database")) cobra.CheckErr(err) - err = db.SetOAuth2Token(serviceName, *tok) + err = db.SetOAuth2Token(serviceName, tok) cobra.CheckErr(err) // oauth2.Token{ diff --git a/cmd/listens.go b/cmd/listens.go index d593033..a564866 100644 --- a/cmd/listens.go +++ b/cmd/listens.go @@ -54,8 +54,21 @@ var listensCmd = &cobra.Command{ cobra.CheckErr(err) // Authenticate backends, if needed - backends.Authenticate(exportBackend, db, viper.GetViper()) - backends.Authenticate(importBackend, db, viper.GetViper()) + token, err := db.GetOAuth2Token(sourceName) + 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 timestamp := time.Unix(getInt64FromFlag(cmd, "timestamp"), 0) diff --git a/cmd/loves.go b/cmd/loves.go index 5a70e6e..2ec458b 100644 --- a/cmd/loves.go +++ b/cmd/loves.go @@ -43,15 +43,32 @@ var lovesCmd = &cobra.Command{ targetName, targetConfig := getConfigFromFlag(cmd, "to") 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 exportBackend, err := backends.ResolveBackend[models.LovesExport](sourceConfig) cobra.CheckErr(err) importBackend, err := backends.ResolveBackend[models.LovesImport](targetConfig) cobra.CheckErr(err) - // Setup database - db, err := storage.New(viper.GetString("database")) + // Authenticate backends, if needed + token, err := db.GetOAuth2Token(sourceName) 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 timestamp := time.Unix(getInt64FromFlag(cmd, "timestamp"), 0) diff --git a/models/interfaces.go b/models/interfaces.go index bc2d6a2..37c4308 100644 --- a/models/interfaces.go +++ b/models/interfaces.go @@ -31,6 +31,9 @@ import ( // A listen service backend. // All listen services must implement this interface. type Backend interface { + // Return the name of the interface + Name() string + // Initialize the backend from a config. FromConfig(config *viper.Viper) Backend } diff --git a/storage/database.go b/storage/database.go index 32d3227..44e1223 100644 --- a/storage/database.go +++ b/storage/database.go @@ -24,7 +24,6 @@ package storage import ( "encoding/json" - "fmt" "log" "os" "time" @@ -95,11 +94,10 @@ func (db Database) GetOAuth2Token(service string) (*oauth2.Token, error) { if result.Token != nil { err = json.Unmarshal(result.Token, &token) } - fmt.Printf("TOK DEC: %v\n", token) 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) if err != nil { return err diff --git a/storage/database_test.go b/storage/database_test.go index b58bef8..664a881 100644 --- a/storage/database_test.go +++ b/storage/database_test.go @@ -64,7 +64,7 @@ func TestOAuth2TokenUpdate(t *testing.T) { newToken := oauth2.Token{ AccessToken: "thetoken", } - err = db.SetOAuth2Token(service, newToken) + err = db.SetOAuth2Token(service, &newToken) require.NoError(t, err) token, err = db.GetOAuth2Token(service)