< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.StartupController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/StartupController.cs
Line coverage
78%
Covered lines: 18
Uncovered lines: 5
Coverable lines: 23
Total lines: 154
Line coverage: 78.2%
Branch coverage
50%
Covered branches: 3
Total branches: 6
Branch coverage: 50%
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%11100%
CompleteWizard()100%11100%
GetStartupConfiguration()100%11100%
UpdateInitialConfiguration(...)50%66100%
SetRemoteAccess(...)100%210%

File(s)

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

#LineLine coverage
 1using System.ComponentModel.DataAnnotations;
 2using System.Linq;
 3using System.Threading.Tasks;
 4using Jellyfin.Api.Constants;
 5using Jellyfin.Api.Models.StartupDtos;
 6using MediaBrowser.Common.Api;
 7using MediaBrowser.Common.Net;
 8using MediaBrowser.Controller.Configuration;
 9using MediaBrowser.Controller.Library;
 10using Microsoft.AspNetCore.Authorization;
 11using Microsoft.AspNetCore.Http;
 12using Microsoft.AspNetCore.Mvc;
 13
 14namespace Jellyfin.Api.Controllers;
 15
 16/// <summary>
 17/// The startup wizard controller.
 18/// </summary>
 19[Authorize(Policy = Policies.FirstTimeSetupOrElevated)]
 20public class StartupController : BaseJellyfinApiController
 21{
 22    private readonly IServerConfigurationManager _config;
 23    private readonly IUserManager _userManager;
 24
 25    /// <summary>
 26    /// Initializes a new instance of the <see cref="StartupController" /> class.
 27    /// </summary>
 28    /// <param name="config">The server configuration manager.</param>
 29    /// <param name="userManager">The user manager.</param>
 3830    public StartupController(IServerConfigurationManager config, IUserManager userManager)
 31    {
 3832        _config = config;
 3833        _userManager = userManager;
 3834    }
 35
 36    /// <summary>
 37    /// Completes the startup wizard.
 38    /// </summary>
 39    /// <response code="204">Startup wizard completed.</response>
 40    /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
 41    [HttpPost("Complete")]
 42    [ProducesResponseType(StatusCodes.Status204NoContent)]
 43    public ActionResult CompleteWizard()
 44    {
 1745        _config.Configuration.IsStartupWizardCompleted = true;
 1746        _config.SaveConfiguration();
 1747        return NoContent();
 48    }
 49
 50    /// <summary>
 51    /// Gets the initial startup wizard configuration.
 52    /// </summary>
 53    /// <response code="200">Initial startup wizard configuration retrieved.</response>
 54    /// <returns>An <see cref="OkResult"/> containing the initial startup wizard configuration.</returns>
 55    [HttpGet("Configuration")]
 56    [ProducesResponseType(StatusCodes.Status200OK)]
 57    public ActionResult<StartupConfigurationDto> GetStartupConfiguration()
 58    {
 159        return new StartupConfigurationDto
 160        {
 161            UICulture = _config.Configuration.UICulture,
 162            MetadataCountryCode = _config.Configuration.MetadataCountryCode,
 163            PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage
 164        };
 65    }
 66
 67    /// <summary>
 68    /// Sets the initial startup wizard configuration.
 69    /// </summary>
 70    /// <param name="startupConfiguration">The updated startup configuration.</param>
 71    /// <response code="204">Configuration saved.</response>
 72    /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
 73    [HttpPost("Configuration")]
 74    [ProducesResponseType(StatusCodes.Status204NoContent)]
 75    public ActionResult UpdateInitialConfiguration([FromBody, Required] StartupConfigurationDto startupConfiguration)
 76    {
 177        _config.Configuration.UICulture = startupConfiguration.UICulture ?? string.Empty;
 178        _config.Configuration.MetadataCountryCode = startupConfiguration.MetadataCountryCode ?? string.Empty;
 179        _config.Configuration.PreferredMetadataLanguage = startupConfiguration.PreferredMetadataLanguage ?? string.Empty
 180        _config.SaveConfiguration();
 181        return NoContent();
 82    }
 83
 84    /// <summary>
 85    /// Sets remote access and UPnP.
 86    /// </summary>
 87    /// <param name="startupRemoteAccessDto">The startup remote access dto.</param>
 88    /// <response code="204">Configuration saved.</response>
 89    /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
 90    [HttpPost("RemoteAccess")]
 91    [ProducesResponseType(StatusCodes.Status204NoContent)]
 92    public ActionResult SetRemoteAccess([FromBody, Required] StartupRemoteAccessDto startupRemoteAccessDto)
 93    {
 094        NetworkConfiguration settings = _config.GetNetworkConfiguration();
 095        settings.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess;
 096        settings.EnableUPnP = startupRemoteAccessDto.EnableAutomaticPortMapping;
 097        _config.SaveConfiguration(NetworkConfigurationStore.StoreKey, settings);
 098        return NoContent();
 99    }
 100
 101    /// <summary>
 102    /// Gets the first user.
 103    /// </summary>
 104    /// <response code="200">Initial user retrieved.</response>
 105    /// <returns>The first user.</returns>
 106    [HttpGet("User")]
 107    [HttpGet("FirstUser", Name = "GetFirstUser_2")]
 108    [ProducesResponseType(StatusCodes.Status200OK)]
 109    public async Task<StartupUserDto> GetFirstUser()
 110    {
 111        // TODO: Remove this method when startup wizard no longer requires an existing user.
 112        await _userManager.InitializeAsync().ConfigureAwait(false);
 113        var user = _userManager.Users.First();
 114        return new StartupUserDto
 115        {
 116            Name = user.Username,
 117            Password = user.Password
 118        };
 119    }
 120
 121    /// <summary>
 122    /// Sets the user name and password.
 123    /// </summary>
 124    /// <param name="startupUserDto">The DTO containing username and password.</param>
 125    /// <response code="204">Updated user name and password.</response>
 126    /// <returns>
 127    /// A <see cref="Task" /> that represents the asynchronous update operation.
 128    /// The task result contains a <see cref="NoContentResult"/> indicating success.
 129    /// </returns>
 130    [HttpPost("User")]
 131    [ProducesResponseType(StatusCodes.Status204NoContent)]
 132    public async Task<ActionResult> UpdateStartupUser([FromBody] StartupUserDto startupUserDto)
 133    {
 134        var user = _userManager.Users.First();
 135        if (string.IsNullOrWhiteSpace(startupUserDto.Password))
 136        {
 137            return BadRequest("Password must not be empty");
 138        }
 139
 140        if (startupUserDto.Name is not null)
 141        {
 142            user.Username = startupUserDto.Name;
 143        }
 144
 145        await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
 146
 147        if (!string.IsNullOrEmpty(startupUserDto.Password))
 148        {
 149            await _userManager.ChangePassword(user, startupUserDto.Password).ConfigureAwait(false);
 150        }
 151
 152        return NoContent();
 153    }
 154}