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}?",