using System; using Jellyfin.Api.Constants; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Devices; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ModelBinding; namespace Jellyfin.Api.Controllers { /// /// Devices Controller. /// [Authorize(Policy = Policies.DefaultAuthorization)] public class DevicesController : BaseJellyfinApiController { private readonly IDeviceManager _deviceManager; private readonly IAuthenticationRepository _authenticationRepository; private readonly ISessionManager _sessionManager; /// /// Initializes a new instance of the class. /// /// Instance of interface. /// Instance of interface. /// Instance of interface. public DevicesController( IDeviceManager deviceManager, IAuthenticationRepository authenticationRepository, ISessionManager sessionManager) { _deviceManager = deviceManager; _authenticationRepository = authenticationRepository; _sessionManager = sessionManager; } /// /// Get Devices. /// /// Gets or sets a value indicating whether [supports synchronize]. /// Gets or sets the user identifier. /// Devices retrieved. /// An containing the list of devices. [HttpGet] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetDevices([FromQuery] bool? supportsSync, [FromQuery] Guid? userId) { var deviceQuery = new DeviceQuery { SupportsSync = supportsSync, UserId = userId ?? Guid.Empty }; return _deviceManager.GetDevices(deviceQuery); } /// /// Get info for a device. /// /// Device Id. /// Device info retrieved. /// Device not found. /// An containing the device info on success, or a if the device could not be found. [HttpGet("Info")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetDeviceInfo([FromQuery, BindRequired] string? id) { var deviceInfo = _deviceManager.GetDevice(id); if (deviceInfo == null) { return NotFound(); } return deviceInfo; } /// /// Get options for a device. /// /// Device Id. /// Device options retrieved. /// Device not found. /// An containing the device info on success, or a if the device could not be found. [HttpGet("Options")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetDeviceOptions([FromQuery, BindRequired] string? id) { var deviceInfo = _deviceManager.GetDeviceOptions(id); if (deviceInfo == null) { return NotFound(); } return deviceInfo; } /// /// Update device options. /// /// Device Id. /// Device Options. /// Device options updated. /// Device not found. /// A on success, or a if the device could not be found. [HttpPost("Options")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult UpdateDeviceOptions( [FromQuery, BindRequired] string? id, [FromBody, BindRequired] DeviceOptions deviceOptions) { var existingDeviceOptions = _deviceManager.GetDeviceOptions(id); if (existingDeviceOptions == null) { return NotFound(); } _deviceManager.UpdateDeviceOptions(id, deviceOptions); return NoContent(); } /// /// Deletes a device. /// /// Device Id. /// Device deleted. /// Device not found. /// A on success, or a if the device could not be found. [HttpDelete] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult DeleteDevice([FromQuery, BindRequired] string? id) { var existingDevice = _deviceManager.GetDevice(id); if (existingDevice == null) { return NotFound(); } var sessions = _authenticationRepository.Get(new AuthenticationInfoQuery { DeviceId = id }).Items; foreach (var session in sessions) { _sessionManager.Logout(session); } return NoContent(); } } }