mirror of
https://github.com/Readarr/Readarr.git
synced 2026-03-11 15:20:03 -04:00
Compare commits
9 Commits
sonarr-pul
...
sonarr-pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03ed01e7d8 | ||
|
|
ce820f6f73 | ||
|
|
53e6cb24b7 | ||
|
|
7c1ca8acc1 | ||
|
|
5e9e578101 | ||
|
|
156407c541 | ||
|
|
1ef6c60318 | ||
|
|
73b3b1848b | ||
|
|
33fbd95707 |
@@ -9,7 +9,7 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '0.3.1'
|
||||
majorVersion: '0.3.2'
|
||||
minorVersion: $[counter('minorVersion', 1)]
|
||||
readarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
|
||||
.statusIcon {
|
||||
width: 20px !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { tooltipPositions } from 'Helpers/Props';
|
||||
import Tooltip from './Tooltip';
|
||||
import styles from './Popover.css';
|
||||
|
||||
@@ -30,8 +31,13 @@ function Popover(props) {
|
||||
}
|
||||
|
||||
Popover.propTypes = {
|
||||
className: PropTypes.string,
|
||||
bodyClassName: PropTypes.string,
|
||||
anchor: PropTypes.node.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
body: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired
|
||||
body: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
|
||||
position: PropTypes.oneOf(tooltipPositions.all),
|
||||
canFlip: PropTypes.bool
|
||||
};
|
||||
|
||||
export default Popover;
|
||||
|
||||
8
frontend/src/Helpers/Props/TooltipPosition.ts
Normal file
8
frontend/src/Helpers/Props/TooltipPosition.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
enum TooltipPosition {
|
||||
Top = 'top',
|
||||
Right = 'right',
|
||||
Bottom = 'bottom',
|
||||
Left = 'left',
|
||||
}
|
||||
|
||||
export default TooltipPosition;
|
||||
@@ -17,6 +17,11 @@ const authenticationMethodOptions = [
|
||||
{ key: 'forms', value: 'Forms (Login Page)' }
|
||||
];
|
||||
|
||||
const authenticationRequiredOptions = [
|
||||
{ key: 'enabled', value: 'Enabled' },
|
||||
{ key: 'disabledForLocalAddresses', value: 'Disabled for Local Addresses' }
|
||||
];
|
||||
|
||||
const certificateValidationOptions = [
|
||||
{ key: 'enabled', value: 'Enabled' },
|
||||
{ key: 'disabledForLocalAddresses', value: 'Disabled for Local Addresses' },
|
||||
@@ -68,6 +73,7 @@ class SecuritySettings extends Component {
|
||||
|
||||
const {
|
||||
authenticationMethod,
|
||||
authenticationRequired,
|
||||
username,
|
||||
password,
|
||||
apiKey,
|
||||
@@ -94,7 +100,24 @@ class SecuritySettings extends Component {
|
||||
</FormGroup>
|
||||
|
||||
{
|
||||
authenticationEnabled &&
|
||||
authenticationEnabled ?
|
||||
<FormGroup>
|
||||
<FormLabel>Authentication Required</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
name="authenticationRequired"
|
||||
values={authenticationRequiredOptions}
|
||||
helpText="Change which requests authentication is required for. Do not change unless you understand the risks."
|
||||
onChange={onInputChange}
|
||||
{...authenticationRequired}
|
||||
/>
|
||||
</FormGroup> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
authenticationEnabled ?
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
{translate('Username')}
|
||||
@@ -106,11 +129,12 @@ class SecuritySettings extends Component {
|
||||
onChange={onInputChange}
|
||||
{...username}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormGroup> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
authenticationEnabled &&
|
||||
authenticationEnabled ?
|
||||
<FormGroup>
|
||||
<FormLabel>
|
||||
{translate('Password')}
|
||||
@@ -122,7 +146,8 @@ class SecuritySettings extends Component {
|
||||
onChange={onInputChange}
|
||||
{...password}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormGroup> :
|
||||
null
|
||||
}
|
||||
|
||||
<FormGroup>
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
"@babel/preset-env": "7.22.9",
|
||||
"@babel/preset-react": "7.22.5",
|
||||
"@babel/preset-typescript": "7.22.5",
|
||||
"@types/redux-actions": "2.6.2",
|
||||
"@typescript-eslint/eslint-plugin": "6.0.0",
|
||||
"@typescript-eslint/parser": "6.0.0",
|
||||
"autoprefixer": "10.4.14",
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace NzbDrone.Automation.Test
|
||||
|
||||
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
|
||||
_runner.KillAll();
|
||||
_runner.Start();
|
||||
_runner.Start(true);
|
||||
|
||||
driver.Url = "http://localhost:8787";
|
||||
|
||||
|
||||
@@ -77,7 +77,9 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||
FullName = Name;
|
||||
}
|
||||
|
||||
if (IsLinux && File.Exists("/proc/1/cgroup") && File.ReadAllText("/proc/1/cgroup").Contains("/docker/"))
|
||||
if (IsLinux &&
|
||||
((File.Exists("/proc/1/cgroup") && File.ReadAllText("/proc/1/cgroup").Contains("/docker/")) ||
|
||||
(File.Exists("/proc/1/mountinfo") && File.ReadAllText("/proc/1/mountinfo").Contains("/docker/"))))
|
||||
{
|
||||
IsDocker = true;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,13 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
||||
"OutOfMemoryException",
|
||||
|
||||
// Filter out people stuck in boot loops
|
||||
"CorruptDatabaseException"
|
||||
"CorruptDatabaseException",
|
||||
|
||||
// Filter SingleInstance Termination Exceptions
|
||||
"TerminateApplicationException",
|
||||
|
||||
// User config issue, root folder missing, etc.
|
||||
"DirectoryNotFoundException"
|
||||
};
|
||||
|
||||
public static readonly List<string> FilteredExceptionMessages = new List<string>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace NzbDrone.Core.Authentication
|
||||
{
|
||||
public enum AuthenticationRequiredType
|
||||
{
|
||||
Enabled = 0,
|
||||
DisabledForLocalAddresses = 1
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
namespace NzbDrone.Core.Authentication
|
||||
namespace NzbDrone.Core.Authentication
|
||||
{
|
||||
public enum AuthenticationType
|
||||
{
|
||||
None = 0,
|
||||
Basic = 1,
|
||||
Forms = 2
|
||||
Forms = 2,
|
||||
External = 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace NzbDrone.Core.Configuration
|
||||
bool EnableSsl { get; }
|
||||
bool LaunchBrowser { get; }
|
||||
AuthenticationType AuthenticationMethod { get; }
|
||||
AuthenticationRequiredType AuthenticationRequired { get; }
|
||||
bool AnalyticsEnabled { get; }
|
||||
string LogLevel { get; }
|
||||
string ConsoleLogLevel { get; }
|
||||
@@ -190,6 +191,8 @@ namespace NzbDrone.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
public AuthenticationRequiredType AuthenticationRequired => GetValueEnum("AuthenticationRequired", AuthenticationRequiredType.Enabled);
|
||||
|
||||
public bool AnalyticsEnabled => GetValueBoolean("AnalyticsEnabled", true, persist: false);
|
||||
|
||||
// TODO: Change back to "master" for the first stable release
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Localization;
|
||||
using NzbDrone.Core.ThingiProvider.Events;
|
||||
|
||||
namespace NzbDrone.Core.HealthCheck.Checks
|
||||
{
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IIndexer>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<IIndexer>))]
|
||||
[CheckOn(typeof(ProviderUpdatedEvent<IDownloadClient>))]
|
||||
[CheckOn(typeof(ProviderDeletedEvent<IDownloadClient>))]
|
||||
public class IndexerDownloadClientCheck : HealthCheckBase
|
||||
{
|
||||
private readonly IIndexerFactory _indexerFactory;
|
||||
private readonly IDownloadClientFactory _downloadClientFactory;
|
||||
|
||||
public IndexerDownloadClientCheck(IIndexerFactory indexerFactory,
|
||||
IDownloadClientFactory downloadClientFactory,
|
||||
ILocalizationService localizationService)
|
||||
: base(localizationService)
|
||||
{
|
||||
_indexerFactory = indexerFactory;
|
||||
_downloadClientFactory = downloadClientFactory;
|
||||
}
|
||||
|
||||
public override HealthCheck Check()
|
||||
{
|
||||
var downloadClientsIds = _downloadClientFactory.All().Where(v => v.Enable).Select(v => v.Id).ToList();
|
||||
var invalidIndexers = _indexerFactory.All()
|
||||
.Where(v => v.Enable && v.DownloadClientId > 0 && !downloadClientsIds.Contains(v.DownloadClientId))
|
||||
.ToList();
|
||||
|
||||
if (invalidIndexers.Any())
|
||||
{
|
||||
return new HealthCheck(GetType(),
|
||||
HealthCheckResult.Warning,
|
||||
string.Format(_localizationService.GetLocalizedString("IndexerDownloadClientHealthCheckMessage"), string.Join(", ", invalidIndexers.Select(v => v.Name).ToArray())),
|
||||
"#invalid-indexer-download-client-setting");
|
||||
}
|
||||
|
||||
return new HealthCheck(GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -392,6 +392,7 @@
|
||||
"IncludeUnknownAuthorItemsHelpText": "Show items without a author in the queue, this could include removed authors, books or anything else in Readarr's category",
|
||||
"IncludeUnmonitored": "Include Unmonitored",
|
||||
"Indexer": "Indexer",
|
||||
"IndexerDownloadClientHealthCheckMessage": "Indexers with invalid download clients: {0}.",
|
||||
"IndexerDownloadClientHelpText": "Specify which download client is used for grabs from this indexer",
|
||||
"IndexerIdHelpText": "Specify what indexer the profile applies to",
|
||||
"IndexerIdHelpTextWarning": "Using a specific indexer with preferred words can lead to duplicate releases being grabbed",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"SslPortHelpTextWarning": "Nécessite un redémarrage pour prendre effet",
|
||||
"SslCertPathHelpTextWarning": "Nécessite un redémarrage pour prendre effet",
|
||||
"UnableToLoadMetadataProfiles": "Impossible de charger les profils de délai",
|
||||
"AddingTag": "Ajout d'un tag",
|
||||
"AddingTag": "Ajouter un tag",
|
||||
"AgeWhenGrabbed": "Age (au moment du téléchargement)",
|
||||
"AlreadyInYourLibrary": "Déjà présent dans votre collection",
|
||||
"AlternateTitles": "Titre alternatif",
|
||||
@@ -761,5 +761,8 @@
|
||||
"ExistingTag": "Tag existant",
|
||||
"No": "Non",
|
||||
"RemovingTag": "Suppression du tag",
|
||||
"SetTags": "Définir Tags"
|
||||
"SetTags": "Définir Tags",
|
||||
"CountDownloadClientsSelected": "{0} client(s) de téléchargement sélectionné(s)",
|
||||
"EditSelectedDownloadClients": "Modifier les clients de téléchargement sélectionnés",
|
||||
"EditSelectedIndexers": "Modifier les indexeurs sélectionnés"
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
"Theme": "Tema",
|
||||
"Title": "Naslov",
|
||||
"Torrents": "Torrenti",
|
||||
"UI": "Korisničko Sučelje",
|
||||
"UI": "Korisničko sučelje",
|
||||
"URLBase": "URL Base",
|
||||
"Usenet": "Usenet",
|
||||
"Analytics": "Analitika",
|
||||
@@ -155,5 +155,29 @@
|
||||
"DeleteSelectedIndexersMessageText": "Jeste li sigurni da želite obrisati oznaku formata {0}?",
|
||||
"RemoveSelectedItemQueueMessageText": "Jeste li sigurni da želite izbrisati stavku {0} iz reda?",
|
||||
"RemoveSelectedItemsQueueMessageText": "Jeste li sigurni da želite izbrisati stavku {0} iz reda?",
|
||||
"Required": "Zahtjevaj"
|
||||
"Required": "Zahtjevaj",
|
||||
"Options": "Opcije",
|
||||
"Style": "Stil",
|
||||
"Today": "Danas",
|
||||
"UnselectAll": "Odznači sve",
|
||||
"No": "Ne",
|
||||
"Restart": "Resetiraj",
|
||||
"RestartNow": "Resetiraj sad",
|
||||
"Tomorrow": "Sutra",
|
||||
"Yes": "Da",
|
||||
"History": "Povijest",
|
||||
"Save": "Spremi",
|
||||
"Security": "Sigurnost",
|
||||
"SelectAll": "Odaberi sve",
|
||||
"Source": "Izvor",
|
||||
"Status": "Status",
|
||||
"Time": "Vrijeme",
|
||||
"YesCancel": "Da, otkaži",
|
||||
"Yesterday": "Jučer",
|
||||
"Year": "Godina",
|
||||
"Result": "Rezultat",
|
||||
"UseProxy": "Koristi proxy",
|
||||
"RemoveFilter": "Ukloni filter",
|
||||
"Name": "Ime",
|
||||
"Version": "Verzija"
|
||||
}
|
||||
|
||||
@@ -147,5 +147,7 @@
|
||||
"AddMissing": "Legg til manglende",
|
||||
"AddNewItem": "Legg til nytt item",
|
||||
"45MinutesFourtyFive": "45 Minutter: {0}",
|
||||
"60MinutesSixty": "60 Minutter: {0}"
|
||||
"60MinutesSixty": "60 Minutter: {0}",
|
||||
"ApplyChanges": "Bekreft endringer",
|
||||
"ApiKeyValidationHealthCheckMessage": "Vennligst oppdater din API-nøkkel til å være minst {0} tegn lang. Du kan gjøre dette via innstillinger eller konfigurasjonsfilen"
|
||||
}
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
"APIKey": "API-sleutel",
|
||||
"About": "Over",
|
||||
"AddListExclusion": "Toevoegen aan Uitzonderingenlijst",
|
||||
"AddingTag": "Tag toevoegen",
|
||||
"AddingTag": "Tag wordt toegevoegd",
|
||||
"AgeWhenGrabbed": "Leeftijd (op moment van ophalen)",
|
||||
"AlreadyInYourLibrary": "Reeds in uw bibliotheek",
|
||||
"AlternateTitles": "Alternatieve Titel",
|
||||
"Analytics": "Statistieken",
|
||||
"AnalyticsEnabledHelpText": "Stuur anonieme gebruiks- en foutinformatie naar de servers van Radarr. Dit omvat informatie over uw browser, welke Radarr WebUI pagina's u gebruikt, foutrapportage en OS en runtime versie. We zullen deze informatie gebruiken om prioriteiten te stellen voor functies en het verhelpen van fouten.",
|
||||
"AppDataDirectory": "AppData map",
|
||||
"ApplyTags": "Tags Toepassen",
|
||||
"AppDataDirectory": "AppData folder",
|
||||
"ApplyTags": "Pas Tags Toe",
|
||||
"Authentication": "Authenticatie",
|
||||
"AuthenticationMethodHelpText": "Gebruikersnaam en wachtwoord nodig voor toegang tot Radarr",
|
||||
"AuthorClickToChangeBook": "Klik om film te wijzigen",
|
||||
@@ -32,7 +32,7 @@
|
||||
"AutoUnmonitorPreviouslyDownloadedBooksHelpText": "Verwijderde films zullen automatisch als onbewaakt worden gemarkeerd in Radarr",
|
||||
"Automatic": "Automatisch",
|
||||
"BackupFolderHelpText": "Relatieve paden zullen t.o.v. de Radarr AppData map bekeken worden",
|
||||
"BackupNow": "Veiligheidskopie Maken",
|
||||
"BackupNow": "Nu backup nemen",
|
||||
"BackupRetentionHelpText": "Automatische veiligheidskopieën ouder dan de retentie periode zullen worden opgeruimd",
|
||||
"Backups": "Veiligheidskopieën",
|
||||
"BindAddress": "Gebonden Adres",
|
||||
@@ -55,7 +55,7 @@
|
||||
"ChmodFolderHelpTextWarning": "Dit werkt alleen als de gebruiker die Radarr draait de eigenaar is van het bestand. Het is beter om zeker te zijn dat de downloader de juiste rechten zet.",
|
||||
"ChownGroupHelpText": "Groep naam of gid. Gebruik gid voor externe bestandssystemen.",
|
||||
"ChownGroupHelpTextWarning": "Dit werkt alleen als de gebruiker die Radarr draait de eigenaar is van het bestand. Het is beter om zeker te zijn dat de downloader dezelfde groep gebruikt als Radarr.",
|
||||
"Clear": "Wissen",
|
||||
"Clear": "Wis",
|
||||
"ClickToChangeQuality": "Klik om kwaliteit te wijzigen",
|
||||
"ClientPriority": "Client Prioriteit",
|
||||
"CloneIndexer": "Dupliceer Indexeerder",
|
||||
@@ -76,8 +76,8 @@
|
||||
"DelayProfile": "Vertragingsprofiel",
|
||||
"DelayProfiles": "Vertragingsprofielen",
|
||||
"DelayingDownloadUntilInterp": "Vertraag download tot {0} op {1}",
|
||||
"Delete": "Verwijderen",
|
||||
"DeleteBackup": "Verwijder Veiligheidskopie",
|
||||
"Delete": "Verwijder",
|
||||
"DeleteBackup": "Verwijder Backup",
|
||||
"DeleteBackupMessageText": "Bent u zeker dat u de veiligheidskopie '{0}' wilt verwijderen?",
|
||||
"DeleteDelayProfile": "Verwijder Vertragingsprofiel",
|
||||
"DeleteDelayProfileMessageText": "Weet u zeker dat u dit vertragingsprofiel wilt verwijderen?",
|
||||
@@ -458,8 +458,8 @@
|
||||
"ShowBookTitleHelpText": "Toon filmtitel onder poster",
|
||||
"Blocklist": "Blokkeerlijst",
|
||||
"BlocklistRelease": "Uitgave op blokkeerlijst zetten",
|
||||
"All": "Alles",
|
||||
"Component": "Onderdeel",
|
||||
"All": "Alle",
|
||||
"Component": "Component",
|
||||
"ConsoleLogLevel": "Console-logboekniveau",
|
||||
"DeleteBookFileMessageText": "Weet u zeker dat u {0} wilt verwijderen?",
|
||||
"FilterAnalyticsEvents": "Analytics-gebeurtenissen filteren",
|
||||
@@ -637,5 +637,15 @@
|
||||
"ThereWasAnErrorLoadingThisPage": "Er ging iets fout bij het laden van deze pagina",
|
||||
"ApiKeyValidationHealthCheckMessage": "Maak je API sleutel alsjeblieft minimaal {0} karakters lang. Dit kan gedaan worden via de instellingen of het configuratiebestand",
|
||||
"ResetDefinitions": "Reset definities",
|
||||
"ResetTitles": "Reset titels"
|
||||
"ResetTitles": "Reset titels",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Hoe tags toepassen op de geselecteerde indexeerders",
|
||||
"AutomaticAdd": "Automatisch Toevoegen",
|
||||
"CloneCondition": "Kloon Conditie",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Hoe tags toepassen op de geselecteerde import lijsten",
|
||||
"ApplyChanges": "Pas Wijzigingen Toe",
|
||||
"ApplyTagsHelpTextAdd": "Toevoegen: Voeg de tags toe aan de bestaande tag lijst",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Hoe tags toepassen op de geselecteerde download clients",
|
||||
"ApplyTagsHelpTextRemove": "Verwijderen: Verwijder de ingevoerde tags",
|
||||
"ApplyTagsHelpTextReplace": "Vervangen: Vervang de tags met de ingevoerde tags (vul geen tags in om alle tags te wissen)",
|
||||
"AutoAdd": "Automatisch Toevoegen"
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
"BookIsDownloading": "O livro está baixando",
|
||||
"DiskSpace": "Espaço em Disco",
|
||||
"Docker": "Docker",
|
||||
"DownloadClient": "Cliente de download",
|
||||
"DownloadClient": "Cliente de Download",
|
||||
"DownloadClientSettings": "Configurações do cliente de download",
|
||||
"DownloadClients": "Clientes de download",
|
||||
"DownloadFailedCheckDownloadClientForMoreDetails": "Falha no download: verifique o cliente de download para saber mais",
|
||||
@@ -127,7 +127,7 @@
|
||||
"DeleteQualityProfileMessageText": "Tem certeza que deseja excluir o perfil de qualidade \"{0}\"?",
|
||||
"DeleteReleaseProfile": "Excluir Perfil de Lançamento",
|
||||
"DeleteReleaseProfileMessageText": "Tem certeza de que deseja excluir este Perfil de Lançamento?",
|
||||
"DeleteRootFolderMessageText": "Tem certeza de que deseja excluir a pasta raiz \"{0}\"?",
|
||||
"DeleteRootFolderMessageText": "Tem certeza de que deseja excluir a pasta raiz '{0}'?",
|
||||
"DeleteSelectedBookFiles": "Excluir arquivos do livro selecionado",
|
||||
"DeleteSelectedBookFilesMessageText": "Tem certeza de que deseja excluir os arquivos do livro selecionado?",
|
||||
"DeleteTag": "Excluir tag",
|
||||
@@ -183,7 +183,7 @@
|
||||
"Importing": "Importando",
|
||||
"IncludeHealthWarningsHelpText": "Incluir avisos de integridade",
|
||||
"IncludeUnknownAuthorItemsHelpText": "Mostrar itens sem autor na fila, isso pode incluir autores removidos, livros ou qualquer outra coisa na categoria de Readarr",
|
||||
"IncludeUnmonitored": "Incluir não monitorados",
|
||||
"IncludeUnmonitored": "Incluir não monitorado",
|
||||
"Indexer": "Indexador",
|
||||
"IndexerPriority": "Prioridade do indexador",
|
||||
"IndexerSettings": "Configurações do indexador",
|
||||
@@ -319,7 +319,7 @@
|
||||
"RetentionHelpText": "Apenas Usenet: use 0 para definir para retenção ilimitada",
|
||||
"RetryingDownloadInterp": "Tentando novamente o download {0} em {1}",
|
||||
"RootFolder": "Pasta Raiz",
|
||||
"RootFolders": "Pastas raiz",
|
||||
"RootFolders": "Pastas Raiz",
|
||||
"RssSyncIntervalHelpText": "Intervalo em minutos. Defina como zero para desabilitar (isso interromperá todos os downloads automáticos de lançamentos)",
|
||||
"SSLCertPassword": "Senha do certificado SSL",
|
||||
"SSLCertPath": "Caminho do certificado SSL",
|
||||
@@ -588,7 +588,7 @@
|
||||
"DiscNumber": "Número do disco",
|
||||
"DiscCount": "Contagem de disco",
|
||||
"Development": "Desenvolvimento",
|
||||
"DeleteRootFolder": "Excluir pasta raiz",
|
||||
"DeleteRootFolder": "Excluir Pasta Raiz",
|
||||
"DeleteMetadataProfile": "Excluir perfil de metadados",
|
||||
"DeleteImportList": "Excluir lista de importação",
|
||||
"DeleteFilesHelpText": "Excluir arquivos do livro e pasta do autor",
|
||||
@@ -826,7 +826,7 @@
|
||||
"SettingsRemotePathMappingRemotePathHelpText": "Caminho raiz para o diretório que o Cliente de Download acessa",
|
||||
"SizeLimit": "Tamanho limite",
|
||||
"SystemTimeCheckMessage": "A hora do sistema está desligada por mais de 1 dia. Tarefas agendadas podem não ser executadas corretamente até que o horário seja corrigido",
|
||||
"TimeLeft": "Tempo restante",
|
||||
"TimeLeft": "Tempo Restante",
|
||||
"UISettingsSummary": "Opções de calendário, data e cores prejudicadas",
|
||||
"UpdateCheckStartupNotWritableMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' não pode ser gravada pelo usuário '{1}'.",
|
||||
"UpdateCheckStartupTranslocationMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' está em uma pasta de translocação de aplicativo.",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"DiskSpace": "Spațiul pe disc",
|
||||
"EnableRSS": "Activați RSS",
|
||||
"EnableSslHelpText": " Necesită repornirea în funcție de administrator pentru a intra în vigoare",
|
||||
"Ended": "Finalizat",
|
||||
"Ended": "Încheiat",
|
||||
"Grab": "Apuca",
|
||||
"LoadingBookFilesFailed": "Încărcarea fișierelor film a eșuat",
|
||||
"LoadingBooksFailed": "Încărcarea fișierelor film a eșuat",
|
||||
@@ -138,7 +138,7 @@
|
||||
"DelayProfiles": "Profile de întârziere",
|
||||
"DelayingDownloadUntilInterp": "Întârzierea descărcării până la {0} la {1}",
|
||||
"Delete": "Șterge",
|
||||
"DeleteBackup": "Ștergeți copie de siguranță",
|
||||
"DeleteBackup": "Ștergeți copia de rezervă",
|
||||
"DeleteBackupMessageText": "Sigur doriți să ștergeți copia de siguranță „{0}”?",
|
||||
"DeleteDelayProfile": "Ștergeți profilul de întârziere",
|
||||
"DeleteDelayProfileMessageText": "Sigur doriți să ștergeți acest profil de întârziere?",
|
||||
@@ -192,7 +192,7 @@
|
||||
"FileDateHelpText": "Schimbați data fișierului la import / rescanare",
|
||||
"FileManagement": "Administrarea de fișiere",
|
||||
"FileNames": "Numele fișierelor",
|
||||
"Filename": "Numele fișierului",
|
||||
"Filename": "Nume fișier",
|
||||
"Files": "Fișiere",
|
||||
"FirstDayOfWeek": "Prima zi a săptămânii",
|
||||
"Fixed": "Fix",
|
||||
@@ -546,7 +546,7 @@
|
||||
"RestartRequiredHelpTextWarning": "Necesită repornire pentru a intra în vigoare",
|
||||
"Test": "Testează",
|
||||
"AddList": "Adaugă listă",
|
||||
"RenameFiles": "Redenumește Fișiere",
|
||||
"RenameFiles": "Redenumește Fișierele",
|
||||
"Label": "Etichetă",
|
||||
"ImportListExclusions": "Ștergeți excluderea listei de import",
|
||||
"ManualImportSelectEdition": "Import manual - Selectați film",
|
||||
@@ -571,7 +571,7 @@
|
||||
"CutoffFormatScoreHelpText": "Odată ce acest scor personalizat este atins, Radarr nu va mai descărca filme",
|
||||
"DeleteFormatMessageText": "Sigur doriți să ștergeți eticheta format {0}?",
|
||||
"IncludeCustomFormatWhenRenamingHelpText": "Includeți în formatul de redenumire {Formate personalizate}",
|
||||
"HiddenClickToShow": "Ascuns, faceți clic pentru a afișa",
|
||||
"HiddenClickToShow": "Ascuns, faceți clic pentru afișare",
|
||||
"HideAdvanced": "Ascunde Avansat",
|
||||
"ShowAdvanced": "Arată setări avansate",
|
||||
"ShownClickToHide": "Afișat, faceți clic pentru a ascunde",
|
||||
@@ -601,7 +601,7 @@
|
||||
"RedownloadFailed": "Descarcare esuata",
|
||||
"ApplyTagsHelpTextAdd": "Adăugare: adăugați etichetele la lista de etichete existentă",
|
||||
"ApplyTagsHelpTextHowToApplyImportLists": "Cum se aplică etichete listelor de import selectate",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Cum se aplică etichete filmelor selectate",
|
||||
"ApplyTagsHelpTextHowToApplyDownloadClients": "Cum se aplică etichete clienților de descărcare selectați",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Cum se aplică etichete indexatoarelor selectate",
|
||||
"ApplyTagsHelpTextRemove": "Eliminați: eliminați etichetele introduse",
|
||||
"ApplyTagsHelpTextReplace": "Înlocuire: înlocuiți etichetele cu etichetele introduse (nu introduceți etichete pentru a șterge toate etichetele)",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"BackupFolderHelpText": "相对路径将在Radarr的AppData目录下",
|
||||
"BackupNow": "马上备份",
|
||||
"BackupRetentionHelpText": "早于保留周期的自动备份将被自动清除",
|
||||
"Backups": "备份",
|
||||
"Backups": "历史备份",
|
||||
"BindAddress": "绑定地址",
|
||||
"BindAddressHelpTextWarning": "需重启以生效",
|
||||
"BookIsDownloading": "影片正在下载中",
|
||||
@@ -422,7 +422,7 @@
|
||||
"Version": "版本",
|
||||
"WeekColumnHeader": "日期格式",
|
||||
"Year": "年",
|
||||
"YesCancel": "是,取消",
|
||||
"YesCancel": "确定,取消",
|
||||
"20MinutesTwenty": "20 分钟:{0}",
|
||||
"45MinutesFourtyFive": "45分钟: {0}",
|
||||
"60MinutesSixty": "60分钟: {0}",
|
||||
@@ -438,13 +438,13 @@
|
||||
"MaintenanceRelease": "维护版本:修复错误及其他改进,参见Github提交 查看更多详情",
|
||||
"DeleteBookFileMessageText": "您确认您想删除吗?",
|
||||
"ApiKeyHelpTextWarning": "需重启以生效",
|
||||
"Actions": "操作",
|
||||
"Actions": "动作",
|
||||
"AddMissing": "添加丢失项",
|
||||
"AddNewItem": "添加新项目",
|
||||
"DeleteRootFolderMessageText": "您确定要删除索引 '{0}'吗?",
|
||||
"Progress": "进度",
|
||||
"Publisher": "发布者",
|
||||
"Series": "集",
|
||||
"Series": "节目",
|
||||
"ShowBookTitleHelpText": "在海报下显示电影标题",
|
||||
"BookAvailableButMissing": "影片可下载,但没有下载",
|
||||
"ShowReleaseDate": "显示发布日期",
|
||||
@@ -454,7 +454,7 @@
|
||||
"NotAvailable": "不可用",
|
||||
"NotMonitored": "未监控的",
|
||||
"OutputPath": "输出路径",
|
||||
"ReleaseTitle": "歌曲发布标题",
|
||||
"ReleaseTitle": "发布标题",
|
||||
"TheAuthorFolderAndAllOfItsContentWillBeDeleted": "电影目录 '{0}' 及所有内容都会被删除。",
|
||||
"Today": "今天",
|
||||
"Tomorrow": "明天",
|
||||
@@ -480,7 +480,7 @@
|
||||
"All": "全部",
|
||||
"Level": "等级",
|
||||
"RemoveFromBlocklist": "从黑名单中移除",
|
||||
"Blocklist": "阻止列表",
|
||||
"Blocklist": "黑名单",
|
||||
"BlocklistRelease": "黑名单版本",
|
||||
"AllowFingerprinting": "允许指纹识别",
|
||||
"AllExpandedCollapseAll": "收缩所有",
|
||||
@@ -921,5 +921,27 @@
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "如何将标签应用到已选择的索引器",
|
||||
"ApplyTagsHelpTextRemove": "移除: 移除已输入的标签",
|
||||
"ApplyTagsHelpTextReplace": "替换: 用输入的标签替换当前标签 (不输入将会清除所有标签)",
|
||||
"ApplyTagsHelpTextAdd": "添加: 添加标签至已有的标签列表中"
|
||||
"ApplyTagsHelpTextAdd": "添加: 添加标签至已有的标签列表中",
|
||||
"AutoAdd": "自动添加",
|
||||
"DeleteSelectedIndexers": "删除索引器",
|
||||
"EditSelectedDownloadClients": "编辑选定的下载客户端",
|
||||
"EditSelectedImportLists": "编辑选定的导入列表",
|
||||
"EditSelectedIndexers": "编辑选定的索引器",
|
||||
"ExistingTag": "已有标签",
|
||||
"NoEventsFound": "无事件",
|
||||
"RemoveCompleted": "移除已完成",
|
||||
"RemoveSelectedItems": "删除所选项目",
|
||||
"RemovingTag": "移除标签",
|
||||
"SetTags": "设置标签",
|
||||
"Yes": "确定",
|
||||
"BlocklistReleases": "黑名单版本",
|
||||
"Required": "必须的",
|
||||
"RemoveFailed": "删除失败",
|
||||
"RemoveSelectedItem": "删除所选项目",
|
||||
"DeleteSelectedDownloadClients": "删除下载客户端",
|
||||
"DeleteSelectedImportLists": "删除导入列表",
|
||||
"NoChange": "无修改",
|
||||
"Negated": "无效的",
|
||||
"No": "否",
|
||||
"ResetQualityDefinitions": "重置质量定义"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.TPL;
|
||||
using NzbDrone.Core.Configuration;
|
||||
@@ -116,6 +117,9 @@ namespace NzbDrone.Core.MediaFiles
|
||||
|
||||
private void StartWatchingPath(string path)
|
||||
{
|
||||
Ensure.That(path, () => path).IsNotNullOrWhiteSpace();
|
||||
Ensure.That(path, () => path).IsValidPath(PathValidationType.CurrentOs);
|
||||
|
||||
// Already being watched
|
||||
if (_fileSystemWatchers.ContainsKey(path))
|
||||
{
|
||||
|
||||
@@ -171,6 +171,8 @@ namespace NzbDrone.Host
|
||||
.PersistKeysToFileSystem(new DirectoryInfo(Configuration["dataProtectionFolder"]));
|
||||
|
||||
services.AddSingleton<IAuthorizationPolicyProvider, UiAuthorizationPolicyProvider>();
|
||||
services.AddSingleton<IAuthorizationHandler, UiAuthorizationHandler>();
|
||||
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
options.AddPolicy("SignalR", policy =>
|
||||
|
||||
@@ -38,12 +38,12 @@ namespace NzbDrone.Test.Common
|
||||
Port = port;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
public void Start(bool enableAuth = false)
|
||||
{
|
||||
AppData = Path.Combine(TestContext.CurrentContext.TestDirectory, "_intg_" + TestBase.GetUID());
|
||||
Directory.CreateDirectory(AppData);
|
||||
|
||||
GenerateConfigFile();
|
||||
GenerateConfigFile(enableAuth);
|
||||
|
||||
string readarrConsoleExe;
|
||||
if (OsInfo.IsWindows)
|
||||
@@ -178,7 +178,7 @@ namespace NzbDrone.Test.Common
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateConfigFile()
|
||||
private void GenerateConfigFile(bool enableAuth)
|
||||
{
|
||||
var configFile = Path.Combine(AppData, "config.xml");
|
||||
|
||||
@@ -191,6 +191,8 @@ namespace NzbDrone.Test.Common
|
||||
new XElement(nameof(ConfigFileProvider.ApiKey), apiKey),
|
||||
new XElement(nameof(ConfigFileProvider.LogLevel), "trace"),
|
||||
new XElement(nameof(ConfigFileProvider.AnalyticsEnabled), false),
|
||||
new XElement(nameof(ConfigFileProvider.AuthenticationMethod), enableAuth ? "Forms" : "None"),
|
||||
new XElement(nameof(ConfigFileProvider.AuthenticationRequired), "DisabledForLocalAddresses"),
|
||||
new XElement(nameof(ConfigFileProvider.Port), Port)));
|
||||
|
||||
var data = xDoc.ToString();
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Readarr.Api.V1.Config
|
||||
public bool EnableSsl { get; set; }
|
||||
public bool LaunchBrowser { get; set; }
|
||||
public AuthenticationType AuthenticationMethod { get; set; }
|
||||
public AuthenticationRequiredType AuthenticationRequired { get; set; }
|
||||
public bool AnalyticsEnabled { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
@@ -57,6 +58,7 @@ namespace Readarr.Api.V1.Config
|
||||
EnableSsl = model.EnableSsl,
|
||||
LaunchBrowser = model.LaunchBrowser,
|
||||
AuthenticationMethod = model.AuthenticationMethod,
|
||||
AuthenticationRequired = model.AuthenticationRequired,
|
||||
AnalyticsEnabled = model.AnalyticsEnabled,
|
||||
|
||||
//Username
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Readarr.Http.Authentication
|
||||
public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
|
||||
{
|
||||
public const string DefaultScheme = "API Key";
|
||||
|
||||
public string Scheme => DefaultScheme;
|
||||
public string AuthenticationType = DefaultScheme;
|
||||
|
||||
|
||||
@@ -22,10 +22,16 @@ namespace Readarr.Http.Authentication
|
||||
return authenticationBuilder.AddScheme<AuthenticationSchemeOptions, NoAuthenticationHandler>(name, options => { });
|
||||
}
|
||||
|
||||
public static AuthenticationBuilder AddExternal(this AuthenticationBuilder authenticationBuilder, string name)
|
||||
{
|
||||
return authenticationBuilder.AddScheme<AuthenticationSchemeOptions, NoAuthenticationHandler>(name, options => { });
|
||||
}
|
||||
|
||||
public static AuthenticationBuilder AddAppAuthentication(this IServiceCollection services)
|
||||
{
|
||||
return services.AddAuthentication()
|
||||
.AddNone(AuthenticationType.None.ToString())
|
||||
.AddExternal(AuthenticationType.External.ToString())
|
||||
.AddBasic(AuthenticationType.Basic.ToString())
|
||||
.AddCookie(AuthenticationType.Forms.ToString(), options =>
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.AspNetCore.Authorization.Infrastructure;
|
||||
|
||||
namespace NzbDrone.Http.Authentication
|
||||
{
|
||||
public class BypassableDenyAnonymousAuthorizationRequirement : DenyAnonymousAuthorizationRequirement
|
||||
{
|
||||
}
|
||||
}
|
||||
45
src/Readarr.Http/Authentication/UiAuthorizationHandler.cs
Normal file
45
src/Readarr.Http/Authentication/UiAuthorizationHandler.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Configuration.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using Readarr.Http.Extensions;
|
||||
|
||||
namespace NzbDrone.Http.Authentication
|
||||
{
|
||||
public class UiAuthorizationHandler : AuthorizationHandler<BypassableDenyAnonymousAuthorizationRequirement>, IAuthorizationRequirement, IHandle<ConfigSavedEvent>
|
||||
{
|
||||
private readonly IConfigFileProvider _configService;
|
||||
private static AuthenticationRequiredType _authenticationRequired;
|
||||
|
||||
public UiAuthorizationHandler(IConfigFileProvider configService)
|
||||
{
|
||||
_configService = configService;
|
||||
_authenticationRequired = configService.AuthenticationRequired;
|
||||
}
|
||||
|
||||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BypassableDenyAnonymousAuthorizationRequirement requirement)
|
||||
{
|
||||
if (_authenticationRequired == AuthenticationRequiredType.DisabledForLocalAddresses)
|
||||
{
|
||||
if (context.Resource is HttpContext httpContext &&
|
||||
IPAddress.TryParse(httpContext.GetRemoteIP(), out var ipAddress) &&
|
||||
ipAddress.IsLocalAddress())
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Handle(ConfigSavedEvent message)
|
||||
{
|
||||
_authenticationRequired = _configService.AuthenticationRequired;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,8 @@ namespace NzbDrone.Http.Authentication
|
||||
if (policyName.Equals(POLICY_NAME, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var policy = new AuthorizationPolicyBuilder(_config.AuthenticationMethod.ToString())
|
||||
.RequireAuthenticatedUser();
|
||||
.AddRequirements(new BypassableDenyAnonymousAuthorizationRequirement());
|
||||
|
||||
return Task.FromResult(policy.Build());
|
||||
}
|
||||
|
||||
|
||||
@@ -1508,6 +1508,11 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/redux-actions@2.6.2":
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/redux-actions/-/redux-actions-2.6.2.tgz#5956d9e7b9a644358e2c0610f47b1fa3060edc21"
|
||||
integrity sha512-TvcINy8rWFANcpc3EiEQX9Yv3owM3d3KIrqr2ryUIOhYIYzXA/bhDZeGSSSuai62iVR2qMZUgz9tQ5kr0Kl+Tg==
|
||||
|
||||
"@types/scheduler@*":
|
||||
version "0.16.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5"
|
||||
|
||||
Reference in New Issue
Block a user