2020-06-12 18:54:25 +02:00
using System ;
using System.Collections.Generic ;
using System.ComponentModel.DataAnnotations ;
using System.Linq ;
using System.Threading ;
2021-04-10 22:57:25 +02:00
using System.Threading.Tasks ;
2020-06-22 15:44:11 +02:00
using Jellyfin.Api.Constants ;
2022-10-06 13:57:47 +02:00
using Jellyfin.Api.Extensions ;
2020-06-12 18:54:25 +02:00
using Jellyfin.Api.Helpers ;
2020-10-01 19:57:31 +02:00
using Jellyfin.Api.ModelBinders ;
2020-11-21 19:37:22 +01:00
using Jellyfin.Api.Models.SessionDtos ;
2020-06-19 13:03:53 +02:00
using Jellyfin.Data.Enums ;
2020-06-12 18:54:25 +02:00
using MediaBrowser.Controller.Devices ;
using MediaBrowser.Controller.Library ;
using MediaBrowser.Controller.Session ;
using MediaBrowser.Model.Dto ;
using MediaBrowser.Model.Session ;
using Microsoft.AspNetCore.Authorization ;
using Microsoft.AspNetCore.Http ;
using Microsoft.AspNetCore.Mvc ;
namespace Jellyfin.Api.Controllers
{
/// <summary>
/// The session controller.
/// </summary>
2020-08-04 20:48:53 +02:00
[Route("")]
2020-06-12 18:54:25 +02:00
public class SessionController : BaseJellyfinApiController
{
private readonly ISessionManager _sessionManager ;
private readonly IUserManager _userManager ;
private readonly IDeviceManager _deviceManager ;
/// <summary>
/// Initializes a new instance of the <see cref="SessionController"/> class.
/// </summary>
/// <param name="sessionManager">Instance of <see cref="ISessionManager"/> interface.</param>
/// <param name="userManager">Instance of <see cref="IUserManager"/> interface.</param>
/// <param name="deviceManager">Instance of <see cref="IDeviceManager"/> interface.</param>
public SessionController (
ISessionManager sessionManager ,
IUserManager userManager ,
2020-06-19 13:03:53 +02:00
IDeviceManager deviceManager )
2020-06-12 18:54:25 +02:00
{
_sessionManager = sessionManager ;
_userManager = userManager ;
_deviceManager = deviceManager ;
}
/// <summary>
/// Gets a list of sessions.
/// </summary>
/// <param name="controllableByUserId">Filter by sessions that a given user is allowed to remote control.</param>
/// <param name="deviceId">Filter by device Id.</param>
/// <param name="activeWithinSeconds">Optional. Filter by sessions that were active in the last n seconds.</param>
/// <response code="200">List of sessions returned.</response>
/// <returns>An <see cref="IEnumerable{SessionInfo}"/> with the available sessions.</returns>
2020-08-04 20:48:53 +02:00
[HttpGet("Sessions")]
2020-06-22 15:44:11 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult < IEnumerable < SessionInfo > > GetSessions (
2020-07-07 17:10:51 +02:00
[FromQuery] Guid ? controllableByUserId ,
2020-06-27 18:50:44 +02:00
[FromQuery] string? deviceId ,
2020-06-12 18:54:25 +02:00
[FromQuery] int? activeWithinSeconds )
{
var result = _sessionManager . Sessions ;
if ( ! string . IsNullOrEmpty ( deviceId ) )
{
result = result . Where ( i = > string . Equals ( i . DeviceId , deviceId , StringComparison . OrdinalIgnoreCase ) ) ;
}
2022-02-21 14:15:09 +01:00
if ( controllableByUserId . HasValue & & ! controllableByUserId . Equals ( default ) )
2020-06-12 18:54:25 +02:00
{
result = result . Where ( i = > i . SupportsRemoteControl ) ;
2020-07-07 17:10:51 +02:00
var user = _userManager . GetUserById ( controllableByUserId . Value ) ;
2020-06-12 18:54:25 +02:00
2020-06-19 13:03:53 +02:00
if ( ! user . HasPermission ( PermissionKind . EnableRemoteControlOfOtherUsers ) )
2020-06-12 18:54:25 +02:00
{
2022-02-21 14:15:09 +01:00
result = result . Where ( i = > i . UserId . Equals ( default ) | | i . ContainsUser ( controllableByUserId . Value ) ) ;
2020-06-12 18:54:25 +02:00
}
2020-06-19 13:03:53 +02:00
if ( ! user . HasPermission ( PermissionKind . EnableSharedDeviceControl ) )
2020-06-12 18:54:25 +02:00
{
2022-02-21 14:15:09 +01:00
result = result . Where ( i = > ! i . UserId . Equals ( default ) ) ;
2020-06-12 18:54:25 +02:00
}
if ( activeWithinSeconds . HasValue & & activeWithinSeconds . Value > 0 )
{
var minActiveDate = DateTime . UtcNow . AddSeconds ( 0 - activeWithinSeconds . Value ) ;
result = result . Where ( i = > i . LastActivityDate > = minActiveDate ) ;
}
result = result . Where ( i = >
{
if ( ! string . IsNullOrWhiteSpace ( i . DeviceId ) )
{
if ( ! _deviceManager . CanAccessDevice ( user , i . DeviceId ) )
{
return false ;
}
}
return true ;
} ) ;
}
return Ok ( result ) ;
}
/// <summary>
/// Instructs a session to browse to an item or view.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session Id.</param>
2020-06-12 18:54:25 +02:00
/// <param name="itemType">The type of item to browse to.</param>
/// <param name="itemId">The Id of the item.</param>
/// <param name="itemName">The name of the item.</param>
/// <response code="204">Instruction sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/{sessionId}/Viewing")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > DisplayContent (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2021-12-12 03:31:30 +01:00
[FromQuery, Required] BaseItemKind itemType ,
2020-09-08 02:45:06 +02:00
[FromQuery, Required] string itemId ,
[FromQuery, Required] string itemName )
2020-06-12 18:54:25 +02:00
{
var command = new BrowseRequest
{
ItemId = itemId ,
ItemName = itemName ,
ItemType = itemType
} ;
2021-04-10 22:57:25 +02:00
await _sessionManager . SendBrowseCommand (
2022-10-06 13:57:47 +02:00
await RequestHelpers . GetSessionId ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ,
2020-06-21 02:02:07 +02:00
sessionId ,
2020-06-12 18:54:25 +02:00
command ,
2021-04-10 22:57:25 +02:00
CancellationToken . None )
. ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Instructs a session to play an item.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2020-09-19 16:01:34 +02:00
/// <param name="playCommand">The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.</param>
2020-06-12 18:54:25 +02:00
/// <param name="itemIds">The ids of the items to play, comma delimited.</param>
/// <param name="startPositionTicks">The starting position of the first item.</param>
2021-03-26 12:15:44 +01:00
/// <param name="mediaSourceId">Optional. The media source id.</param>
/// <param name="audioStreamIndex">Optional. The index of the audio stream to play.</param>
/// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to play.</param>
/// <param name="startIndex">Optional. The start index.</param>
2020-06-12 18:54:25 +02:00
/// <response code="204">Instruction sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-09-17 18:54:09 +02:00
[HttpPost("Sessions/{sessionId}/Playing")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > Play (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2020-09-19 16:01:34 +02:00
[FromQuery, Required] PlayCommand playCommand ,
2020-11-17 04:29:46 +01:00
[FromQuery, Required, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid [ ] itemIds ,
2021-03-26 12:15:44 +01:00
[FromQuery] long? startPositionTicks ,
2021-03-26 14:13:45 +01:00
[FromQuery] string? mediaSourceId ,
2021-03-26 12:15:44 +01:00
[FromQuery] int? audioStreamIndex ,
[FromQuery] int? subtitleStreamIndex ,
[FromQuery] int? startIndex )
2020-06-12 18:54:25 +02:00
{
2020-08-21 15:24:44 +02:00
var playRequest = new PlayRequest
2020-06-12 18:54:25 +02:00
{
2020-11-17 04:29:46 +01:00
ItemIds = itemIds ,
2020-08-21 15:24:44 +02:00
StartPositionTicks = startPositionTicks ,
2021-03-26 12:15:44 +01:00
PlayCommand = playCommand ,
MediaSourceId = mediaSourceId ,
AudioStreamIndex = audioStreamIndex ,
SubtitleStreamIndex = subtitleStreamIndex ,
StartIndex = startIndex
2020-08-21 15:24:44 +02:00
} ;
2020-06-12 18:54:25 +02:00
2021-04-10 22:57:25 +02:00
await _sessionManager . SendPlayCommand (
2022-10-11 23:37:29 +02:00
await RequestHelpers . GetSessionId ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ,
2020-06-21 02:02:07 +02:00
sessionId ,
2020-06-12 18:54:25 +02:00
playRequest ,
2021-04-10 22:57:25 +02:00
CancellationToken . None )
. ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Issues a playstate command to a client.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2020-09-20 15:36:46 +02:00
/// <param name="command">The <see cref="PlaystateCommand"/>.</param>
/// <param name="seekPositionTicks">The optional position ticks.</param>
/// <param name="controllingUserId">The optional controlling user id.</param>
2020-06-12 18:54:25 +02:00
/// <response code="204">Playstate command sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-09-17 18:54:09 +02:00
[HttpPost("Sessions/{sessionId}/Playing/{command}")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > SendPlaystateCommand (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2020-09-20 15:36:46 +02:00
[FromRoute, Required] PlaystateCommand command ,
[FromQuery] long? seekPositionTicks ,
[FromQuery] string? controllingUserId )
2020-06-12 18:54:25 +02:00
{
2021-04-10 22:57:25 +02:00
await _sessionManager . SendPlaystateCommand (
2022-10-11 23:37:29 +02:00
await RequestHelpers . GetSessionId ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ,
2020-06-21 02:02:07 +02:00
sessionId ,
2020-09-20 15:36:46 +02:00
new PlaystateRequest ( )
{
Command = command ,
ControllingUserId = controllingUserId ,
SeekPositionTicks = seekPositionTicks ,
} ,
2021-04-10 22:57:25 +02:00
CancellationToken . None )
. ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Issues a system command to a client.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2020-06-12 18:54:25 +02:00
/// <param name="command">The command to send.</param>
/// <response code="204">System command sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/{sessionId}/System/{command}")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > SendSystemCommand (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2020-09-21 17:49:45 +02:00
[FromRoute, Required] GeneralCommandType command )
2020-06-12 18:54:25 +02:00
{
2022-10-06 13:57:47 +02:00
var currentSession = await RequestHelpers . GetSession ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
var generalCommand = new GeneralCommand
{
2020-09-21 17:49:45 +02:00
Name = command ,
2020-06-12 18:54:25 +02:00
ControllingUserId = currentSession . UserId
} ;
2022-10-06 13:57:47 +02:00
await _sessionManager . SendGeneralCommand ( currentSession . Id , sessionId , generalCommand , CancellationToken . None ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Issues a general command to a client.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2020-06-12 18:54:25 +02:00
/// <param name="command">The command to send.</param>
/// <response code="204">General command sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/{sessionId}/Command/{command}")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > SendGeneralCommand (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2020-09-21 17:49:45 +02:00
[FromRoute, Required] GeneralCommandType command )
2020-06-12 18:54:25 +02:00
{
2022-10-06 13:57:47 +02:00
var currentSession = await RequestHelpers . GetSession ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
var generalCommand = new GeneralCommand
{
Name = command ,
ControllingUserId = currentSession . UserId
} ;
2021-04-10 22:57:25 +02:00
await _sessionManager . SendGeneralCommand ( currentSession . Id , sessionId , generalCommand , CancellationToken . None )
. ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Issues a full general command to a client.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2020-06-12 18:54:25 +02:00
/// <param name="command">The <see cref="GeneralCommand"/>.</param>
/// <response code="204">Full general command sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/{sessionId}/Command")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > SendFullGeneralCommand (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2020-06-12 18:54:25 +02:00
[FromBody, Required] GeneralCommand command )
{
2022-10-06 13:57:47 +02:00
var currentSession = await RequestHelpers . GetSession ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
2022-12-05 15:00:20 +01:00
if ( command is null )
2020-06-12 18:54:25 +02:00
{
throw new ArgumentException ( "Request body may not be null" ) ;
}
command . ControllingUserId = currentSession . UserId ;
2021-04-10 22:57:25 +02:00
await _sessionManager . SendGeneralCommand (
2020-06-12 18:54:25 +02:00
currentSession . Id ,
2020-06-21 02:02:07 +02:00
sessionId ,
2020-06-12 18:54:25 +02:00
command ,
2021-04-10 22:57:25 +02:00
CancellationToken . None )
. ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Issues a command to a client to display a message to the user.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2021-03-26 15:02:23 +01:00
/// <param name="command">The <see cref="MessageCommand" /> object containing Header, Message Text, and TimeoutMs.</param>
2020-06-12 18:54:25 +02:00
/// <response code="204">Message sent.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/{sessionId}/Message")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > SendMessageCommand (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2021-03-28 05:28:08 +02:00
[FromBody, Required] MessageCommand command )
2020-06-12 18:54:25 +02:00
{
2021-03-31 07:23:51 +02:00
if ( string . IsNullOrWhiteSpace ( command . Header ) )
2020-06-12 18:54:25 +02:00
{
2021-03-31 07:24:38 +02:00
command . Header = "Message from Server" ;
2021-03-30 13:29:40 +02:00
}
2020-06-12 18:54:25 +02:00
2021-04-10 22:57:25 +02:00
await _sessionManager . SendMessageCommand (
2022-10-06 13:57:47 +02:00
await RequestHelpers . GetSessionId ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ,
2021-04-10 22:57:25 +02:00
sessionId ,
command ,
CancellationToken . None )
. ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Adds an additional user to a session.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2020-06-12 18:54:25 +02:00
/// <param name="userId">The user id.</param>
/// <response code="204">User added to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/{sessionId}/User/{userId}")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult AddUserToSession (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2020-09-06 17:07:27 +02:00
[FromRoute, Required] Guid userId )
2020-06-12 18:54:25 +02:00
{
2020-06-21 02:02:07 +02:00
_sessionManager . AddAdditionalUser ( sessionId , userId ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Removes an additional user from a session.
/// </summary>
2020-06-21 02:02:07 +02:00
/// <param name="sessionId">The session id.</param>
2020-06-12 18:54:25 +02:00
/// <param name="userId">The user id.</param>
/// <response code="204">User removed from session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpDelete("Sessions/{sessionId}/User/{userId}")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult RemoveUserFromSession (
2020-09-08 02:45:06 +02:00
[FromRoute, Required] string sessionId ,
2020-09-06 17:07:27 +02:00
[FromRoute, Required] Guid userId )
2020-06-12 18:54:25 +02:00
{
2020-06-21 02:02:07 +02:00
_sessionManager . RemoveAdditionalUser ( sessionId , userId ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Updates capabilities for a device.
/// </summary>
/// <param name="id">The session id.</param>
/// <param name="playableMediaTypes">A list of playable media types, comma delimited. Audio, Video, Book, Photo.</param>
2020-10-01 19:57:31 +02:00
/// <param name="supportedCommands">A list of supported remote control commands, comma delimited.</param>
2020-06-12 18:54:25 +02:00
/// <param name="supportsMediaControl">Determines whether media can be played remotely..</param>
/// <param name="supportsSync">Determines whether sync is supported.</param>
/// <param name="supportsPersistentIdentifier">Determines whether the device supports a unique identifier.</param>
/// <response code="204">Capabilities posted.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/Capabilities")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > PostCapabilities (
2020-09-09 22:28:30 +02:00
[FromQuery] string? id ,
2020-11-17 04:29:46 +01:00
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string [ ] playableMediaTypes ,
2020-10-14 21:03:36 +02:00
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] GeneralCommandType [ ] supportedCommands ,
2020-07-07 17:10:51 +02:00
[FromQuery] bool supportsMediaControl = false ,
[FromQuery] bool supportsSync = false ,
2020-06-12 18:54:25 +02:00
[FromQuery] bool supportsPersistentIdentifier = true )
{
if ( string . IsNullOrWhiteSpace ( id ) )
{
2022-10-06 13:57:47 +02:00
id = await RequestHelpers . GetSessionId ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
}
_sessionManager . ReportCapabilities ( id , new ClientCapabilities
{
2020-11-17 04:29:46 +01:00
PlayableMediaTypes = playableMediaTypes ,
2020-10-01 22:48:42 +02:00
SupportedCommands = supportedCommands ,
2020-06-12 18:54:25 +02:00
SupportsMediaControl = supportsMediaControl ,
SupportsSync = supportsSync ,
SupportsPersistentIdentifier = supportsPersistentIdentifier
} ) ;
return NoContent ( ) ;
}
/// <summary>
/// Updates capabilities for a device.
/// </summary>
/// <param name="id">The session id.</param>
/// <param name="capabilities">The <see cref="ClientCapabilities"/>.</param>
/// <response code="204">Capabilities updated.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/Capabilities/Full")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > PostFullCapabilities (
2020-08-09 22:12:39 +02:00
[FromQuery] string? id ,
2020-11-21 19:37:22 +01:00
[FromBody, Required] ClientCapabilitiesDto capabilities )
2020-06-12 18:54:25 +02:00
{
if ( string . IsNullOrWhiteSpace ( id ) )
{
2022-10-06 13:57:47 +02:00
id = await RequestHelpers . GetSessionId ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
}
2020-11-21 19:37:22 +01:00
_sessionManager . ReportCapabilities ( id , capabilities . ToClientCapabilities ( ) ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Reports that a session is viewing an item.
/// </summary>
/// <param name="sessionId">The session id.</param>
/// <param name="itemId">The item id.</param>
/// <response code="204">Session reported to server.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/Viewing")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-04-10 22:57:25 +02:00
public async Task < ActionResult > ReportViewing (
2020-06-27 18:50:44 +02:00
[FromQuery] string? sessionId ,
2020-09-20 15:36:46 +02:00
[FromQuery, Required] string? itemId )
2020-06-12 18:54:25 +02:00
{
2022-10-06 13:57:47 +02:00
string session = sessionId ? ? await RequestHelpers . GetSessionId ( _sessionManager , _userManager , HttpContext ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
_sessionManager . ReportNowViewingItem ( session , itemId ) ;
return NoContent ( ) ;
}
/// <summary>
/// Reports that a session has ended.
/// </summary>
/// <response code="204">Session end reported to server.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
2020-08-04 20:48:53 +02:00
[HttpPost("Sessions/Logout")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.DefaultAuthorization)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status204NoContent)]
2021-05-21 05:56:59 +02:00
public async Task < ActionResult > ReportSessionEnded ( )
2020-06-12 18:54:25 +02:00
{
2022-10-06 13:57:47 +02:00
await _sessionManager . Logout ( User . GetToken ( ) ) . ConfigureAwait ( false ) ;
2020-06-12 18:54:25 +02:00
return NoContent ( ) ;
}
/// <summary>
/// Get all auth providers.
/// </summary>
/// <response code="200">Auth providers retrieved.</response>
/// <returns>An <see cref="IEnumerable{NameIdPair}"/> with the auth providers.</returns>
2020-08-04 20:48:53 +02:00
[HttpGet("Auth/Providers")]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.RequiresElevation)]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult < IEnumerable < NameIdPair > > GetAuthProviders ( )
{
return _userManager . GetAuthenticationProviders ( ) ;
}
/// <summary>
/// Get all password reset providers.
/// </summary>
/// <response code="200">Password reset providers retrieved.</response>
/// <returns>An <see cref="IEnumerable{NameIdPair}"/> with the password reset providers.</returns>
2020-08-10 18:09:27 +02:00
[HttpGet("Auth/PasswordResetProviders")]
2020-06-12 18:54:25 +02:00
[ProducesResponseType(StatusCodes.Status200OK)]
2020-08-06 16:17:45 +02:00
[Authorize(Policy = Policies.RequiresElevation)]
2020-06-12 18:54:25 +02:00
public ActionResult < IEnumerable < NameIdPair > > GetPasswordResetProviders ( )
{
return _userManager . GetPasswordResetProviders ( ) ;
}
}
}