diff --git a/.env.example b/.env.example index dc417df..b75f93b 100644 --- a/.env.example +++ b/.env.example @@ -41,3 +41,17 @@ PREFERRED_DEVICES="Living Room@192.168.1.100:8090;Kitchen@192.168.1.101;192.168. # Alternative format examples: # PREFERRED_DEVICES="192.168.178.35;192.168.178.28" # PREFERRED_DEVICES="SoundTouch 10@192.168.178.35;SoundTouch 20@192.168.178.28" + +# Spotify Integration +# Create an app at https://developer.spotify.com/dashboard +# SPOTIFY_CLIENT_ID=your_client_id +# SPOTIFY_CLIENT_SECRET=your_client_secret +# SPOTIFY_REDIRECT_URI=https://your-server.example.com/mgmt/spotify/confirm + +# Management API Authentication +# Protects /mgmt/* endpoints (Spotify token access, account management) +MGMT_USERNAME=admin +MGMT_PASSWORD=change_me! + +# External base URL (required when behind a reverse proxy for OAuth callbacks) +# BASE_URL=https://your-server.example.com diff --git a/cmd/soundtouch-service/main.go b/cmd/soundtouch-service/main.go index bf96ae4..1f0feeb 100644 --- a/cmd/soundtouch-service/main.go +++ b/cmd/soundtouch-service/main.go @@ -184,12 +184,6 @@ func main() { Value: "change_me!", EnvVars: []string{"MGMT_PASSWORD"}, }, - &cli.BoolFlag{ - Name: "zeroconf-primer-enabled", - Usage: "Enable ZeroConf Spotify primer for speakers", - Value: true, - EnvVars: []string{"ZEROCONF_PRIMER_ENABLED"}, - }, &cli.StringFlag{ Name: "base-url", Usage: "External base URL for OAuth callbacks behind reverse proxy", @@ -226,7 +220,6 @@ func main() { server.SetDNSSettings(persisted.DNSEnabled, persisted.DNSUpstream, persisted.DNSBindAddr) server.SetSpotifyConfig(config.spotifyClientID, config.spotifyClientSecret, config.spotifyRedirectURI) server.SetMgmtConfig(config.mgmtUsername, config.mgmtPassword) - server.SetZeroconfEnabled(config.zeroconfEnabled) server.SetBaseURL(config.baseURL) if config.spotifyClientID != "" { @@ -362,7 +355,6 @@ type serviceConfig struct { spotifyRedirectURI string mgmtUsername string mgmtPassword string - zeroconfEnabled bool baseURL string } @@ -427,7 +419,6 @@ func loadConfig(c *cli.Context) serviceConfig { spotifyRedirectURI := c.String("spotify-redirect-uri") mgmtUsername := c.String("mgmt-username") mgmtPassword := c.String("mgmt-password") - zeroconfEnabled := c.Bool("zeroconf-primer-enabled") baseURL := c.String("base-url") return serviceConfig{ @@ -453,7 +444,6 @@ func loadConfig(c *cli.Context) serviceConfig { spotifyRedirectURI: spotifyRedirectURI, mgmtUsername: mgmtUsername, mgmtPassword: mgmtPassword, - zeroconfEnabled: zeroconfEnabled, baseURL: baseURL, } } @@ -668,14 +658,21 @@ func setupRouter(server *handlers.Server) *chi.Mux { }) r.Route("/mgmt", func(r chi.Router) { - r.Use(server.BasicAuthMgmt()) - r.Get("/accounts/{accountId}/speakers", server.HandleMgmtListSpeakers) - r.Get("/devices/{deviceId}/events", server.HandleMgmtDeviceEvents) - r.Post("/spotify/init", server.HandleMgmtSpotifyInit) - r.Post("/spotify/confirm", server.HandleMgmtSpotifyConfirm) - r.Get("/spotify/accounts", server.HandleMgmtSpotifyAccounts) - r.Get("/spotify/token", server.HandleMgmtSpotifyToken) - r.Post("/spotify/entity", server.HandleMgmtSpotifyEntity) + // OAuth callback — no auth required (browser redirect from Spotify). + // The authorization code is single-use, short-lived, and useless without + // the client_secret (which only the server has). + r.Get("/spotify/confirm", server.HandleMgmtSpotifyConfirm) + + // All other management endpoints require Basic Auth. + r.Group(func(r chi.Router) { + r.Use(server.BasicAuthMgmt()) + r.Get("/accounts/{accountId}/speakers", server.HandleMgmtListSpeakers) + r.Get("/devices/{deviceId}/events", server.HandleMgmtDeviceEvents) + r.Post("/spotify/init", server.HandleMgmtSpotifyInit) + r.Get("/spotify/accounts", server.HandleMgmtSpotifyAccounts) + r.Get("/spotify/token", server.HandleMgmtSpotifyToken) + r.Post("/spotify/entity", server.HandleMgmtSpotifyEntity) + }) }) r.Get("/proxy/*", server.HandleProxyRequest) diff --git a/pkg/service/handlers/server.go b/pkg/service/handlers/server.go index 8f534db..a2f688e 100644 --- a/pkg/service/handlers/server.go +++ b/pkg/service/handlers/server.go @@ -46,7 +46,6 @@ type Server struct { spotifyClientID string spotifyClientSecret string spotifyRedirectURI string - zeroconfEnabled bool baseURL string spotifyService *spotify.SpotifyService } @@ -243,14 +242,6 @@ func (s *Server) SetMgmtConfig(username, password string) { s.mgmtPassword = password } -// SetZeroconfEnabled sets whether ZeroConf Spotify primer is enabled. -func (s *Server) SetZeroconfEnabled(enabled bool) { - s.mu.Lock() - defer s.mu.Unlock() - - s.zeroconfEnabled = enabled -} - // SetBaseURL sets the external base URL for OAuth callbacks. func (s *Server) SetBaseURL(baseURL string) { s.mu.Lock()