New: Disable backup downloads

pull/6705/head
Bogdan 1 month ago
parent 8a7b67c593
commit da59d63bd1

@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Icon from 'Components/Icon';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
@ -65,7 +64,6 @@ class BackupRow extends Component {
id,
type,
name,
path,
size,
time
} = this.props;
@ -98,12 +96,7 @@ class BackupRow extends Component {
</TableRowCell>
<TableRowCell>
<Link
to={`${window.Sonarr.urlBase}${path}`}
noRouter={true}
>
{name}
</Link>
{name}
</TableRowCell>
<TableRowCell>
@ -155,7 +148,6 @@ BackupRow.propTypes = {
id: PropTypes.number.isRequired,
type: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
time: PropTypes.string.isRequired,
onDeleteBackupPress: PropTypes.func.isRequired

@ -73,6 +73,7 @@ class Backups extends Component {
isPopulated,
error,
items,
location,
backupExecuting,
onBackupPress,
onDeleteBackupPress
@ -101,6 +102,12 @@ class Backups extends Component {
</PageToolbar>
<PageContentBody>
<Alert>
{translate('BackupFilesLocation', {
location
})}
</Alert>
{
isFetching && !isPopulated &&
<LoadingIndicator />
@ -115,7 +122,7 @@ class Backups extends Component {
{
noBackups &&
<Alert kind={kinds.INFO}>
<Alert kind={kinds.WARNING}>
{translate('NoBackupsAreAvailable')}
</Alert>
}
@ -132,7 +139,6 @@ class Backups extends Component {
id,
type,
name,
path,
size,
time
} = item;
@ -143,7 +149,6 @@ class Backups extends Component {
id={id}
type={type}
name={name}
path={path}
size={size}
time={time}
onDeleteBackupPress={onDeleteBackupPress}
@ -171,6 +176,7 @@ Backups.propTypes = {
isPopulated: PropTypes.bool.isRequired,
error: PropTypes.object,
items: PropTypes.array.isRequired,
location: PropTypes.string.isRequired,
backupExecuting: PropTypes.bool.isRequired,
onBackupPress: PropTypes.func.isRequired,
onDeleteBackupPress: PropTypes.func.isRequired

@ -11,21 +11,24 @@ import Backups from './Backups';
function createMapStateToProps() {
return createSelector(
(state) => state.system.backups,
(state) => state.system.status.item,
createCommandExecutingSelector(commandNames.BACKUP),
(backups, backupExecuting) => {
(backups, status, backupExecuting) => {
const {
isFetching,
isPopulated,
error,
items
} = backups;
const { backupFolder } = status;
return {
isFetching,
isPopulated,
error,
items,
backupExecuting
backupExecuting,
location: backupFolder
};
}
);

@ -4,18 +4,7 @@ namespace NzbDrone.Core.Backup
{
public class BackupCommand : Command
{
public BackupType Type
{
get
{
if (Trigger == CommandTrigger.Scheduled)
{
return BackupType.Scheduled;
}
return BackupType.Manual;
}
}
public BackupType Type => Trigger == CommandTrigger.Scheduled ? BackupType.Scheduled : BackupType.Manual;
public override bool SendUpdatesToClient => true;

@ -105,12 +105,12 @@ namespace NzbDrone.Core.Backup
if (_diskProvider.FolderExists(folder))
{
backups.AddRange(GetBackupFiles(folder).Select(b => new Backup
{
Name = Path.GetFileName(b),
Type = backupType,
Size = _diskProvider.GetFileSize(b),
Time = _diskProvider.FileGetLastWrite(b)
}));
{
Name = Path.GetFileName(b),
Type = backupType,
Size = _diskProvider.GetFileSize(b),
Time = _diskProvider.FileGetLastWrite(b)
}));
}
}

@ -142,6 +142,7 @@
"AutomaticSearch": "Automatic Search",
"AutomaticUpdatesDisabledDocker": "Automatic updates are not directly supported when using the Docker update mechanism. You will need to update the container image outside of {appName} or use a script",
"Backup": "Backup",
"BackupFilesLocation": "Backup files are located in: {location}",
"BackupFolderHelpText": "Relative paths will be under {appName}'s AppData directory",
"BackupIntervalHelpText": "Interval between automatic backups",
"BackupNow": "Backup Now",
@ -248,8 +249,8 @@
"ConnectionLost": "Connection Lost",
"ConnectionLostReconnect": "{appName} will try to connect automatically, or you can click reload below.",
"ConnectionLostToBackend": "{appName} has lost its connection to the backend and will need to be reloaded to restore functionality.",
"Connections": "Connections",
"ConnectionSettingsUrlBaseHelpText": "Adds a prefix to the {connectionName} url, such as {url}",
"Connections": "Connections",
"Continuing": "Continuing",
"ContinuingOnly": "Continuing Only",
"ContinuingSeriesDescription": "More episodes/another season is expected",
@ -280,8 +281,8 @@
"CustomFormats": "Custom Formats",
"CustomFormatsLoadError": "Unable to load Custom Formats",
"CustomFormatsSettings": "Custom Formats Settings",
"CustomFormatsSettingsTriggerInfo": "A Custom Format will be applied to a release or file when it matches at least one of each of the different condition types chosen.",
"CustomFormatsSettingsSummary": "Custom Formats and Settings",
"CustomFormatsSettingsTriggerInfo": "A Custom Format will be applied to a release or file when it matches at least one of each of the different condition types chosen.",
"CustomFormatsSpecificationFlag": "Flag",
"CustomFormatsSpecificationLanguage": "Language",
"CustomFormatsSpecificationMaximumSize": "Maximum Size",
@ -410,16 +411,16 @@
"DownloadClientAriaSettingsDirectoryHelpText": "Optional location to put downloads in, leave blank to use the default Aria2 location",
"DownloadClientCheckNoneAvailableHealthCheckMessage": "No download client is available",
"DownloadClientCheckUnableToCommunicateWithHealthCheckMessage": "Unable to communicate with {downloadClientName}. {errorMessage}",
"DownloadClientDelugeSettingsDirectory": "Download Directory",
"DownloadClientDelugeSettingsDirectoryCompleted": "Move When Completed Directory",
"DownloadClientDelugeSettingsDirectoryCompletedHelpText": "Optional location to move completed downloads to, leave blank to use the default Deluge location",
"DownloadClientDelugeSettingsDirectoryHelpText": "Optional location to put downloads in, leave blank to use the default Deluge location",
"DownloadClientDelugeSettingsUrlBaseHelpText": "Adds a prefix to the deluge json url, see {url}",
"DownloadClientDelugeTorrentStateError": "Deluge is reporting an error",
"DownloadClientDelugeValidationLabelPluginFailure": "Configuration of label failed",
"DownloadClientDelugeValidationLabelPluginFailureDetail": "{appName} was unable to add the label to {clientName}.",
"DownloadClientDelugeValidationLabelPluginInactive": "Label plugin not activated",
"DownloadClientDelugeValidationLabelPluginInactiveDetail": "You must have the Label plugin enabled in {clientName} to use categories.",
"DownloadClientDelugeSettingsDirectory": "Download Directory",
"DownloadClientDelugeSettingsDirectoryHelpText": "Optional location to put downloads in, leave blank to use the default Deluge location",
"DownloadClientDelugeSettingsDirectoryCompleted": "Move When Completed Directory",
"DownloadClientDelugeSettingsDirectoryCompletedHelpText": "Optional location to move completed downloads to, leave blank to use the default Deluge location",
"DownloadClientDownloadStationProviderMessage": "{appName} is unable to connect to Download Station if 2-Factor Authentication is enabled on your DSM account",
"DownloadClientDownloadStationSettingsDirectoryHelpText": "Optional shared folder to put downloads into, leave blank to use the default Download Station location",
"DownloadClientDownloadStationValidationApiVersion": "Download Station API version not supported, should be at least {requiredVersion}. It supports from {minVersion} to {maxVersion}",
@ -866,12 +867,12 @@
"ImportListsSimklSettingsUserListTypePlanToWatch": "Plan To Watch",
"ImportListsSimklSettingsUserListTypeWatching": "Watching",
"ImportListsSonarrSettingsApiKeyHelpText": "API Key of the {appName} instance to import from",
"ImportListsSonarrSettingsSyncSeasonMonitoring": "Sync Season Monitoring",
"ImportListsSonarrSettingsSyncSeasonMonitoringHelpText": "Sync season monitoring from {appName} instance, if enabled 'Monitor' will be ignored",
"ImportListsSonarrSettingsFullUrl": "Full URL",
"ImportListsSonarrSettingsFullUrlHelpText": "URL, including port, of the {appName} instance to import from",
"ImportListsSonarrSettingsQualityProfilesHelpText": "Quality Profiles from the source instance to import from",
"ImportListsSonarrSettingsRootFoldersHelpText": "Root Folders from the source instance to import from",
"ImportListsSonarrSettingsSyncSeasonMonitoring": "Sync Season Monitoring",
"ImportListsSonarrSettingsSyncSeasonMonitoringHelpText": "Sync season monitoring from {appName} instance, if enabled 'Monitor' will be ignored",
"ImportListsSonarrSettingsTagsHelpText": "Tags from the source instance to import from",
"ImportListsSonarrValidationInvalidUrl": "{appName} URL is invalid, are you missing a URL base?",
"ImportListsTraktSettingsAdditionalParameters": "Additional Parameters",
@ -1787,7 +1788,6 @@
"SelectSeries": "Select Series",
"SendAnonymousUsageData": "Send Anonymous Usage Data",
"Series": "Series",
"SeriesFootNote": "Optionally control truncation to a maximum number of bytes including ellipsis (`...`). Truncating from the end (e.g. `{Series Title:30}`) or the beginning (e.g. `{Series Title:-30}`) are both supported.",
"SeriesAndEpisodeInformationIsProvidedByTheTVDB": "Series and episode information is provided by TheTVDB.com. [Please consider supporting them]({url}) .",
"SeriesCannotBeFound": "Sorry, that series cannot be found.",
"SeriesDetailsCountEpisodeFiles": "{episodeFileCount} episode files",
@ -1801,6 +1801,7 @@
"SeriesFolderFormat": "Series Folder Format",
"SeriesFolderFormatHelpText": "Used when adding a new series or moving series via the series editor",
"SeriesFolderImportedTooltip": "Episode imported from series folder",
"SeriesFootNote": "Optionally control truncation to a maximum number of bytes including ellipsis (`...`). Truncating from the end (e.g. `{Series Title:30}`) or the beginning (e.g. `{Series Title:-30}`) are both supported.",
"SeriesID": "Series ID",
"SeriesIndexFooterContinuing": "Continuing (All episodes downloaded)",
"SeriesIndexFooterDownloading": "Downloading (One or more episodes)",

@ -40,7 +40,6 @@ namespace Sonarr.Api.V3.System.Backup
{
Id = GetBackupId(b),
Name = b.Name,
Path = $"/backup/{b.Type.ToString().ToLower()}/{b.Name}",
Size = b.Size,
Type = b.Type,
Time = b.Time

@ -7,7 +7,6 @@ namespace Sonarr.Api.V3.System.Backup
public class BackupResource : RestResource
{
public string Name { get; set; }
public string Path { get; set; }
public BackupType Type { get; set; }
public long Size { get; set; }
public DateTime Time { get; set; }

@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Internal;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Backup;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Lifecycle;
@ -27,6 +28,7 @@ namespace Sonarr.Api.V3.System
private readonly EndpointDataSource _endpointData;
private readonly DfaGraphWriter _graphWriter;
private readonly DuplicateEndpointDetector _detector;
private readonly IBackupService _backupService;
public SystemController(IAppFolderInfo appFolderInfo,
IRuntimeInfo runtimeInfo,
@ -38,7 +40,8 @@ namespace Sonarr.Api.V3.System
IDeploymentInfoProvider deploymentInfoProvider,
EndpointDataSource endpoints,
DfaGraphWriter graphWriter,
DuplicateEndpointDetector detector)
DuplicateEndpointDetector detector,
IBackupService backupService)
{
_appFolderInfo = appFolderInfo;
_runtimeInfo = runtimeInfo;
@ -51,6 +54,7 @@ namespace Sonarr.Api.V3.System
_endpointData = endpoints;
_graphWriter = graphWriter;
_detector = detector;
_backupService = backupService;
}
[HttpGet("status")]
@ -69,6 +73,7 @@ namespace Sonarr.Api.V3.System
IsUserInteractive = RuntimeInfo.IsUserInteractive,
StartupPath = _appFolderInfo.StartUpFolder,
AppData = _appFolderInfo.GetAppDataPath(),
BackupFolder = _backupService.GetBackupFolder(),
OsName = _osInfo.Name,
OsVersion = _osInfo.Version,
IsNetCore = true,

@ -18,6 +18,7 @@ namespace Sonarr.Api.V3.System
public bool IsUserInteractive { get; set; }
public string StartupPath { get; set; }
public string AppData { get; set; }
public string BackupFolder { get; set; }
public string OsName { get; set; }
public string OsVersion { get; set; }
public bool IsNetCore { get; set; }

@ -1,30 +0,0 @@
using System.IO;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Backup;
namespace Sonarr.Http.Frontend.Mappers
{
public class BackupFileMapper : StaticResourceMapperBase
{
private readonly IBackupService _backupService;
public BackupFileMapper(IBackupService backupService, IDiskProvider diskProvider, Logger logger)
: base(diskProvider, logger)
{
_backupService = backupService;
}
public override string Map(string resourceUrl)
{
var path = resourceUrl.Replace("/backup/", "").Replace('/', Path.DirectorySeparatorChar);
return Path.Combine(_backupService.GetBackupFolder(), path);
}
public override bool CanHandle(string resourceUrl)
{
return resourceUrl.StartsWith("/backup/") && BackupService.BackupFileRegex.IsMatch(resourceUrl);
}
}
}
Loading…
Cancel
Save