using System.ComponentModel.DataAnnotations; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.QuickConnect; using MediaBrowser.Model.QuickConnect; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers { /// /// Quick connect controller. /// public class QuickConnectController : BaseJellyfinApiController { private readonly IQuickConnect _quickConnect; private readonly IUserManager _userManager; private readonly IAuthorizationContext _authContext; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. public QuickConnectController( IQuickConnect quickConnect, IUserManager userManager, IAuthorizationContext authContext) { _quickConnect = quickConnect; _userManager = userManager; _authContext = authContext; } /// /// Gets the current quick connect state. /// /// Quick connect state returned. /// The current . [HttpGet("Status")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetStatus() { _quickConnect.ExpireRequests(); return _quickConnect.State; } /// /// Initiate a new quick connect request. /// /// Device friendly name. /// Quick connect request successfully created. /// Quick connect is not active on this server. /// A with a secret and code for future use or an error message. [HttpGet("Initiate")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult Initiate([FromQuery] string? friendlyName) { return _quickConnect.TryConnect(friendlyName); } /// /// Attempts to retrieve authentication information. /// /// Secret previously returned from the Initiate endpoint. /// Quick connect result returned. /// Unknown quick connect secret. /// An updated . [HttpGet("Connect")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult Connect([FromQuery] string? secret) { try { var result = _quickConnect.CheckRequestStatus(secret); return result; } catch (ResourceNotFoundException) { return NotFound("Unknown secret"); } } /// /// Temporarily activates quick connect for five minutes. /// /// Quick connect has been temporarily activated. /// Quick connect is unavailable on this server. /// An on success. [HttpPost("Activate")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult Activate() { if (_quickConnect.State == QuickConnectState.Unavailable) { return Forbid("Quick connect is unavailable"); } _quickConnect.Activate(); return NoContent(); } /// /// Enables or disables quick connect. /// /// New . /// Quick connect state set successfully. /// An on success. [HttpPost("Available")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult Available([FromQuery] QuickConnectState? status) { _quickConnect.SetState(status ?? QuickConnectState.Available); return NoContent(); } /// /// Authorizes a pending quick connect request. /// /// Quick connect code to authorize. /// Quick connect result authorized successfully. /// Missing quick connect code. /// Boolean indicating if the authorization was successful. [HttpPost("Authorize")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult Authorize([FromQuery, Required] string? code) { return _quickConnect.AuthorizeRequest(Request, code); } /// /// Deauthorize all quick connect devices for the current user. /// /// All quick connect devices were deleted. /// The number of devices that were deleted. [HttpPost("Deauthorize")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult Deauthorize() { var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); if (!userId.HasValue) { return 0; } return _quickConnect.DeleteAllDevices(userId.Value); } } }