From cb1fd39cb3840c1ec50510ddf14f522682f0881b Mon Sep 17 00:00:00 2001 From: Bogdan Date: Mon, 8 May 2023 06:56:26 +0300 Subject: [PATCH] API key improvements Fixed: Special characters in API key New: Add heathcheck for API Key (cherry picked from commit 9325140b90f8ac625ae5b26075748c22f6f06158) --- frontend/src/Components/SignalRConnector.js | 4 +-- .../Indexer/Index/Table/IndexerIndexRow.tsx | 6 +++- .../Checks/ApiKeyValidationCheck.cs | 35 +++++++++++++++++++ src/NzbDrone.Core/Localization/Core/en.json | 1 + 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/NzbDrone.Core/HealthCheck/Checks/ApiKeyValidationCheck.cs diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js index 3c10c2754..28c12df12 100644 --- a/frontend/src/Components/SignalRConnector.js +++ b/frontend/src/Components/SignalRConnector.js @@ -54,7 +54,7 @@ function Logger(minimumLogLevel) { } Logger.prototype.cleanse = function(message) { - const apikey = new RegExp(`access_token=${window.Prowlarr.apiKey}`, 'g'); + const apikey = new RegExp(`access_token=${encodeURIComponent(window.Prowlarr.apiKey)}`, 'g'); return message.replace(apikey, 'access_token=(removed)'); }; @@ -98,7 +98,7 @@ class SignalRConnector extends Component { this.connection = new signalR.HubConnectionBuilder() .configureLogging(new Logger(signalR.LogLevel.Information)) - .withUrl(`${url}?access_token=${window.Prowlarr.apiKey}`) + .withUrl(`${url}?access_token=${encodeURIComponent(window.Prowlarr.apiKey)}`) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: (retryContext) => { if (retryContext.elapsedMilliseconds > 180000) { diff --git a/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx b/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx index b5a7f7f36..7bda8a287 100644 --- a/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx +++ b/frontend/src/Indexer/Index/Table/IndexerIndexRow.tsx @@ -55,7 +55,11 @@ function IndexerIndexRow(props: IndexerIndexRowProps) { const vipExpiration = fields.find((field) => field.name === 'vipExpiration')?.value ?? ''; - const rssUrl = `${window.location.origin}${window.Prowlarr.urlBase}/${id}/api?t=search&extended=1&apikey=${window.Prowlarr.apiKey}`; + const rssUrl = `${window.location.origin}${ + window.Prowlarr.urlBase + }/${id}/api?apikey=${encodeURIComponent( + window.Prowlarr.apiKey + )}&extended=1&t=search`; const [isEditIndexerModalOpen, setIsEditIndexerModalOpen] = useState(false); const [isDeleteIndexerModalOpen, setIsDeleteIndexerModalOpen] = diff --git a/src/NzbDrone.Core/HealthCheck/Checks/ApiKeyValidationCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/ApiKeyValidationCheck.cs new file mode 100644 index 000000000..77e76d2a3 --- /dev/null +++ b/src/NzbDrone.Core/HealthCheck/Checks/ApiKeyValidationCheck.cs @@ -0,0 +1,35 @@ +using NLog; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Configuration.Events; +using NzbDrone.Core.Lifecycle; +using NzbDrone.Core.Localization; + +namespace NzbDrone.Core.HealthCheck.Checks +{ + [CheckOn(typeof(ApplicationStartedEvent))] + [CheckOn(typeof(ConfigSavedEvent))] + public class ApiKeyValidationCheck : HealthCheckBase + { + private readonly IConfigFileProvider _configFileProvider; + private readonly Logger _logger; + + public ApiKeyValidationCheck(IConfigFileProvider configFileProvider, ILocalizationService localizationService, Logger logger) + : base(localizationService) + { + _configFileProvider = configFileProvider; + _logger = logger; + } + + public override HealthCheck Check() + { + if (_configFileProvider.ApiKey.Length < 20) + { + _logger.Warn("Please update your API key to be at least 20 characters long. You can do this via settings or the config file"); + + return new HealthCheck(GetType(), HealthCheckResult.Warning, _localizationService.GetLocalizedString("ApiKeyValidationHealthCheckMessage"), "#invalid-api-key"); + } + + return new HealthCheck(GetType()); + } + } +} diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 48d631a9a..a2aae24d0 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -23,6 +23,7 @@ "Analytics": "Analytics", "AnalyticsEnabledHelpText": "Send anonymous usage and error information to Prowlarr's servers. This includes information on your browser, which Prowlarr WebUI pages you use, error reporting as well as OS and runtime version. We will use this information to prioritize features and bug fixes.", "ApiKey": "API Key", + "ApiKeyValidationHealthCheckMessage": "Please update your API key to be at least 20 characters long. You can do this via settings or the config file", "AppDataDirectory": "AppData directory", "AppDataLocationHealthCheckMessage": "Updating will not be possible to prevent deleting AppData on Update", "AppProfileDeleteConfirm": "Are you sure you want to delete {0}?",