< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.BackupController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/BackupController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 12
Coverable lines: 12
Total lines: 127
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 2
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
StartRestoreBackup(...)0%620%
SanitizePath(...)100%210%

File(s)

/srv/git/jellyfin/Jellyfin.Api/Controllers/BackupController.cs

#LineLine coverage
 1using System.IO;
 2using System.Threading.Tasks;
 3using Jellyfin.Server.Implementations.SystemBackupService;
 4using MediaBrowser.Common.Api;
 5using MediaBrowser.Common.Configuration;
 6using MediaBrowser.Controller.SystemBackupService;
 7using Microsoft.AspNetCore.Authentication.OAuth.Claims;
 8using Microsoft.AspNetCore.Authorization;
 9using Microsoft.AspNetCore.Http;
 10using Microsoft.AspNetCore.Mvc;
 11using Microsoft.AspNetCore.Mvc.ModelBinding;
 12
 13namespace Jellyfin.Api.Controllers;
 14
 15/// <summary>
 16/// The backup controller.
 17/// </summary>
 18[Authorize(Policy = Policies.RequiresElevation)]
 19public class BackupController : BaseJellyfinApiController
 20{
 21    private readonly IBackupService _backupService;
 22    private readonly IApplicationPaths _applicationPaths;
 23
 24    /// <summary>
 25    /// Initializes a new instance of the <see cref="BackupController"/> class.
 26    /// </summary>
 27    /// <param name="backupService">Instance of the <see cref="IBackupService"/> interface.</param>
 28    /// <param name="applicationPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
 029    public BackupController(IBackupService backupService, IApplicationPaths applicationPaths)
 30    {
 031        _backupService = backupService;
 032        _applicationPaths = applicationPaths;
 033    }
 34
 35    /// <summary>
 36    /// Creates a new Backup.
 37    /// </summary>
 38    /// <param name="backupOptions">The backup options.</param>
 39    /// <response code="200">Backup created.</response>
 40    /// <response code="403">User does not have permission to retrieve information.</response>
 41    /// <returns>The created backup manifest.</returns>
 42    [HttpPost("Create")]
 43    [ProducesResponseType(StatusCodes.Status200OK)]
 44    [ProducesResponseType(StatusCodes.Status403Forbidden)]
 45    public async Task<ActionResult<BackupManifestDto>> CreateBackup([FromBody] BackupOptionsDto backupOptions)
 46    {
 47        return Ok(await _backupService.CreateBackupAsync(backupOptions ?? new()).ConfigureAwait(false));
 48    }
 49
 50    /// <summary>
 51    /// Restores to a backup by restarting the server and applying the backup.
 52    /// </summary>
 53    /// <param name="archiveRestoreDto">The data to start a restore process.</param>
 54    /// <response code="204">Backup restore started.</response>
 55    /// <response code="403">User does not have permission to retrieve information.</response>
 56    /// <returns>No-Content.</returns>
 57    [HttpPost("Restore")]
 58    [ProducesResponseType(StatusCodes.Status204NoContent)]
 59    [ProducesResponseType(StatusCodes.Status404NotFound)]
 60    [ProducesResponseType(StatusCodes.Status403Forbidden)]
 61    public IActionResult StartRestoreBackup([FromBody, BindRequired] BackupRestoreRequestDto archiveRestoreDto)
 62    {
 063        var archivePath = SanitizePath(archiveRestoreDto.ArchiveFileName);
 064        if (!System.IO.File.Exists(archivePath))
 65        {
 066            return NotFound();
 67        }
 68
 069        _backupService.ScheduleRestoreAndRestartServer(archivePath);
 070        return NoContent();
 71    }
 72
 73    /// <summary>
 74    /// Gets a list of all currently present backups in the backup directory.
 75    /// </summary>
 76    /// <response code="200">Backups available.</response>
 77    /// <response code="403">User does not have permission to retrieve information.</response>
 78    /// <returns>The list of backups.</returns>
 79    [HttpGet]
 80    [ProducesResponseType(StatusCodes.Status200OK)]
 81    [ProducesResponseType(StatusCodes.Status403Forbidden)]
 82    public async Task<ActionResult<BackupManifestDto[]>> ListBackups()
 83    {
 84        return Ok(await _backupService.EnumerateBackups().ConfigureAwait(false));
 85    }
 86
 87    /// <summary>
 88    /// Gets the descriptor from an existing archive is present.
 89    /// </summary>
 90    /// <param name="path">The data to start a restore process.</param>
 91    /// <response code="200">Backup archive manifest.</response>
 92    /// <response code="204">Not a valid jellyfin Archive.</response>
 93    /// <response code="404">Not a valid path.</response>
 94    /// <response code="403">User does not have permission to retrieve information.</response>
 95    /// <returns>The backup manifest.</returns>
 96    [HttpGet("Manifest")]
 97    [ProducesResponseType(StatusCodes.Status200OK)]
 98    [ProducesResponseType(StatusCodes.Status204NoContent)]
 99    [ProducesResponseType(StatusCodes.Status404NotFound)]
 100    [ProducesResponseType(StatusCodes.Status403Forbidden)]
 101    public async Task<ActionResult<BackupManifestDto>> GetBackup([BindRequired] string path)
 102    {
 103        var backupPath = SanitizePath(path);
 104
 105        if (!System.IO.File.Exists(backupPath))
 106        {
 107            return NotFound();
 108        }
 109
 110        var manifest = await _backupService.GetBackupManifest(backupPath).ConfigureAwait(false);
 111        if (manifest is null)
 112        {
 113            return NoContent();
 114        }
 115
 116        return Ok(manifest);
 117    }
 118
 119    [NonAction]
 120    private string SanitizePath(string path)
 121    {
 122        // sanitize path
 0123        var archiveRestorePath = Path.GetFileName(Path.GetFullPath(path));
 0124        var archivePath = Path.Combine(_applicationPaths.BackupPath, archiveRestorePath);
 0125        return archivePath;
 126    }
 127}