1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-21 16:54:30 -04:00

Compare commits

...

9 Commits

Author SHA1 Message Date
Bogdan
c96b3c4b0b Fixed: Autotagging Genres are case insensitive
(cherry picked from commit 87ecbf39c1c0cc8a3a3f4ee1d1878b34ea49f6b8)

Closes #9436
2023-11-20 00:59:06 +02:00
Mark McDowall
78bc9f9b4b Fixed: Saving indexer, download client, etc settings
(cherry picked from commit 804a5921b3b620e2407d5d6a7fd69fb1fd9b0cbf)
2023-11-20 00:53:45 +02:00
Servarr
b737f05a83 Automated API Docs update 2023-11-19 22:40:17 +02:00
Bogdan
8d96fd2387 More cleanup appName tokens 2023-11-19 22:35:57 +02:00
servarr[bot]
6c487ead00 Fixed: Disable SSL when using the removed SslCertHash configuration (#9426)
(cherry picked from commit d95660d3c78d1ee11a7966d58e78a82a8df01393)

Co-authored-by: Mark McDowall <mark@mcdowall.ca>
2023-11-19 21:46:06 +02:00
Bogdan
22e3cf844c New: Confirmation before clearing blocklist
(cherry picked from commit 366d8a4e78e024bc045e4791d3a51af391f4e95a)

Closes #9429
Fixes #9401
2023-11-19 21:17:00 +02:00
Bogdan
14b4b5e122 Cleanup appName tokens
Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com>

Closes #9430
2023-11-19 21:14:48 +02:00
Mark McDowall
10f5f3c5c8 New: Require password confirmation when setting or changing password
(cherry picked from commit b248163df598dc611ee919d525eb7357256d73d5)
2023-11-19 21:10:52 +02:00
Bogdan
c687b552f0 Bump version to 5.2.2 2023-11-19 07:06:29 +02:00
26 changed files with 140 additions and 40 deletions

View File

@@ -9,7 +9,7 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '5.2.1'
majorVersion: '5.2.2'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'

View File

@@ -36,6 +36,7 @@ class Blocklist extends Component {
lastToggled: null,
selectedState: {},
isConfirmRemoveModalOpen: false,
isConfirmClearModalOpen: false,
items: props.items
};
}
@@ -90,6 +91,19 @@ class Blocklist extends Component {
this.setState({ isConfirmRemoveModalOpen: false });
};
onClearBlocklistPress = () => {
this.setState({ isConfirmClearModalOpen: true });
};
onClearBlocklistConfirmed = () => {
this.props.onClearBlocklistPress();
this.setState({ isConfirmClearModalOpen: false });
};
onConfirmClearModalClose = () => {
this.setState({ isConfirmClearModalOpen: false });
};
//
// Render
@@ -103,7 +117,6 @@ class Blocklist extends Component {
totalRecords,
isRemoving,
isClearingBlocklistExecuting,
onClearBlocklistPress,
...otherProps
} = this.props;
@@ -111,7 +124,8 @@ class Blocklist extends Component {
allSelected,
allUnselected,
selectedState,
isConfirmRemoveModalOpen
isConfirmRemoveModalOpen,
isConfirmClearModalOpen
} = this.state;
const selectedIds = this.getSelectedIds();
@@ -131,8 +145,9 @@ class Blocklist extends Component {
<PageToolbarButton
label={translate('Clear')}
iconName={icons.CLEAR}
isDisabled={!items.length}
isSpinning={isClearingBlocklistExecuting}
onPress={onClearBlocklistPress}
onPress={this.onClearBlocklistPress}
/>
</PageToolbarSection>
@@ -215,6 +230,16 @@ class Blocklist extends Component {
onConfirm={this.onRemoveSelectedConfirmed}
onCancel={this.onConfirmRemoveModalClose}
/>
<ConfirmModal
isOpen={isConfirmClearModalOpen}
kind={kinds.DANGER}
title={translate('ClearBlocklist')}
message={translate('ClearBlocklistMessageText')}
confirmLabel={translate('Clear')}
onConfirm={this.onClearBlocklistConfirmed}
onCancel={this.onConfirmClearModalClose}
/>
</PageContent>
);
}

View File

