QuickConnectController.cs 6.5 KB

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