using System; using System.ComponentModel.DataAnnotations; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; 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 IAuthorizationContext _authContext; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. public QuickConnectController( IQuickConnect quickConnect, IAuthorizationContext authContext) { _quickConnect = quickConnect; _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. /// /// 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() { return _quickConnect.TryConnect(); } /// /// 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, Required] string secret) { try { return _quickConnect.CheckRequestStatus(secret); } 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 = QuickConnectState.Available) { _quickConnect.SetState(status); return NoContent(); } /// /// Authorizes a pending quick connect request. /// /// Quick connect code to authorize. /// User id. /// Quick connect result authorized successfully. /// User is not allowed to authorize quick connect requests. /// Boolean indicating if the authorization was successful. [HttpPost("Authorize")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult Authorize([FromQuery, Required] string code, [FromQuery, Required] Guid userId) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) { return Forbid("User is not allowed to authorize quick connect requests."); } return _quickConnect.AuthorizeRequest(userId, 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); } } }