using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.StartupDtos; using Jellyfin.Networking.Configuration; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers; /// /// The startup wizard controller. /// [Authorize(Policy = Policies.FirstTimeSetupOrElevated)] public class StartupController : BaseJellyfinApiController { private readonly IServerConfigurationManager _config; private readonly IUserManager _userManager; /// /// Initializes a new instance of the class. /// /// The server configuration manager. /// The user manager. public StartupController(IServerConfigurationManager config, IUserManager userManager) { _config = config; _userManager = userManager; } /// /// Completes the startup wizard. /// /// Startup wizard completed. /// A indicating success. [HttpPost("Complete")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult CompleteWizard() { _config.Configuration.IsStartupWizardCompleted = true; _config.SaveConfiguration(); return NoContent(); } /// /// Gets the initial startup wizard configuration. /// /// Initial startup wizard configuration retrieved. /// An containing the initial startup wizard configuration. [HttpGet("Configuration")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetStartupConfiguration() { return new StartupConfigurationDto { UICulture = _config.Configuration.UICulture, MetadataCountryCode = _config.Configuration.MetadataCountryCode, PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage }; } /// /// Sets the initial startup wizard configuration. /// /// The updated startup configuration. /// Configuration saved. /// A indicating success. [HttpPost("Configuration")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult UpdateInitialConfiguration([FromBody, Required] StartupConfigurationDto startupConfiguration) { _config.Configuration.UICulture = startupConfiguration.UICulture ?? string.Empty; _config.Configuration.MetadataCountryCode = startupConfiguration.MetadataCountryCode ?? string.Empty; _config.Configuration.PreferredMetadataLanguage = startupConfiguration.PreferredMetadataLanguage ?? string.Empty; _config.SaveConfiguration(); return NoContent(); } /// /// Sets remote access and UPnP. /// /// The startup remote access dto. /// Configuration saved. /// A indicating success. [HttpPost("RemoteAccess")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SetRemoteAccess([FromBody, Required] StartupRemoteAccessDto startupRemoteAccessDto) { NetworkConfiguration settings = _config.GetNetworkConfiguration(); settings.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess; settings.EnableUPnP = startupRemoteAccessDto.EnableAutomaticPortMapping; _config.SaveConfiguration(NetworkConfigurationStore.StoreKey, settings); return NoContent(); } /// /// Gets the first user. /// /// Initial user retrieved. /// The first user. [HttpGet("User")] [HttpGet("FirstUser", Name = "GetFirstUser_2")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetFirstUser() { // TODO: Remove this method when startup wizard no longer requires an existing user. await _userManager.InitializeAsync().ConfigureAwait(false); var user = _userManager.Users.First(); return new StartupUserDto { Name = user.Username, Password = user.Password }; } /// /// Sets the user name and password. /// /// The DTO containing username and password. /// Updated user name and password. /// /// A that represents the asynchronous update operation. /// The task result contains a indicating success. /// [HttpPost("User")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task UpdateStartupUser([FromBody] StartupUserDto startupUserDto) { var user = _userManager.Users.First(); if (startupUserDto.Name is not null) { user.Username = startupUserDto.Name; } await _userManager.UpdateUserAsync(user).ConfigureAwait(false); if (!string.IsNullOrEmpty(startupUserDto.Password)) { await _userManager.ChangePassword(user, startupUserDto.Password).ConfigureAwait(false); } return NoContent(); } }