From 0ea5d55b8a069231e5ace5d3f4e3d185c8a57c7f Mon Sep 17 00:00:00 2001 From: Ben Sarmiento Date: Wed, 10 Jan 2024 23:42:14 +0100 Subject: [PATCH] Rework basic auth --- README.md | 4 +++- config.example.yml | 6 ++--- internal/config/types.go | 4 ++-- internal/handlers/basicauth.go | 41 ++++++++++++++++++++++++++++------ internal/torrent/repair.go | 3 --- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 0cbc142..3c0965b 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ docker pull ghcr.io/debridmediamanager/zurg-testing:latest docker pull ghcr.io/debridmediamanager/zurg-testing:v0.9.3 ``` -## How to run zurg in 5 steps for Plex +## How to run zurg in 5 steps for Plex with Docker 1. Clone this repo `git clone https://github.com/debridmediamanager/zurg-testing.git` 2. Add your token in `config.yml` @@ -24,6 +24,8 @@ docker pull ghcr.io/debridmediamanager/zurg-testing:v0.9.3 A webdav server is also exposed to your localhost via port `9999`. +### Note: when using zurg in a server outside of your home network, ensure that "Use my Remote Traffic automatically when needed" is unchecked on your [Account page](https://real-debrid.com/account) + ## Why zurg? Why not X? - Better performance than anything out there; changes in your library appear instantly ([assuming Plex picks it up fast enough](./plex_update.sh)) diff --git a/config.example.yml b/config.example.yml index d11756b..7607b23 100644 --- a/config.example.yml +++ b/config.example.yml @@ -6,9 +6,9 @@ token: YOUR_RD_API_TOKEN # https://real-debrid.com/apitoken host: "[::]" port: 9999 -# you can protect zurg server with username+password auth -username: yowmamasita -password: 1234 +# you can protect zurg's webdav server with username+password auth +# webdav_username: yowmamasita +# webdav_password: 1234 # How many requests in parallel should we send to Real-Debrid API? concurrent_workers: 20 diff --git a/internal/config/types.go b/internal/config/types.go index bd10cfd..67310ff 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -37,8 +37,8 @@ type ZurgConfig struct { Host string `yaml:"host" json:"host"` Port string `yaml:"port" json:"port"` - Username string `yaml:"username" json:"username"` - Password string `yaml:"password" json:"password"` + Username string `yaml:"webdav_username" json:"webdav_username"` + Password string `yaml:"webdav_password" json:"webdav_password"` NumOfWorkers int `yaml:"concurrent_workers" json:"concurrent_workers"` RefreshEverySeconds int `yaml:"check_for_changes_every_secs" json:"check_for_changes_every_secs"` diff --git a/internal/handlers/basicauth.go b/internal/handlers/basicauth.go index a6f0268..08c809b 100644 --- a/internal/handlers/basicauth.go +++ b/internal/handlers/basicauth.go @@ -1,17 +1,44 @@ package handlers -import "net/http" +import ( + "net/http" + "strings" +) +// basicAuth is a middleware that performs basic authentication. func (hs *Handlers) basicAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - username, password, ok := r.BasicAuth() - if !ok || username != hs.cfg.GetUsername() || password != hs.cfg.GetPassword() { - w.Header().Set("WWW-Authenticate", `Basic realm="restricted"`) - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte(http.StatusText(http.StatusUnauthorized))) - return + if r.Method != "OPTIONS" && needsAuth(r.URL.Path) { + if !hs.authenticate(r) { + hs.unauthorized(w) + return + } } next.ServeHTTP(w, r) }) } + +// needsAuth checks if the given path requires authentication. +func needsAuth(path string) bool { + authenticatedPaths := []string{"/dav/", "/infuse/"} + for _, p := range authenticatedPaths { + if strings.HasPrefix(path, p) { + return true + } + } + return false +} + +// authenticate performs the basic authentication check. +func (hs *Handlers) authenticate(r *http.Request) bool { + username, password, ok := r.BasicAuth() + return ok && username == hs.cfg.GetUsername() && password == hs.cfg.GetPassword() +} + +// unauthorized sends an unauthorized response. +func (hs *Handlers) unauthorized(w http.ResponseWriter) { + w.Header().Set("WWW-Authenticate", `Basic realm="restricted"`) + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte(http.StatusText(http.StatusUnauthorized))) +} diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index e6617e7..d14bd01 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -35,13 +35,10 @@ func (t *TorrentManager) repairAll() { if torrent.AnyInProgress() || torrent.Unfixable { return } - // Check if the current group is full if currentGroup.Cardinality() >= maxGroupSize { - // Create a new group and add it to the hashGroups currentGroup = mapset.NewSet[string]() hashGroups = append(hashGroups, currentGroup) } - // Add the hash to the current group currentGroup.Add(torrent.Hash) })