From f36f98e32b2f02f654eb04a169b173226f90c812 Mon Sep 17 00:00:00 2001 From: Qstick Date: Fri, 12 Mar 2021 14:59:04 -0500 Subject: [PATCH] Secret Dev Settings Page --- frontend/src/App/AppRoutes.js | 6 + .../Development/DevelopmentSettings.js | 143 ++++++++++++++++++ .../DevelopmentSettingsConnector.js | 77 ++++++++++ .../src/Store/Actions/Settings/development.js | 64 ++++++++ frontend/src/Store/Actions/settingsActions.js | 5 + .../Configuration/ConfigService.cs | 7 + .../Configuration/IConfigService.cs | 3 + .../Definitions/Cardigann/Cardigann.cs | 6 +- .../Definitions/Cardigann/CardigannBase.cs | 24 ++- .../Definitions/Cardigann/CardigannParser.cs | 15 +- .../Cardigann/CardigannRequestGenerator.cs | 6 +- src/NzbDrone.Core/Indexers/HttpIndexerBase.cs | 6 +- src/NzbDrone.Core/Localization/Core/en.json | 15 +- .../Config/DevelopmentConfigModule.cs | 50 ++++++ .../Config/DevelopmentConfigResource.cs | 30 ++++ .../Config/HostConfigModule.cs | 2 +- 16 files changed, 440 insertions(+), 19 deletions(-) create mode 100644 frontend/src/Settings/Development/DevelopmentSettings.js create mode 100644 frontend/src/Settings/Development/DevelopmentSettingsConnector.js create mode 100644 frontend/src/Store/Actions/Settings/development.js create mode 100644 src/Prowlarr.Api.V1/Config/DevelopmentConfigModule.cs create mode 100644 src/Prowlarr.Api.V1/Config/DevelopmentConfigResource.cs diff --git a/frontend/src/App/AppRoutes.js b/frontend/src/App/AppRoutes.js index fc207ac1b..694207be1 100644 --- a/frontend/src/App/AppRoutes.js +++ b/frontend/src/App/AppRoutes.js @@ -8,6 +8,7 @@ import IndexerIndexConnector from 'Indexer/Index/IndexerIndexConnector'; import StatsConnector from 'Indexer/Stats/StatsConnector'; import SearchIndexConnector from 'Search/SearchIndexConnector'; import ApplicationSettingsConnector from 'Settings/Applications/ApplicationSettingsConnector'; +import DevelopmentSettingsConnector from 'Settings/Development/DevelopmentSettingsConnector'; import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector'; import NotificationSettings from 'Settings/Notifications/NotificationSettings'; import Settings from 'Settings/Settings'; @@ -113,6 +114,11 @@ function AppRoutes(props) { component={UISettingsConnector} /> + + {/* System */} diff --git a/frontend/src/Settings/Development/DevelopmentSettings.js b/frontend/src/Settings/Development/DevelopmentSettings.js new file mode 100644 index 000000000..7c25e2c68 --- /dev/null +++ b/frontend/src/Settings/Development/DevelopmentSettings.js @@ -0,0 +1,143 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import FieldSet from 'Components/FieldSet'; +import Form from 'Components/Form/Form'; +import FormGroup from 'Components/Form/FormGroup'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import PageContent from 'Components/Page/PageContent'; +import PageContentBody from 'Components/Page/PageContentBody'; +import { inputTypes } from 'Helpers/Props'; +import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; +import translate from 'Utilities/String/translate'; + +const logLevelOptions = [ + { key: 'info', value: 'Info' }, + { key: 'debug', value: 'Debug' }, + { key: 'trace', value: 'Trace' } +]; + +class DevelopmentSettings extends Component { + + // + // Render + + render() { + const { + isFetching, + error, + settings, + hasSettings, + onInputChange, + onSavePress, + ...otherProps + } = this.props; + + return ( + + + + + { + isFetching && + + } + + { + !isFetching && error && +
+ {translate('UnableToLoadDevelopmentSettings')} +
+ } + + { + hasSettings && !isFetching && !error && +
+
+ + {translate('SettingsLogRotate')} + + + + + + {translate('SettingsConsoleLogLevel')} + + + + + {translate('SettingsLogSql')} + + + + + + {translate('SettingsIndexerLogging')} + + + +
+ +
+ + {translate('SettingsFilterSentryEvents')} + + + +
+
+ } +
+
+ ); + } + +} + +DevelopmentSettings.propTypes = { + isFetching: PropTypes.bool.isRequired, + error: PropTypes.object, + settings: PropTypes.object.isRequired, + hasSettings: PropTypes.bool.isRequired, + onSavePress: PropTypes.func.isRequired, + onInputChange: PropTypes.func.isRequired +}; + +export default DevelopmentSettings; diff --git a/frontend/src/Settings/Development/DevelopmentSettingsConnector.js b/frontend/src/Settings/Development/DevelopmentSettingsConnector.js new file mode 100644 index 000000000..974cd446a --- /dev/null +++ b/frontend/src/Settings/Development/DevelopmentSettingsConnector.js @@ -0,0 +1,77 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { clearPendingChanges } from 'Store/Actions/baseActions'; +import { fetchDevelopmentSettings, saveDevelopmentSettings, setDevelopmentSettingsValue } from 'Store/Actions/settingsActions'; +import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; +import DevelopmentSettings from './DevelopmentSettings'; + +const SECTION = 'development'; + +function createMapStateToProps() { + return createSelector( + (state) => state.settings.advancedSettings, + createSettingsSectionSelector(SECTION), + (advancedSettings, sectionSettings) => { + return { + advancedSettings, + ...sectionSettings + }; + } + ); +} + +const mapDispatchToProps = { + setDevelopmentSettingsValue, + saveDevelopmentSettings, + fetchDevelopmentSettings, + clearPendingChanges +}; + +class DevelopmentSettingsConnector extends Component { + + // + // Lifecycle + + componentDidMount() { + this.props.fetchDevelopmentSettings(); + } + + componentWillUnmount() { + this.props.clearPendingChanges({ section: `settings.${SECTION}` }); + } + + // + // Listeners + + onInputChange = ({ name, value }) => { + this.props.setDevelopmentSettingsValue({ name, value }); + } + + onSavePress = () => { + this.props.saveDevelopmentSettings(); + } + + // + // Render + + render() { + return ( + + ); + } +} + +DevelopmentSettingsConnector.propTypes = { + setDevelopmentSettingsValue: PropTypes.func.isRequired, + saveDevelopmentSettings: PropTypes.func.isRequired, + fetchDevelopmentSettings: PropTypes.func.isRequired, + clearPendingChanges: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(DevelopmentSettingsConnector); diff --git a/frontend/src/Store/Actions/Settings/development.js b/frontend/src/Store/Actions/Settings/development.js new file mode 100644 index 000000000..f8e37b814 --- /dev/null +++ b/frontend/src/Store/Actions/Settings/development.js @@ -0,0 +1,64 @@ +import { createAction } from 'redux-actions'; +import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; +import createSaveHandler from 'Store/Actions/Creators/createSaveHandler'; +import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; +import { createThunk } from 'Store/thunks'; + +// +// Variables + +const section = 'settings.development'; + +// +// Actions Types + +export const FETCH_DEVELOPMENT_SETTINGS = 'settings/development/fetchDevelopmentSettings'; +export const SET_DEVELOPMENT_SETTINGS_VALUE = 'settings/development/setDevelopmentSettingsValue'; +export const SAVE_DEVELOPMENT_SETTINGS = 'settings/development/saveDevelopmentSettings'; + +// +// Action Creators + +export const fetchDevelopmentSettings = createThunk(FETCH_DEVELOPMENT_SETTINGS); +export const saveDevelopmentSettings = createThunk(SAVE_DEVELOPMENT_SETTINGS); +export const setDevelopmentSettingsValue = createAction(SET_DEVELOPMENT_SETTINGS_VALUE, (payload) => { + return { + section, + ...payload + }; +}); + +// +// Details + +export default { + + // + // State + + defaultState: { + isFetching: false, + isPopulated: false, + error: null, + pendingChanges: {}, + isSaving: false, + saveError: null, + item: {} + }, + + // + // Action Handlers + + actionHandlers: { + [FETCH_DEVELOPMENT_SETTINGS]: createFetchHandler(section, '/config/development'), + [SAVE_DEVELOPMENT_SETTINGS]: createSaveHandler(section, '/config/development') + }, + + // + // Reducers + + reducers: { + [SET_DEVELOPMENT_SETTINGS_VALUE]: createSetSettingValueReducer(section) + } + +}; diff --git a/frontend/src/Store/Actions/settingsActions.js b/frontend/src/Store/Actions/settingsActions.js index 330d42f10..4e9e8dc14 100644 --- a/frontend/src/Store/Actions/settingsActions.js +++ b/frontend/src/Store/Actions/settingsActions.js @@ -2,6 +2,7 @@ import { createAction } from 'redux-actions'; import { handleThunks } from 'Store/thunks'; import createHandleActions from './Creators/createHandleActions'; import applications from './Settings/applications'; +import development from './Settings/development'; import general from './Settings/general'; import indexerCategories from './Settings/indexerCategories'; import indexerFlags from './Settings/indexerFlags'; @@ -15,6 +16,7 @@ export * from './Settings/indexerFlags'; export * from './Settings/languages'; export * from './Settings/notifications'; export * from './Settings/applications'; +export * from './Settings/development'; export * from './Settings/ui'; // @@ -34,6 +36,7 @@ export const defaultState = { languages: languages.defaultState, notifications: notifications.defaultState, applications: applications.defaultState, + development: development.defaultState, ui: ui.defaultState }; @@ -61,6 +64,7 @@ export const actionHandlers = handleThunks({ ...languages.actionHandlers, ...notifications.actionHandlers, ...applications.actionHandlers, + ...development.actionHandlers, ...ui.actionHandlers }); @@ -79,6 +83,7 @@ export const reducers = createHandleActions({ ...languages.reducers, ...notifications.reducers, ...applications.reducers, + ...development.reducers, ...ui.reducers }, defaultState, section); diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs index dfcffeafd..c51653df3 100644 --- a/src/NzbDrone.Core/Configuration/ConfigService.cs +++ b/src/NzbDrone.Core/Configuration/ConfigService.cs @@ -160,6 +160,13 @@ namespace NzbDrone.Core.Configuration set { SetValue("PreferIndexerFlags", value); } } + public bool LogIndexerResponse + { + get { return GetValueBoolean("LogIndexerResponse", false); } + + set { SetValue("LogIndexerResponse", value); } + } + public bool AllowHardcodedSubs { get { return GetValueBoolean("AllowHardcodedSubs", false); } diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs index 9b6e85faa..75397f183 100644 --- a/src/NzbDrone.Core/Configuration/IConfigService.cs +++ b/src/NzbDrone.Core/Configuration/IConfigService.cs @@ -96,6 +96,9 @@ namespace NzbDrone.Core.Configuration int BackupInterval { get; } int BackupRetention { get; } + // Indexers + bool LogIndexerResponse { get; set; } + CertificateValidationType CertificateValidation { get; } } } diff --git a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs index 6c1c03b66..e060b7141 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/Cardigann.cs @@ -22,7 +22,8 @@ namespace NzbDrone.Core.Indexers.Cardigann public override IIndexerRequestGenerator GetRequestGenerator() { - return new CardigannRequestGenerator(_definitionService.GetDefinition(Settings.DefinitionFile), + return new CardigannRequestGenerator(_configService, + _definitionService.GetDefinition(Settings.DefinitionFile), Settings, _logger) { @@ -32,7 +33,8 @@ namespace NzbDrone.Core.Indexers.Cardigann public override IParseIndexerResponse GetParser() { - return new CardigannParser(_definitionService.GetDefinition(Settings.DefinitionFile), + return new CardigannParser(_configService, + _definitionService.GetDefinition(Settings.DefinitionFile), Settings, _logger); } diff --git a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannBase.cs b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannBase.cs index 85a71db98..978e49b73 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannBase.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannBase.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json.Linq; using NLog; using NzbDrone.Common.Extensions; using NzbDrone.Common.Serializer; +using NzbDrone.Core.Configuration; using NzbDrone.Core.Parser; namespace NzbDrone.Core.Indexers.Cardigann @@ -20,6 +21,7 @@ namespace NzbDrone.Core.Indexers.Cardigann protected readonly CardigannSettings _settings; protected readonly Logger _logger; protected readonly Encoding _encoding; + protected readonly IConfigService _configService; protected string SiteLink { get; private set; } @@ -46,10 +48,12 @@ namespace NzbDrone.Core.Indexers.Cardigann protected static readonly Regex _LogicFunctionRegex = new Regex( $@"\b({string.Join("|", _SupportedLogicFunctions.Select(Regex.Escape))})(?:\s+(\(?\.[^\)\s]+\)?|""[^""]+"")){{2,}}"); - public CardigannBase(CardigannDefinition definition, + public CardigannBase(IConfigService configService, + CardigannDefinition definition, CardigannSettings settings, Logger logger) { + _configService = configService; _definition = definition; _settings = settings; _encoding = Encoding.GetEncoding(definition.Encoding); @@ -206,6 +210,7 @@ namespace NzbDrone.Core.Indexers.Cardigann protected Dictionary GetBaseTemplateVariables() { + var indexerLogging = _configService.LogIndexerResponse; var variables = new Dictionary { [".Config.sitelink"] = SiteLink, @@ -221,7 +226,7 @@ namespace NzbDrone.Core.Indexers.Cardigann var name = ".Config." + setting.Name; var value = _settings.ExtraFieldData.GetValueOrDefault(setting.Name, setting.Default); - if (setting.Type != "password") + if (setting.Type != "password" && indexerLogging) { _logger.Trace($"{name} got value {value.ToJson()}"); } @@ -236,11 +241,18 @@ namespace NzbDrone.Core.Indexers.Cardigann } else if (setting.Type == "select") { - _logger.Trace($"Setting options: {setting.Options.ToJson()}"); + if (indexerLogging) + { + _logger.Trace($"Setting options: {setting.Options.ToJson()}"); + } + var sorted = setting.Options.OrderBy(x => x.Key).ToList(); var selected = sorted[(int)(long)value]; - _logger.Debug($"Selected option: {selected.ToJson()}"); + if (indexerLogging) + { + _logger.Debug($"Selected option: {selected.ToJson()}"); + } variables[name] = selected.Key; } @@ -253,7 +265,7 @@ namespace NzbDrone.Core.Indexers.Cardigann throw new NotSupportedException(); } - if (setting.Type != "password") + if (setting.Type != "password" && indexerLogging) { _logger.Debug($"Setting {setting.Name} to {variables[name]}"); } @@ -514,7 +526,7 @@ namespace NzbDrone.Core.Indexers.Cardigann var all = variablesRegExMatches.Groups[0].Value; var variable = variablesRegExMatches.Groups[1].Value; - var value = (string)variables[variable]; + var value = variables[variable].ToString(); if (modifier != null) { value = modifier(value); diff --git a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannParser.cs b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannParser.cs index 95b610003..9ed3d296d 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannParser.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannParser.cs @@ -7,6 +7,7 @@ using AngleSharp.Dom; using AngleSharp.Html.Parser; using NLog; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Configuration; using NzbDrone.Core.Indexers.Exceptions; using NzbDrone.Core.Parser; using NzbDrone.Core.Parser.Model; @@ -17,10 +18,11 @@ namespace NzbDrone.Core.Indexers.Cardigann { public Action, DateTime?> CookiesUpdater { get; set; } - public CardigannParser(CardigannDefinition definition, + public CardigannParser(IConfigService configService, + CardigannDefinition definition, CardigannSettings settings, Logger logger) - : base(definition, settings, logger) + : base(configService, definition, settings, logger) { } @@ -61,7 +63,7 @@ namespace NzbDrone.Core.Indexers.Cardigann { results = ApplyFilters(results, search.Preprocessingfilters, variables); searchResultDocument = searchResultParser.ParseDocument(results); - _logger.Debug(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results)); + _logger.Trace(string.Format("CardigannIndexer ({0}): result after preprocessingfilters: {1}", _definition.Id, results)); } var rowsSelector = ApplyGoTemplateText(search.Rows.Selector, variables); @@ -101,6 +103,7 @@ namespace NzbDrone.Core.Indexers.Cardigann try { var release = new CardigannReleaseInfo(); + var indexerLogging = _configService.LogIndexerResponse; // Parse fields foreach (var field in search.Fields) @@ -334,8 +337,10 @@ namespace NzbDrone.Core.Indexers.Cardigann continue; } - //Parser errors usually happen on every result and are costly to performance, trace only - _logger.Trace("Error while parsing field={0}, selector={1}, value={2}: {3}", field.Key, field.Value.Selector, value == null ? "" : value, ex.Message); + if (indexerLogging) + { + _logger.Trace("Error while parsing field={0}, selector={1}, value={2}: {3}", field.Key, field.Value.Selector, value == null ? "" : value, ex.Message); + } } } diff --git a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs index eff9e71f0..1999ba53e 100644 --- a/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs +++ b/src/NzbDrone.Core/Indexers/Definitions/Cardigann/CardigannRequestGenerator.cs @@ -8,6 +8,7 @@ using AngleSharp.Html.Parser; using Newtonsoft.Json.Linq; using NLog; using NzbDrone.Common.Http; +using NzbDrone.Core.Configuration; using NzbDrone.Core.Indexers.Definitions.Cardigann; using NzbDrone.Core.IndexerSearch.Definitions; using NzbDrone.Core.Parser; @@ -21,10 +22,11 @@ namespace NzbDrone.Core.Indexers.Cardigann protected HttpResponse landingResult; protected IHtmlDocument landingResultDocument; - public CardigannRequestGenerator(CardigannDefinition definition, + public CardigannRequestGenerator(IConfigService configService, + CardigannDefinition definition, CardigannSettings settings, Logger logger) - : base(definition, settings, logger) + : base(configService, definition, settings, logger) { } diff --git a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs index 706a8e636..85e7663e2 100644 --- a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs +++ b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs @@ -406,8 +406,12 @@ namespace NzbDrone.Core.Indexers request.HttpRequest.RateLimit = RateLimit; } + if (_configService.LogIndexerResponse) + { + request.HttpRequest.LogResponseContent = true; + } + request.HttpRequest.AllowAutoRedirect = FollowRedirect; - request.HttpRequest.LogResponseContent = true; Cookies = GetCookies(); diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index edfd9d15e..e0e0393e6 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -72,6 +72,7 @@ "DeleteTag": "Delete Tag", "DeleteTagMessageText": "Are you sure you want to delete the tag '{0}'?", "Details": "Details", + "DevelopmentSettings": "Development Settings", "Disabled": "Disabled", "Docker": "Docker", "Downloading": "Downloading", @@ -96,8 +97,6 @@ "EnableSSL": "Enable SSL", "EnableSslHelpText": " Requires restart running as administrator to take effect", "Error": "Error", - "NewznabVipCheckExpiringClientMessage": "Indexer VIP benefits expiring soon: {0}", - "NewznabVipCheckExpiredClientMessage": "Indexer VIP benefits have expired: {0}", "ErrorLoadingContents": "Error loading contents", "Events": "Events", "EventType": "Event Type", @@ -176,6 +175,8 @@ "Name": "Name", "NetCore": ".NET Core", "New": "New", + "NewznabVipCheckExpiredClientMessage": "Indexer VIP benefits have expired: {0}", + "NewznabVipCheckExpiringClientMessage": "Indexer VIP benefits expiring soon: {0}", "NoBackupsAreAvailable": "No backups are available", "NoChange": "No Change", "NoChanges": "No Changes", @@ -253,12 +254,21 @@ "SendAnonymousUsageData": "Send Anonymous Usage Data", "SetTags": "Set Tags", "Settings": "Settings", + "SettingsConsoleLogLevel": "Console Log Level", "SettingsEnableColorImpairedMode": "Enable Color-Impaired Mode", "SettingsEnableColorImpairedModeHelpText": "Altered style to allow color-impaired users to better distinguish color coded information", + "SettingsFilterSentryEvents": "Filter Analytics Events", + "SettingsFilterSentryEventsHelpText": "Filter known user error events from being sent as Analytics", + "SettingsIndexerLogging": "Enchanced Indexer Logging", + "SettingsIndexerLoggingHelpText": "Log additional Indexer data including response", + "SettingsLogRotate": "Log Rotation", + "SettingsLogRotateHelpText": "Max number of log files to keep saved in logs folder", + "SettingsLogSql": "Log Sql", "SettingsLongDateFormat": "Long Date Format", "SettingsShortDateFormat": "Short Date Format", "SettingsShowRelativeDates": "Show Relative Dates", "SettingsShowRelativeDatesHelpText": "Show relative (Today/Yesterday/etc) or absolute dates", + "SettingsSqlLoggingHelpText": "Log all SQL queries from Prowlarr", "SettingsTimeFormat": "Time Format", "ShowAdvanced": "Show Advanced", "ShownClickToHide": "Shown, click to hide", @@ -306,6 +316,7 @@ "UnableToAddANewIndexerPleaseTryAgain": "Unable to add a new indexer, please try again.", "UnableToAddANewNotificationPleaseTryAgain": "Unable to add a new notification, please try again.", "UnableToLoadBackups": "Unable to load backups", + "UnableToLoadDevelopmentSettings": "Unable to load Development settings", "UnableToLoadGeneralSettings": "Unable to load General settings", "UnableToLoadHistory": "Unable to load history", "UnableToLoadIndexers": "Unable to load Indexers", diff --git a/src/Prowlarr.Api.V1/Config/DevelopmentConfigModule.cs b/src/Prowlarr.Api.V1/Config/DevelopmentConfigModule.cs new file mode 100644 index 000000000..b0612933c --- /dev/null +++ b/src/Prowlarr.Api.V1/Config/DevelopmentConfigModule.cs @@ -0,0 +1,50 @@ +using System.Linq; +using System.Reflection; +using NzbDrone.Core.Authentication; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Validation.Paths; +using Prowlarr.Http; + +namespace Prowlarr.Api.V1.Config +{ + public class DevelopmentConfigModule : ProwlarrRestModule + { + private readonly IConfigFileProvider _configFileProvider; + private readonly IConfigService _configService; + + public DevelopmentConfigModule(IConfigFileProvider configFileProvider, + IConfigService configService) + : base("/config/development") + { + _configFileProvider = configFileProvider; + _configService = configService; + + GetResourceSingle = GetDevelopmentConfig; + GetResourceById = GetDevelopmentConfig; + UpdateResource = SaveDevelopmentConfig; + } + + private DevelopmentConfigResource GetDevelopmentConfig() + { + var resource = DevelopmentConfigResourceMapper.ToResource(_configFileProvider, _configService); + resource.Id = 1; + + return resource; + } + + private DevelopmentConfigResource GetDevelopmentConfig(int id) + { + return GetDevelopmentConfig(); + } + + private void SaveDevelopmentConfig(DevelopmentConfigResource resource) + { + var dictionary = resource.GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.Public) + .ToDictionary(prop => prop.Name, prop => prop.GetValue(resource, null)); + + _configFileProvider.SaveConfigDictionary(dictionary); + _configService.SaveConfigDictionary(dictionary); + } + } +} diff --git a/src/Prowlarr.Api.V1/Config/DevelopmentConfigResource.cs b/src/Prowlarr.Api.V1/Config/DevelopmentConfigResource.cs new file mode 100644 index 000000000..7c7fe31cf --- /dev/null +++ b/src/Prowlarr.Api.V1/Config/DevelopmentConfigResource.cs @@ -0,0 +1,30 @@ +using NzbDrone.Core.Configuration; +using Prowlarr.Http.REST; + +namespace Prowlarr.Api.V1.Config +{ + public class DevelopmentConfigResource : RestResource + { + //Loggings + public string ConsoleLogLevel { get; set; } + public bool LogSql { get; set; } + public bool LogIndexerResponse { get; set; } + public int LogRotate { get; set; } + public bool FilterSentryEvents { get; set; } + } + + public static class DevelopmentConfigResourceMapper + { + public static DevelopmentConfigResource ToResource(this IConfigFileProvider model, IConfigService configService) + { + return new DevelopmentConfigResource + { + ConsoleLogLevel = model.ConsoleLogLevel, + LogSql = model.LogSql, + LogIndexerResponse = configService.LogIndexerResponse, + LogRotate = model.LogRotate, + FilterSentryEvents = model.FilterSentryEvents + }; + } + } +} diff --git a/src/Prowlarr.Api.V1/Config/HostConfigModule.cs b/src/Prowlarr.Api.V1/Config/HostConfigModule.cs index 081b0669a..8d9079dda 100644 --- a/src/Prowlarr.Api.V1/Config/HostConfigModule.cs +++ b/src/Prowlarr.Api.V1/Config/HostConfigModule.cs @@ -81,7 +81,7 @@ namespace Prowlarr.Api.V1.Config private HostConfigResource GetHostConfig() { - var resource = _configFileProvider.ToResource(_configService); + var resource = HostConfigResourceMapper.ToResource(_configFileProvider, _configService); resource.Id = 1; var user = _userService.FindUser();