using System; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Authentication; 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. /// Whether Quick Connect is enabled on the server or not. [HttpGet("Enabled")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetQuickConnectEnabled() { return _quickConnect.IsEnabled; } /// /// 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. [HttpPost("Initiate")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> InitiateQuickConnect() { try { var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); return _quickConnect.TryConnect(auth); } catch (AuthenticationException) { return Unauthorized("Quick connect is disabled"); } } /// /// Old version of using a GET method. /// Still available to avoid breaking compatibility. /// /// The result of . [Obsolete("Use POST request instead")] [HttpGet("Initiate")] [ApiExplorerSettings(IgnoreApi = true)] public Task> InitiateQuickConnectLegacy() => InitiateQuickConnect(); /// /// 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 GetQuickConnectState([FromQuery, Required] string secret) { try { return _quickConnect.CheckRequestStatus(secret); } catch (ResourceNotFoundException) { return NotFound("Unknown secret"); } catch (AuthenticationException) { return Unauthorized("Quick connect is disabled"); } } /// /// Authorizes a pending quick connect request. /// /// Quick connect code to authorize. /// The user the authorize. Access to the requested user is required. /// Quick connect result authorized successfully. /// Unknown user id. /// Boolean indicating if the authorization was successful. [HttpPost("Authorize")] [Authorize] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> AuthorizeQuickConnect([FromQuery, Required] string code, [FromQuery] Guid? userId = null) { userId = RequestHelpers.GetUserId(User, userId); try { return await _quickConnect.AuthorizeRequest(userId.Value, code).ConfigureAwait(false); } catch (AuthenticationException) { return Unauthorized("Quick connect is disabled"); } } }