From 61de750e0529b881142bb815259b5c03ac047540 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 5 Jul 2015 22:45:51 -0700 Subject: [PATCH] Update plex token cache when password is changed Fixed: New plex.tv password not taking effect immediately Fixed: Prevent an incorrect plex.tv password from locking out account --- .../Plex/PlexAuthenticationException.cs | 14 ++++++ .../Notifications/Plex/PlexServerProxy.cs | 46 ++++++++++++------- .../Notifications/Plex/PlexServerService.cs | 5 ++ src/NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Indexers/Edit/IndexerEditViewTemplate.hbs | 4 +- .../Edit/NotificationEditViewTemplate.hbs | 4 +- 6 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 src/NzbDrone.Core/Notifications/Plex/PlexAuthenticationException.cs diff --git a/src/NzbDrone.Core/Notifications/Plex/PlexAuthenticationException.cs b/src/NzbDrone.Core/Notifications/Plex/PlexAuthenticationException.cs new file mode 100644 index 000000000..86a0d15ec --- /dev/null +++ b/src/NzbDrone.Core/Notifications/Plex/PlexAuthenticationException.cs @@ -0,0 +1,14 @@ +namespace NzbDrone.Core.Notifications.Plex +{ + public class PlexAuthenticationException : PlexException + { + public PlexAuthenticationException(string message) : base(message) + { + } + + public PlexAuthenticationException(string message, params object[] args) + : base(message, args) + { + } + } +} diff --git a/src/NzbDrone.Core/Notifications/Plex/PlexServerProxy.cs b/src/NzbDrone.Core/Notifications/Plex/PlexServerProxy.cs index 192cbff41..6aa8124c1 100644 --- a/src/NzbDrone.Core/Notifications/Plex/PlexServerProxy.cs +++ b/src/NzbDrone.Core/Notifications/Plex/PlexServerProxy.cs @@ -42,7 +42,7 @@ namespace NzbDrone.Core.Notifications.Plex var response = client.Execute(request); _logger.Trace("Sections response: {0}", response.Content); - CheckForError(response); + CheckForError(response, settings); return Json.Deserialize(response.Content) .Directories @@ -58,7 +58,7 @@ namespace NzbDrone.Core.Notifications.Plex var response = client.Execute(request); _logger.Trace("Update response: {0}", response.Content); - CheckForError(response); + CheckForError(response, settings); } public void UpdateSeries(int metadataId, PlexServerSettings settings) @@ -69,7 +69,7 @@ namespace NzbDrone.Core.Notifications.Plex var response = client.Execute(request); _logger.Trace("Update Series response: {0}", response.Content); - CheckForError(response); + CheckForError(response, settings); } public string Version(PlexServerSettings settings) @@ -79,7 +79,7 @@ namespace NzbDrone.Core.Notifications.Plex var response = client.Execute(request); _logger.Trace("Version response: {0}", response.Content); - CheckForError(response); + CheckForError(response, settings); return Json.Deserialize(response.Content).Version; } @@ -91,7 +91,7 @@ namespace NzbDrone.Core.Notifications.Plex var response = client.Execute(request); _logger.Trace("Preferences response: {0}", response.Content); - CheckForError(response); + CheckForError(response, settings); return Json.Deserialize(response.Content).Preferences; } @@ -105,7 +105,7 @@ namespace NzbDrone.Core.Notifications.Plex var response = client.Execute(request); _logger.Trace("Sections response: {0}", response.Content); - CheckForError(response); + CheckForError(response, settings); var item = Json.Deserialize(response.Content) .Items @@ -119,20 +119,18 @@ namespace NzbDrone.Core.Notifications.Plex return item.Id; } - private String Authenticate(string username, string password) + private String Authenticate(PlexServerSettings settings) { var request = GetMyPlexRequest("users/sign_in.json", Method.POST); - var client = GetMyPlexClient(username, password); + var client = GetMyPlexClient(settings.Username, settings.Password); var response = client.Execute(request); _logger.Debug("Authentication Response: {0}", response.Content); - CheckForError(response); + CheckForError(response, settings); var user = Json.Deserialize(JObject.Parse(response.Content).SelectToken("user").ToString()); - _authCache.Set(username, user.AuthenticationToken); - return user.AuthenticationToken; } @@ -170,26 +168,40 @@ namespace NzbDrone.Core.Notifications.Plex var request = new RestRequest(resource, method); request.AddHeader("Accept", "application/json"); - if (!settings.Username.IsNullOrWhiteSpace()) + if (settings.Username.IsNotNullOrWhiteSpace()) { - request.AddParameter("X-Plex-Token", GetAuthenticationToken(settings.Username, settings.Password), ParameterType.HttpHeader); + request.AddParameter("X-Plex-Token", GetAuthenticationToken(settings), ParameterType.HttpHeader); } return request; } - private string GetAuthenticationToken(string username, string password) + private string GetAuthenticationToken(PlexServerSettings settings) { - return _authCache.Get(username, () => Authenticate(username, password)); + var token = _authCache.Get(settings.Username + settings.Password, () => Authenticate(settings)); + + if (token.IsNullOrWhiteSpace()) + { + throw new PlexAuthenticationException("Invalid Token - Update your username and password"); + } + + return token; } - private void CheckForError(IRestResponse response) + private void CheckForError(IRestResponse response, PlexServerSettings settings) { _logger.Trace("Checking for error"); if (response.StatusCode == HttpStatusCode.Unauthorized) { - throw new PlexException("Unauthorized"); + if (settings.Username.IsNullOrWhiteSpace()) + { + throw new PlexAuthenticationException("Unauthorized - Username and password required"); + } + + //Set the token to null in the cache so we don't keep trying with bad credentials + _authCache.Set(settings.Username + settings.Password, null); + throw new PlexAuthenticationException("Unauthorized - Username or password is incorrect"); } var error = Json.Deserialize(response.Content); diff --git a/src/NzbDrone.Core/Notifications/Plex/PlexServerService.cs b/src/NzbDrone.Core/Notifications/Plex/PlexServerService.cs index a17834ed6..bca6fcf05 100644 --- a/src/NzbDrone.Core/Notifications/Plex/PlexServerService.cs +++ b/src/NzbDrone.Core/Notifications/Plex/PlexServerService.cs @@ -151,6 +151,11 @@ namespace NzbDrone.Core.Notifications.Plex return new ValidationFailure("Host", "At least one TV library is required"); } } + catch(PlexAuthenticationException ex) + { + _logger.ErrorException("Unable to connect to Plex Server: " + ex.Message, ex); + return new ValidationFailure("Username", "Incorrect username or password"); + } catch (Exception ex) { _logger.ErrorException("Unable to connect to Plex Server: " + ex.Message, ex); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 1fc36443c..cbcf84be4 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -706,6 +706,7 @@ + diff --git a/src/UI/Settings/Indexers/Edit/IndexerEditViewTemplate.hbs b/src/UI/Settings/Indexers/Edit/IndexerEditViewTemplate.hbs index bdafb4ac1..acfb62cbb 100644 --- a/src/UI/Settings/Indexers/Edit/IndexerEditViewTemplate.hbs +++ b/src/UI/Settings/Indexers/Edit/IndexerEditViewTemplate.hbs @@ -2,9 +2,9 @@