using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Constants; 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 GetEnabled() { 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. [HttpGet("Initiate")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> Initiate() { try { var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); return _quickConnect.TryConnect(auth); } catch (AuthenticationException) { return Unauthorized("Quick connect is disabled"); } } /// /// 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"); } catch (AuthenticationException) { return Unauthorized("Quick connect is disabled"); } } /// /// Authorizes a pending quick connect request. /// /// Quick connect code to authorize. /// Quick connect result authorized successfully. /// Unknown user id. /// Boolean indicating if the authorization was successful. [HttpPost("Authorize")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> Authorize([FromQuery, Required] string code) { var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); if (!userId.HasValue) { return StatusCode(StatusCodes.Status403Forbidden, "Unknown user id"); } try { return await _quickConnect.AuthorizeRequest(userId.Value, code).ConfigureAwait(false); } catch (AuthenticationException) { return Unauthorized("Quick connect is disabled"); } } } }