< Summary - Jellyfin

Information
Class: Jellyfin.Api.Controllers.StartupController
Assembly: Jellyfin.Api
File(s): /srv/git/jellyfin/Jellyfin.Api/Controllers/StartupController.cs
Line coverage
83%
Covered lines: 20
Uncovered lines: 4
Coverable lines: 24
Total lines: 154
Line coverage: 83.3%
Branch coverage
50%
Covered branches: 4
Total branches: 8
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%88100%
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>
 3630    public StartupController(IServerConfigurationManager config, IUserManager userManager)
 31    {
 3632        _config = config;
 3633        _userManager = userManager;
 3634    }
 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    {
 1645        _config.Configuration.IsStartupWizardCompleted = true;
 1646        _config.SaveConfiguration();
 1647        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            ServerName = _config.Configuration.ServerName,
 162            UICulture = _config.Configuration.UICulture,
 163            MetadataCountryCode = _config.Configuration.MetadataCountryCode,
 164            PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage
 165        };
 66    }
 67
 68    /// <summary>
 69    /// Sets the initial startup wizard configuration.
 70    /// </summary>
 71    /// <param name="startupConfiguration">The updated startup configuration.</param>
 72    /// <response code="204">Configuration saved.</response>
 73    /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
 74    [HttpPost("Configuration")]
 75    [ProducesResponseType(StatusCodes.Status204NoContent)]
 76    public ActionResult UpdateInitialConfiguration([FromBody, Required] StartupConfigurationDto startupConfiguration)
 77    {
 178        _config.Configuration.ServerName = startupConfiguration.ServerName ?? string.Empty;
 179        _config.Configuration.UICulture = startupConfiguration.UICulture ?? string.Empty;
 180        _config.Configuration.MetadataCountryCode = startupConfiguration.MetadataCountryCode ?? string.Empty;
 181        _config.Configuration.PreferredMetadataLanguage = startupConfiguration.PreferredMetadataLanguage ?? string.Empty
 182        _config.SaveConfiguration();
 183        return NoContent();
 84    }
 85
 86    /// <summary>
 87    /// Sets remote access and UPnP.
 88    /// </summary>
 89    /// <param name="startupRemoteAccessDto">The startup remote access dto.</param>
 90    /// <response code="204">Configuration saved.</response>
 91    /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
 92    [HttpPost("RemoteAccess")]
 93    [ProducesResponseType(StatusCodes.Status204NoContent)]
 94    public ActionResult SetRemoteAccess([FromBody, Required] StartupRemoteAccessDto startupRemoteAccessDto)
 95    {
 096        NetworkConfiguration settings = _config.GetNetworkConfiguration();
 097        settings.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess;
 098        _config.SaveConfiguration(NetworkConfigurationStore.StoreKey, settings);
 099        return NoContent();
 100    }
 101
 102    /// <summary>
 103    /// Gets the first user.
 104    /// </summary>
 105    /// <response code="200">Initial user retrieved.</response>
 106    /// <returns>The first user.</returns>
 107    [HttpGet("User")]
 108    [HttpGet("FirstUser", Name = "GetFirstUser_2")]
 109    [ProducesResponseType(StatusCodes.Status200OK)]
 110    public async Task<StartupUserDto> GetFirstUser()
 111    {
 112        // TODO: Remove this method when startup wizard no longer requires an existing user.
 113        await _userManager.InitializeAsync().ConfigureAwait(false);
 114        var user = _userManager.Users.First();
 115        return new StartupUserDto
 116        {
 117            Name = user.Username
 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}