QuickConnectController.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using System.ComponentModel.DataAnnotations;
  2. using Jellyfin.Api.Constants;
  3. using MediaBrowser.Common.Extensions;
  4. using MediaBrowser.Controller.Library;
  5. using MediaBrowser.Controller.Net;
  6. using MediaBrowser.Controller.QuickConnect;
  7. using MediaBrowser.Model.QuickConnect;
  8. using Microsoft.AspNetCore.Authorization;
  9. using Microsoft.AspNetCore.Http;
  10. using Microsoft.AspNetCore.Mvc;
  11. namespace Jellyfin.Api.Controllers
  12. {
  13. /// <summary>
  14. /// Quick connect controller.
  15. /// </summary>
  16. public class QuickConnectController : BaseJellyfinApiController
  17. {
  18. private readonly IQuickConnect _quickConnect;
  19. private readonly IUserManager _userManager;
  20. private readonly IAuthorizationContext _authContext;
  21. /// <summary>
  22. /// Initializes a new instance of the <see cref="QuickConnectController"/> class.
  23. /// </summary>
  24. /// <param name="quickConnect">Instance of the <see cref="IQuickConnect"/> interface.</param>
  25. /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
  26. /// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
  27. public QuickConnectController(
  28. IQuickConnect quickConnect,
  29. IUserManager userManager,
  30. IAuthorizationContext authContext)
  31. {
  32. _quickConnect = quickConnect;
  33. _userManager = userManager;
  34. _authContext = authContext;
  35. }
  36. /// <summary>
  37. /// Gets the current quick connect state.
  38. /// </summary>
  39. /// <response code="200">Quick connect state returned.</response>
  40. /// <returns>The current <see cref="QuickConnectState"/>.</returns>
  41. [HttpGet("Status")]
  42. [ProducesResponseType(StatusCodes.Status200OK)]
  43. public ActionResult<QuickConnectState> GetStatus()
  44. {
  45. _quickConnect.ExpireRequests();
  46. return Ok(_quickConnect.State);
  47. }
  48. /// <summary>
  49. /// Initiate a new quick connect request.
  50. /// </summary>
  51. /// <param name="friendlyName">Device friendly name.</param>
  52. /// <response code="200">Quick connect request successfully created.</response>
  53. /// <response code="401">Quick connect is not active on this server.</response>
  54. /// <returns>A <see cref="QuickConnectResult"/> with a secret and code for future use or an error message.</returns>
  55. [HttpGet("Initiate")]
  56. [ProducesResponseType(StatusCodes.Status200OK)]
  57. public ActionResult<QuickConnectResult> Initiate([FromQuery] string? friendlyName)
  58. {
  59. return Ok(_quickConnect.TryConnect(friendlyName));
  60. }
  61. /// <summary>
  62. /// Attempts to retrieve authentication information.
  63. /// </summary>
  64. /// <param name="secret">Secret previously returned from the Initiate endpoint.</param>
  65. /// <response code="200">Quick connect result returned.</response>
  66. /// <response code="404">Unknown quick connect secret.</response>
  67. /// <returns>An updated <see cref="QuickConnectResult"/>.</returns>
  68. [HttpGet("Connect")]
  69. [ProducesResponseType(StatusCodes.Status200OK)]
  70. [ProducesResponseType(StatusCodes.Status404NotFound)]
  71. public ActionResult<QuickConnectResult> Connect([FromQuery] string? secret)
  72. {
  73. try
  74. {
  75. var result = _quickConnect.CheckRequestStatus(secret);
  76. return Ok(result);
  77. }
  78. catch (ResourceNotFoundException)
  79. {
  80. return NotFound("Unknown secret");
  81. }
  82. }
  83. /// <summary>
  84. /// Temporarily activates quick connect for five minutes.
  85. /// </summary>
  86. /// <response code="204">Quick connect has been temporarily activated.</response>
  87. /// <response code="403">Quick connect is unavailable on this server.</response>
  88. /// <returns>An <see cref="NoContentResult"/> on success.</returns>
  89. [HttpPost("Activate")]
  90. [Authorize(Policy = Policies.DefaultAuthorization)]
  91. [ProducesResponseType(StatusCodes.Status204NoContent)]
  92. [ProducesResponseType(StatusCodes.Status403Forbidden)]
  93. public ActionResult Activate()
  94. {
  95. if (_quickConnect.State == QuickConnectState.Unavailable)
  96. {
  97. return Forbid("Quick connect is unavailable");
  98. }
  99. _quickConnect.Activate();
  100. return NoContent();
  101. }
  102. /// <summary>
  103. /// Enables or disables quick connect.
  104. /// </summary>
  105. /// <param name="status">New <see cref="QuickConnectState"/>.</param>
  106. /// <response code="204">Quick connect state set successfully.</response>
  107. /// <returns>An <see cref="NoContentResult"/> on success.</returns>
  108. [HttpPost("Available")]
  109. [Authorize(Policy = Policies.RequiresElevation)]
  110. [ProducesResponseType(StatusCodes.Status204NoContent)]
  111. public ActionResult Available([FromQuery] QuickConnectState? status)
  112. {
  113. _quickConnect.SetState(status ?? QuickConnectState.Available);
  114. return NoContent();
  115. }
  116. /// <summary>
  117. /// Authorizes a pending quick connect request.
  118. /// </summary>
  119. /// <param name="code">Quick connect code to authorize.</param>
  120. /// <response code="200">Quick connect result authorized successfully.</response>
  121. /// <response code="400">Missing quick connect code.</response>
  122. /// <returns>Boolean indicating if the authorization was successful.</returns>
  123. [HttpPost("Authorize")]
  124. [Authorize(Policy = Policies.DefaultAuthorization)]
  125. [ProducesResponseType(StatusCodes.Status200OK)]
  126. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  127. public ActionResult<bool> Authorize([FromQuery, Required] string? code)
  128. {
  129. if (code == null)
  130. {
  131. return BadRequest("Missing code");
  132. }
  133. return Ok(_quickConnect.AuthorizeRequest(Request, code));
  134. }
  135. /// <summary>
  136. /// Deauthorize all quick connect devices for the current user.
  137. /// </summary>
  138. /// <response code="200">All quick connect devices were deleted.</response>
  139. /// <returns>The number of devices that were deleted.</returns>
  140. [HttpPost("Deauthorize")]
  141. [Authorize(Policy = Policies.DefaultAuthorization)]
  142. [ProducesResponseType(StatusCodes.Status200OK)]
  143. public ActionResult<int> Deauthorize()
  144. {
  145. var userId = _authContext.GetAuthorizationInfo(Request).UserId;
  146. return _quickConnect.DeleteAllDevices(userId);
  147. }
  148. }
  149. }