mirror of
https://git.sr.ht/~phw/scotty
synced 2025-04-16 01:59:29 +02:00
Autenticate OAuth backends
This commit is contained in:
parent
94704f9cd0
commit
fa7732c538
15 changed files with 61 additions and 20 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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{},
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
21
cmd/loves.go
21
cmd/loves.go
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Reference in a new issue