diff --git a/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs b/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs index c18b204e5..d2db5644b 100644 --- a/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs +++ b/src/NzbDrone.Core/Books/Calibre/CalibreProxy.cs @@ -537,15 +537,19 @@ namespace NzbDrone.Core.Books.Calibre return response.Resource; } - private bool CalibreLoginEnabled(CalibreSettings settings) + private bool HasWriteAccess(CalibreSettings settings) { - var builder = GetBuilder($"/book-get-last-read-position/{settings.Library}/1", settings); - builder.SuppressHttpError = true; + var request = GetBuilder($"cdb/cmd/saved_searches", settings) + .Post() + .SetHeader("Content-Type", "application/json") + .Build(); + + request.SuppressHttpError = true; + request.SetContent("[\"list\"]"); - var request = builder.Build(); var response = _httpClient.Get(request); - return response.StatusCode != HttpStatusCode.NotFound; + return response.StatusCode != HttpStatusCode.Forbidden; } private HttpRequestBuilder GetBuilder(string relativePath, CalibreSettings settings) @@ -604,16 +608,6 @@ namespace NzbDrone.Core.Books.Calibre private ValidationFailure TestCalibre(CalibreSettings settings) { - var authRequired = settings.Host != "127.0.0.1" && settings.Host != "::1" && settings.Host != "localhost"; - - if (authRequired && settings.Username.IsNullOrWhiteSpace()) - { - return new NzbDroneValidationFailure("Username", "Username required") - { - DetailedDescription = "A username/password is required for non-local Calibre servers to allow write access" - }; - } - var builder = GetBuilder("", settings); builder.Accept(HttpAccept.Html); builder.SuppressHttpError = true; @@ -661,38 +655,18 @@ namespace NzbDrone.Core.Books.Calibre return new ValidationFailure("Port", "Not a valid Calibre content server. See https://manual.calibre-ebook.com/server.html"); } - CalibreLibraryInfo libraryInfo; - try + if (!HasWriteAccess(settings)) { - libraryInfo = GetLibraryInfo(settings); - } - catch (HttpException e) - { - if (e.Response.StatusCode == HttpStatusCode.Unauthorized) - { - return new NzbDroneValidationFailure("Username", "Authentication failure") - { - DetailedDescription = "Please verify your username and password." - }; - } - else - { - return new NzbDroneValidationFailure(string.Empty, "Unknown exception: " + e.Message); - } + return new ValidationFailure("Username", "Readarr needs write access. Configure a user or trusted IP in calibre. See See https://manual.calibre-ebook.com/server.html"); } + var libraryInfo = GetLibraryInfo(settings); + if (settings.Library.IsNullOrWhiteSpace()) { settings.Library = libraryInfo.DefaultLibrary; } - // now that we have library info, double check if auth is actually enabled calibre side. If not, we'll get a 404 back. - // https://github.com/kovidgoyal/calibre/blob/bf53bbf07a6ced728bf6a87d097fb6eb8c67e4e0/src/calibre/srv/books.py#L196 - if (authRequired && !CalibreLoginEnabled(settings)) - { - return new ValidationFailure("Host", "Remote calibre server must have authentication enabled to allow Readarr write access"); - } - if (!libraryInfo.LibraryMap.ContainsKey(settings.Library)) { return new ValidationFailure("Library", "Not a valid library in calibre");