@@ -65,12 +65,12 @@ function AppUpdatedModalContent(props) {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{translate('AppUpdated', { appName: 'Radarr' })}
{translate('AppUpdated')}
</ModalHeader>
<ModalBody>
<div>
<InlineMarkdown data={translate('AppUpdatedVersion', { appName: 'Radarr', version })} blockClassName={styles.version} />
<InlineMarkdown data={translate('AppUpdatedVersion', { version })} blockClassName={styles.version} />
</div>
{

View File

@@ -28,11 +28,11 @@ function ConnectionLostModal(props) {
<ModalBody>
<div>
{translate('ConnectionLostToBackend', { appName: 'Radarr' })}
{translate('ConnectionLostToBackend')}
</div>
<div className={styles.automatic}>
{translate('ConnectionLostReconnect', { appName: 'Radarr' })}
{translate('ConnectionLostReconnect')}
</div>
</ModalBody>
<ModalFooter>

View File

@@ -34,7 +34,8 @@ function AuthenticationRequiredModalContent(props) {
authenticationMethod,
authenticationRequired,
username,
password
password,
passwordConfirmation
} = settings;
const authenticationEnabled = authenticationMethod && authenticationMethod.value !== 'none';
@@ -63,7 +64,7 @@ function AuthenticationRequiredModalContent(props) {
className={styles.authRequiredAlert}
kind={kinds.WARNING}
>
{translate('AuthenticationRequiredWarning', { appName: 'Radarr' })}
{translate('AuthenticationRequiredWarning')}
</Alert>
{
@@ -76,7 +77,7 @@ function AuthenticationRequiredModalContent(props) {
type={inputTypes.SELECT}
name="authenticationMethod"
values={authenticationMethodOptions}
helpText={translate('AuthenticationMethodHelpText', { appName: 'Radarr' })}
helpText={translate('AuthenticationMethodHelpText')}
helpTextWarning={authenticationMethod.value === 'none' ? translate('AuthenticationMethodHelpTextWarning') : undefined}
helpLink="https://wiki.servarr.com/radarr/faq#forced-authentication"
onChange={onInputChange}
@@ -120,6 +121,18 @@ function AuthenticationRequiredModalContent(props) {
{...password}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('PasswordConfirmation')}</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="passwordConfirmation"
onChange={onInputChange}
helpTextWarning={passwordConfirmation?.value ? undefined : translate('AuthenticationRequiredPasswordConfirmationHelpTextWarning')}
{...passwordConfirmation}
/>
</FormGroup>
</div> :
null
}

View File

@@ -124,6 +124,7 @@ class SecuritySettings extends Component {
authenticationRequired,
username,
password,
passwordConfirmation,
apiKey,
certificateValidation
} = settings;
@@ -139,8 +140,8 @@ class SecuritySettings extends Component {
type={inputTypes.SELECT}
name="authenticationMethod"
values={authenticationMethodOptions}
helpText={translate('AuthenticationMethodHelpText', { appName: 'Radarr' })}
helpTextWarning={translate('AuthenticationRequiredWarning', { appName: 'Radarr' })}
helpText={translate('AuthenticationMethodHelpText')}
helpTextWarning={translate('AuthenticationRequiredWarning')}
onChange={onInputChange}
{...authenticationMethod}
/>
@@ -193,6 +194,21 @@ class SecuritySettings extends Component {
null
}
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('PasswordConfirmation')}</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="passwordConfirmation"
onChange={onInputChange}
{...passwordConfirmation}
/>
</FormGroup> :
null
}
<FormGroup>
<FormLabel>{translate('ApiKey')}</FormLabel>

View File

@@ -83,7 +83,7 @@ function UpdateSettings(props) {
type={inputTypes.CHECK}
name="updateAutomatically"
helpText={translate('UpdateAutomaticallyHelpText')}
helpTextWarning={updateMechanism.value === 'docker' ? translate('AutomaticUpdatesDisabledDocker', { appName: 'Radarr' }) : undefined}
helpTextWarning={updateMechanism.value === 'docker' ? translate('AutomaticUpdatesDisabledDocker') : undefined}
onChange={onInputChange}
{...updateAutomatically}
/>

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using FluentValidation;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Validation;
@@ -27,7 +28,7 @@ namespace NzbDrone.Core.AutoTagging.Specifications
protected override bool IsSatisfiedByWithoutNegate(Movie movie)
{
return movie.MovieMetadata.Value.Genres.Any(genre => Value.Contains(genre));
return movie?.MovieMetadata?.Value?.Genres.Any(genre => Value.ContainsIgnoreCase(genre)) ?? false;
}
public override NzbDroneValidationResult Validate()

View File

@@ -323,6 +323,20 @@ namespace NzbDrone.Core.Configuration
}
}
public void MigrateConfigFile()
{
if (!File.Exists(_configFile))
{
return;
}
// If SSL is enabled and a cert hash is still in the config file disable SSL
if (EnableSsl && GetValue("SslCertHash", null).IsNotNullOrWhiteSpace())
{
SetValue("EnableSsl", false);
}
}
private void DeleteOldValues()
{
var xDoc = LoadConfigFile();
@@ -394,6 +408,7 @@ namespace NzbDrone.Core.Configuration
public void HandleAsync(ApplicationStartedEvent message)
{
MigrateConfigFile();
EnsureDefaultConfigFile();
DeleteOldValues();
}

View File

@@ -1140,7 +1140,7 @@
"GrabId": "Captura ID",
"OrganizeNothingToRename": "Èxit! La feina està acabada, no hi ha fitxers per canviar el nom.",
"OrganizeLoadError": "S'ha produït un error en carregar les previsualitzacions",
"BlocklistReleaseHelpText": "Impedeix que Lidarr torni a capturar aquesta versió automàticament",
"BlocklistReleaseHelpText": "Impedeix que {appName} torni a capturar aquesta versió automàticament",
"ConnectionLostReconnect": "{appName} intentarà connectar-se automàticament, o podeu fer clic a recarregar.",
"ConnectionLostToBackend": "{appName} ha perdut la connexió amb el backend i s'haurà de tornar a carregar per restaurar la funcionalitat.",
"DelayingDownloadUntil": "S'està retardant la baixada fins a les {0} a les {1}",
@@ -1150,7 +1150,7 @@
"MovieFileDeleted": "Al suprimir fitxer de pel·lícula",
"QueueLoadError": "No s'ha pogut carregar la cua",
"ReleaseProfilesLoadError": "No es poden carregar els perfils de retard",
"ShowUnknownMovieItemsHelpText": "Mostra elements sense pel·lícula a la cua. Això podria incloure pel·lícules eliminades o qualsevol altra cosa de la categoria de Lidarr",
"ShowUnknownMovieItemsHelpText": "Mostra elements sense pel·lícula a la cua. Això podria incloure pel·lícules eliminades o qualsevol altra cosa de la categoria de {appName}",
"TablePageSize": "Mida de la pàgina",
"TablePageSizeHelpText": "Nombre d'elements per mostrar a cada pàgina",
"MovieFileDeletedTooltip": "Al suprimir fitxer de pel·lícula",

View File

@@ -85,6 +85,7 @@
"AuthenticationMethodHelpTextWarning": "Please select a valid authentication method",
"AuthenticationRequired": "Authentication Required",
"AuthenticationRequiredHelpText": "Change which requests authentication is required for. Do not change unless you understand the risks.",
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirm new password",
"AuthenticationRequiredPasswordHelpTextWarning": "Enter a new password",
"AuthenticationRequiredUsernameHelpTextWarning": "Enter a new username",
"AuthenticationRequiredWarning": "To prevent remote access without authentication, {appName} now requires authentication to be enabled. You can optionally disable authentication from local addresses.",
@@ -157,6 +158,8 @@
"ChooseImportMode": "Choose Import Mode",
"CleanLibraryLevel": "Clean Library Level",
"Clear": "Clear",
"ClearBlocklist": "Clear blocklist",
"ClearBlocklistMessageText": "Are you sure you want to clear all items from the blocklist?",
"ClickToChangeLanguage": "Click to change language",
"ClickToChangeMovie": "Click to change movie",
"ClickToChangeQuality": "Click to change quality",
@@ -824,6 +827,7 @@
"ParseModalHelpTextDetails": "{appName} will attempt to parse the title and show you details about it",
"ParseModalUnableToParse": "Unable to parse the provided title, please try again.",
"Password": "Password",
"PasswordConfirmation": "Password Confirmation",
"Path": "Path",
"Paused": "Paused",
"Peers": "Peers",
@@ -959,7 +963,7 @@
"RemotePathMappingCheckRemoteDownloadClient": "Remote download client {downloadClientName} reported files in {path} but this directory does not appear to exist. Likely missing remote path mapping.",
"RemotePathMappingCheckWrongOSPath": "Remote download client {downloadClientName} places downloads in {path} but this is not a valid {osName} path. Review your remote path mappings and download client settings.",
"RemotePathMappings": "Remote Path Mappings",
"RemotePathMappingsInfo": "Remote Path Mappings are very rarely required, if {app} and your download client are on the same system it is better to match your paths. For more information see the [wiki]({wikiLink}).",
"RemotePathMappingsInfo": "Remote Path Mappings are very rarely required, if {appName} and your download client are on the same system it is better to match your paths. For more information see the [wiki]({wikiLink}).",
"Remove": "Remove",
"RemoveCompleted": "Remove Completed",
"RemoveCompletedDownloads": "Remove Completed Downloads",

View File

@@ -1256,13 +1256,13 @@
"EditIndexerImplementation": "Modifier l'indexeur - {implementationName}",
"MovieFileDeleted": "À la suppression d'un fichier vidéo",
"MovieFileDeletedTooltip": "À la suppression d'un fichier vidéo",
"BlocklistReleaseHelpText": "Empêche Lidarr de récupérer automatiquement cette version",
"BlocklistReleaseHelpText": "Empêche {appName} de récupérer automatiquement cette version",
"InteractiveImportLoadError": "Impossible de charger les éléments d'importation manuelle",
"MovieSearchResultsLoadError": "Impossible de charger les résultats de cette recherche de films. Réessayez plus tard",
"QueueLoadError": "Échec du chargement de la file d'attente",
"RemoveSelectedBlocklistMessageText": "Êtes-vous sûr de vouloir supprimer les éléments sélectionnés de la liste de blocage ?",
"RetryingDownloadOn": "Nouvelle tentative de téléchargement le {date} à {time}",
"ShowUnknownMovieItemsHelpText": "Afficher les éléments sans film dans la file d'attente. Cela peut inclure des films supprimés ou tout autre élément de la catégorie de Lidarr",
"ShowUnknownMovieItemsHelpText": "Afficher les éléments sans film dans la file d'attente. Cela peut inclure des films supprimés ou tout autre élément de la catégorie de {appName}",
"TablePageSize": "Taille de la page",
"EditConditionImplementation": "Modifier la condition {implementationName}",
"EditConnectionImplementation": "Ajouter une condition - {implementationName}",
@@ -1285,7 +1285,7 @@
"AutoRedownloadFailed": "Retélécharger les fichiers ayant échoué",
"AutoRedownloadFailedFromInteractiveSearch": "Retélécharger les fichiers ayant échoué depuis la recherche interactive",
"AutoRedownloadFailedFromInteractiveSearchHelpText": "Rechercher et tenter automatiquement de télécharger une version différente lorsque la version ayant échoué a été récupérée à partir de la recherche interactive",
"RemotePathMappingsInfo": "Les mappages de chemins distants sont très rarement requis. Si {app} et votre client de téléchargement sont sur le même système, il est préférable de faire correspondre vos chemins. Pour plus d'informations, consultez le [wiki]({wikiLink}).",
"RemotePathMappingsInfo": "Les mappages de chemins distants sont très rarement requis. Si {appName} et votre client de téléchargement sont sur le même système, il est préférable de faire correspondre vos chemins. Pour plus d'informations, consultez le [wiki]({wikiLink}).",
"SkipRedownload": "Ignorer le nouveau téléchargement",
"Complete": "Complet",
"RemoveCompletedDownloads": "Supprimer les téléchargements terminés",

View File

@@ -228,7 +228,7 @@
"CollectionShowPostersHelpText": "Prikaži Kolekciju postera",
"CollectionsSelectedInterp": "{0} Kolekcija odabrano",
"ColonReplacement": "Zamjena Zareza",
"ColonReplacementFormatHelpText": "izmijeni kako Radar upravlja zamjenama zareza",
"ColonReplacementFormatHelpText": "izmijeni kako {appName} upravlja zamjenama zareza",
"Columns": "Stupci",
"DeleteBackupMessageText": "Jeste li sigurni da želite obrisati oznaku formata {0}?",
"DeleteCustomFormat": "Kloniraj Prilagođeni Format",

View File

@@ -44,7 +44,7 @@
"DownloadPropersAndRepacks": "適切なものと再梱包",
"EditCustomFormat": "カスタムフォーマットの編集",
"EnableAutoHelpText": "有効にすると、映画はこのリストから{appName}に自動的に追加されます",
"EnableAutomaticSearchHelpText": "UIまたはRadarによって自動検索が実行されるときに使用されます",
"EnableAutomaticSearchHelpText": "UIまたは{appName}によって自動検索が実行されるときに使用されます",
"EnableCompletedDownloadHandlingHelpText": "完了したダウンロードをダウンロードクライアントから自動的にインポートします",
"EnableInteractiveSearch": "インタラクティブ検索を有効にする",
"ErrorRestoringBackup": "バックアップの復元中にエラーが発生しました",

View File

@@ -668,7 +668,7 @@
"RemoveFailedDownloadsHelpText": "Remover transferências falhadas do histórico do cliente de transferências",
"RemoveCompletedDownloadsHelpText": "Remover transferências importadas do histórico do cliente de transferências",
"RecycleBinCleanupDaysHelpText": "Defina como 0 para desativar a limpeza automática",
"RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "O Radar suporta condições personalizadas em relação às propriedades das versões abaixo.",
"RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "O {appName} suporta condições personalizadas em relação às propriedades das versões abaixo.",
"RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "O {appName} suporta qualquer lista de filmes em RSS, bem como as demais listadas abaixo.",
"RadarrSupportsAnyDownloadClient": "O {appName} suporta muitos dos clientes de transferências torrent e usenet mais populares.",
"ProxyUsernameHelpText": "Apenas insira o utilizador e a palavra-passe caso seja requerido. Caso contrário, deixe em branco.",

View File

@@ -790,7 +790,7 @@
"ReadTheWikiForMoreInformation": "Leia o Wiki para obter mais informações",
"Ratings": "Classificações",
"RadarrTags": "Tags do {appName}",
"RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "O Radar suporta condições personalizadas em relação às propriedades das versões abaixo.",
"RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "O {appName} suporta condições personalizadas em relação às propriedades das versões abaixo.",
"RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "O {appName} oferece suporte a qualquer lista de filmes em RSS, além da descrita abaixo.",
"RadarrSupportsAnyIndexer": "O {appName} oferece suporte a qualquer indexador que usa o padrão Newznab, além de outros indexadores, listados abaixo.",
"RadarrSupportsAnyDownloadClient": "{appName} suporta muitos clientes populares de download de torrent e usenet.",
@@ -1219,7 +1219,7 @@
"NotificationStatusAllClientHealthCheckMessage": "Todas as notificações estão indisponíveis devido a falhas",
"NotificationStatusSingleClientHealthCheckMessage": "Notificações indisponíveis devido a falhas: {notificationNames}",
"AutomaticUpdatesDisabledDocker": "As atualizações automáticas não têm suporte direto ao usar o mecanismo de atualização do Docker. Você precisará atualizar a imagem do contêiner fora de {appName} ou usar um script",
"RemotePathMappingsInfo": "Raramente são necessários mapeamentos de caminho remoto, se {app} e seu cliente de download estiverem no mesmo sistema, é melhor combinar seus caminhos. Para obter mais informações, consulte o [wiki]({wikiLink}).",
"RemotePathMappingsInfo": "Raramente são necessários mapeamentos de caminho remoto, se {appName} e seu cliente de download estiverem no mesmo sistema, é melhor combinar seus caminhos. Para obter mais informações, consulte o [wiki]({wikiLink}).",
"DisabledForLocalAddresses": "Desabilitado para endereços locais",
"AudioLanguages": "Idiomas do áudio",
"SubtitleLanguages": "Idiomas das Legendas",

View File

@@ -466,7 +466,7 @@
"ProxyType": "Tip proxy",
"QualityProfileInUse": "Nu se poate șterge un profil de calitate atașat unui film",
"QueueIsEmpty": "Coada este goală",
"RadarrCalendarFeed": "Feed Radar Calendar",
"RadarrCalendarFeed": "Feed {appName} Calendar",
"ReadTheWikiForMoreInformation": "Citiți Wiki pentru mai multe informații",
"Reason": "Motiv",
"RegularExpressionsCanBeTested": "Expresiile regulate pot fi testate ",

View File

@@ -154,7 +154,7 @@
"EnableInteractiveSearch": "Включить интерактивный поиск",
"ExcludeTitle": "Исключить {0}? {appName} не будет автоматически добавлять сканируя лист.",
"InCinemasMsg": "Фильмы в кинотеатрах",
"IncludeRecommendationsHelpText": "Включить в отображении найденного фильмы рекомендованные Radar",
"IncludeRecommendationsHelpText": "Включить в отображении найденного фильмы рекомендованные {appName}",
"IndexerPriorityHelpText": "Приоритет индексатора от 1 (самый высокий) до 50 (самый низкий). По умолчанию: 25. Используется при захвате выпусков в качестве средства разрешения конфликтов для равных в остальном выпусков, {appName} по-прежнему будет использовать все включенные индексаторы для синхронизации и поиска RSS",
"IndexerSearchCheckNoAvailableIndexersMessage": "Все индексаторы с возможностью поиска временно выключены из-за ошибок",
"KeyboardShortcuts": "Горячие клавиши",
@@ -1190,7 +1190,7 @@
"NoHistoryBlocklist": "Нет истории блокировок",
"RemoveFailedDownloads": "Удаление неудачных загрузок",
"VideoDynamicRange": "Динамический диапазон видео",
"SkipRedownloadHelpText": "Предотвращает попытку Radar загрузить альтернативную версию для этого элемента",
"SkipRedownloadHelpText": "Предотвращает попытку {appName} загрузить альтернативную версию для этого элемента",
"RemoveCompletedDownloads": "Удалить завершенные загрузки",
"SkipRedownload": "Пропустить повторное скачивание",
"RemoveQueueItemConfirmation": "Вы уверены, что хотите удалить '{sourceTitle}' из очереди?",
@@ -1217,7 +1217,7 @@
"ReleaseHash": "Очистить хэш",
"OnManualInteractionRequiredHelpText": "Требуется ручное взаимодействие",
"ResetQualityDefinitionsMessageText": "Вы уверены, что хотите сбросить определения качества?",
"RemotePathMappingsInfo": "Сопоставление удаленных путей требуется крайне редко, если {app} и клиент загрузки находятся в одной системе, то лучше согласовать пути. Более подробную информацию можно найти в [wiki]({wikiLink}).",
"RemotePathMappingsInfo": "Сопоставление удаленных путей требуется крайне редко, если {appName} и клиент загрузки находятся в одной системе, то лучше согласовать пути. Более подробную информацию можно найти в [wiki]({wikiLink}).",
"UpdateFiltered": "Фильтр обновлений",
"DeleteRemotePathMappingMessageText": "Вы уверены, что хотите удалить это сопоставление удаленного пути?",
"StopSelecting": "Прекратить выбор",

View File

@@ -782,7 +782,7 @@
"ImportRootPath": "{appName}'ı belirli bir filmi değil, tüm filmlerinizi içeren klasöre yöneltin. Örneğin. {1} değil {0}. Ek olarak, her film kök / kitaplık klasöründe kendi klasöründe olmalıdır.",
"InCinemasDate": "Sinemalarda Tarih",
"InCinemasMsg": "Film Sinemalarda",
"IncludeRadarrRecommendations": "Radar Önerilerini Dahil Et",
"IncludeRadarrRecommendations": "{appName} Önerilerini Dahil Et",
"IncludeRecommendationsHelpText": "{appName} tarafından önerilen filmleri keşif görünümüne dahil et",
"IncludeUnmonitored": "İzlenmeyenleri Dahil Et",
"ImportMovies": "Filmleri İçe Aktar",

View File

@@ -564,7 +564,7 @@
"QuickImport": "Рухатися автоматично",
"RadarrCalendarFeed": "Стрічка календаря {appName}",
"RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "{appName} підтримує спеціальні умови щодо наведених нижче властивостей випуску.",
"RadarrTags": "Теги Radar",
"RadarrTags": "Теги {appName}",
"Rating": "Рейтинг",
"Ratings": "Рейтинги",
"Real": "Справжня",

View File

@@ -1303,7 +1303,7 @@
"OverrideGrabNoLanguage": "请选择至少一种语言",
"PendingDownloadClientUnavailable": "挂起 - 下载客户端不可用",
"QueueLoadError": "加载队列失败",
"RemotePathMappingsInfo": "很少需要远程路径映射,如果{app}和你的下载客户端在同一个系统上,最好匹配你的路径。有关更多信息,请参阅[wiki]({wikiink})。",
"RemotePathMappingsInfo": "很少需要远程路径映射,如果{appName}和你的下载客户端在同一个系统上,最好匹配你的路径。有关更多信息,请参阅[wiki]({wikiink})。",
"RemoveFromDownloadClientHelpTextWarning": "删除将从下载客户端删除下载和文件。",
"ShowTmdbRatingHelpText": "在海报下显示TMDb评分",
"ShowUnknownMovieItemsHelpText": "显示队列中没有电影的项目。这可能包括被删除的电影或任何其他在{appName}的类别",

View File

@@ -1,4 +1,4 @@
using FluentValidation.Validators;
using FluentValidation.Validators;
using NzbDrone.Common.Disk;
namespace NzbDrone.Core.Validation.Paths

View File

@@ -47,6 +47,9 @@ namespace Radarr.Api.V3.Config
SharedValidator.RuleFor(c => c.Password).NotEmpty().When(c => c.AuthenticationMethod == AuthenticationType.Basic ||
c.AuthenticationMethod == AuthenticationType.Forms);
SharedValidator.RuleFor(c => c.PasswordConfirmation)
.Must((resource, p) => IsMatchingPassword(resource)).WithMessage("Must match Password");
SharedValidator.RuleFor(c => c.SslPort).ValidPort().When(c => c.EnableSsl);
SharedValidator.RuleFor(c => c.SslPort).NotEqual(c => c.Port).When(c => c.EnableSsl);
@@ -81,6 +84,23 @@ namespace Radarr.Api.V3.Config
return cert != null;
}
private bool IsMatchingPassword(HostConfigResource resource)
{
var user = _userService.FindUser();
if (user != null && user.Password == resource.Password)
{
return true;
}
if (resource.Password == resource.PasswordConfirmation)
{
return true;
}
return false;
}
protected override HostConfigResource GetResourceById(int id)
{
return GetHostConfig();
@@ -93,11 +113,10 @@ namespace Radarr.Api.V3.Config
resource.Id = 1;
var user = _userService.FindUser();
if (user != null)
{
resource.Username = user.Username;
resource.Password = user.Password;
}
resource.Username = user?.Username ?? string.Empty;
resource.Password = user?.Password ?? string.Empty;
resource.PasswordConfirmation = string.Empty;
return resource;
}

View File

@@ -19,6 +19,7 @@ namespace Radarr.Api.V3.Config
public bool AnalyticsEnabled { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string PasswordConfirmation { get; set; }
public string LogLevel { get; set; }
public string ConsoleLogLevel { get; set; }
public string Branch { get; set; }

View File

@@ -90,7 +90,9 @@ namespace Radarr.Api.V3
var providerDefinition = GetDefinition(providerResource, existingDefinition, true, !forceSave, false);
// Comparing via JSON string to eliminate the need for every provider implementation to implement equality checks.
var hasDefinitionChanged = STJson.ToJson(existingDefinition) != STJson.ToJson(providerDefinition);
// Compare settings separately because they are not serialized with the definition.
var hasDefinitionChanged = STJson.ToJson(existingDefinition) != STJson.ToJson(providerDefinition) ||
STJson.ToJson(existingDefinition.Settings) != STJson.ToJson(providerDefinition.Settings);
// Only test existing definitions if it is enabled and forceSave isn't set or the definition has changed.
if (providerDefinition.Enable && (!forceSave || hasDefinitionChanged))

View File

@@ -9849,6 +9849,10 @@
"type": "string",
"nullable": true
},
"passwordConfirmation": {
"type": "string",
"nullable": true
},
"logLevel": {
"type": "string",
"nullable": true