fix: use HttpContext and ClaimsPrincipal instead of IAuthorizationContext

This commit is contained in:
cvium 2022-10-06 13:57:47 +02:00
parent 927fe33d3a
commit 5dc30c6a6d
44 changed files with 334 additions and 495 deletions

View file

@ -630,8 +630,6 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>(); serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
serviceCollection.AddScoped<ISessionContext, SessionContext>();
serviceCollection.AddSingleton<IAuthService, AuthService>(); serviceCollection.AddSingleton<IAuthService, AuthService>();
serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>(); serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();

View file

@ -1,59 +0,0 @@
#pragma warning disable CS1591
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using Microsoft.AspNetCore.Http;
namespace Emby.Server.Implementations.HttpServer.Security
{
public class SessionContext : ISessionContext
{
private readonly IUserManager _userManager;
private readonly ISessionManager _sessionManager;
private readonly IAuthorizationContext _authContext;
public SessionContext(IUserManager userManager, IAuthorizationContext authContext, ISessionManager sessionManager)
{
_userManager = userManager;
_authContext = authContext;
_sessionManager = sessionManager;
}
public async Task<SessionInfo> GetSession(HttpContext requestContext)
{
var authorization = await _authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false);
var user = authorization.User;
return await _sessionManager.LogSessionActivity(
authorization.Client,
authorization.Version,
authorization.DeviceId,
authorization.Device,
requestContext.GetNormalizedRemoteIp().ToString(),
user).ConfigureAwait(false);
}
public Task<SessionInfo> GetSession(object requestContext)
{
return GetSession((HttpContext)requestContext);
}
public async Task<User?> GetUser(HttpContext requestContext)
{
var session = await GetSession(requestContext).ConfigureAwait(false);
return session.UserId.Equals(default)
? null
: _userManager.GetUserById(session.UserId);
}
public Task<User?> GetUser(object requestContext)
{
return GetUser(((HttpRequest)requestContext).HttpContext);
}
}
}

View file

@ -6,6 +6,7 @@ using System.Linq;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
@ -53,7 +54,6 @@ namespace Emby.Server.Implementations.Session
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
private readonly ILogger<SessionWebSocketListener> _logger; private readonly ILogger<SessionWebSocketListener> _logger;
private readonly ILoggerFactory _loggerFactory; private readonly ILoggerFactory _loggerFactory;
private readonly IAuthorizationContext _authorizationContext;
/// <summary> /// <summary>
/// The KeepAlive cancellation token. /// The KeepAlive cancellation token.
@ -66,17 +66,14 @@ namespace Emby.Server.Implementations.Session
/// <param name="logger">The logger.</param> /// <param name="logger">The logger.</param>
/// <param name="sessionManager">The session manager.</param> /// <param name="sessionManager">The session manager.</param>
/// <param name="loggerFactory">The logger factory.</param> /// <param name="loggerFactory">The logger factory.</param>
/// <param name="authorizationContext">The authorization context.</param>
public SessionWebSocketListener( public SessionWebSocketListener(
ILogger<SessionWebSocketListener> logger, ILogger<SessionWebSocketListener> logger,
ISessionManager sessionManager, ISessionManager sessionManager,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory)
IAuthorizationContext authorizationContext)
{ {
_logger = logger; _logger = logger;
_sessionManager = sessionManager; _sessionManager = sessionManager;
_loggerFactory = loggerFactory; _loggerFactory = loggerFactory;
_authorizationContext = authorizationContext;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -110,21 +107,18 @@ namespace Emby.Server.Implementations.Session
private async Task<SessionInfo> GetSession(HttpContext httpContext, string remoteEndpoint) private async Task<SessionInfo> GetSession(HttpContext httpContext, string remoteEndpoint)
{ {
var authorizationInfo = await _authorizationContext.GetAuthorizationInfo(httpContext) if (!httpContext.User.Identity?.IsAuthenticated ?? false)
.ConfigureAwait(false);
if (!authorizationInfo.IsAuthenticated)
{ {
return null; return null;
} }
var deviceId = authorizationInfo.DeviceId; var deviceId = httpContext.User.GetDeviceId();
if (httpContext.Request.Query.TryGetValue("deviceId", out var queryDeviceId)) if (httpContext.Request.Query.TryGetValue("deviceId", out var queryDeviceId))
{ {
deviceId = queryDeviceId; deviceId = queryDeviceId;
} }
return await _sessionManager.GetSessionByAuthenticationToken(authorizationInfo.Token, deviceId, remoteEndpoint) return await _sessionManager.GetSessionByAuthenticationToken(httpContext.User.GetToken(), deviceId, remoteEndpoint)
.ConfigureAwait(false); .ConfigureAwait(false);
} }

View file

@ -1,4 +1,5 @@
using System.Security.Claims; using System.Security.Claims;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
@ -51,21 +52,21 @@ namespace Jellyfin.Api.Auth
bool requiredDownloadPermission = false) bool requiredDownloadPermission = false)
{ {
// ApiKey is currently global admin, always allow. // ApiKey is currently global admin, always allow.
var isApiKey = ClaimHelpers.GetIsApiKey(claimsPrincipal); var isApiKey = claimsPrincipal.GetIsApiKey();
if (isApiKey) if (isApiKey)
{ {
return true; return true;
} }
// Ensure claim has userId. // Ensure claim has userId.
var userId = ClaimHelpers.GetUserId(claimsPrincipal); var userId = claimsPrincipal.GetUserId();
if (!userId.HasValue) if (userId.Equals(default))
{ {
return false; return false;
} }
// Ensure userId links to a valid user. // Ensure userId links to a valid user.
var user = _userManager.GetUserById(userId.Value); var user = _userManager.GetUserById(userId);
if (user == null) if (user == null)
{ {
return false; return false;

View file

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
@ -44,14 +45,14 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
return Task.CompletedTask; return Task.CompletedTask;
} }
var userId = ClaimHelpers.GetUserId(context.User); var userId = context.User.GetUserId();
var user = _userManager.GetUserById(userId!.Value); var user = _userManager.GetUserById(userId);
if (requirement.RequiredAccess == SyncPlayAccessRequirementType.HasAccess) if (requirement.RequiredAccess == SyncPlayAccessRequirementType.HasAccess)
{ {
if (user.SyncPlayAccess == SyncPlayUserAccessType.CreateAndJoinGroups if (user.SyncPlayAccess == SyncPlayUserAccessType.CreateAndJoinGroups
|| user.SyncPlayAccess == SyncPlayUserAccessType.JoinGroups || user.SyncPlayAccess == SyncPlayUserAccessType.JoinGroups
|| _syncPlayManager.IsUserActive(userId.Value)) || _syncPlayManager.IsUserActive(userId))
{ {
context.Succeed(requirement); context.Succeed(requirement);
} }
@ -85,7 +86,7 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy
} }
else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.IsInGroup) else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.IsInGroup)
{ {
if (_syncPlayManager.IsUserActive(userId.Value)) if (_syncPlayManager.IsUserActive(userId))
{ {
context.Succeed(requirement); context.Succeed(requirement);
} }

View file

@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true) [FromQuery] bool enableTotalRecordCount = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
User? user = null; User? user = null;
@ -323,7 +323,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true) [FromQuery] bool enableTotalRecordCount = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
User? user = null; User? user = null;
@ -463,7 +463,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<BaseItemDto> GetArtistByName([FromRoute, Required] string name, [FromQuery] Guid? userId) public ActionResult<BaseItemDto> GetArtistByName([FromRoute, Required] string name, [FromQuery] Guid? userId)
{ {
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var item = _libraryManager.GetArtist(name, dtoOptions); var item = _libraryManager.GetArtist(name, dtoOptions);

View file

@ -2,6 +2,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.ClientLogDtos; using Jellyfin.Api.Models.ClientLogDtos;
using MediaBrowser.Controller.ClientEvent; using MediaBrowser.Controller.ClientEvent;
@ -69,10 +70,10 @@ namespace Jellyfin.Api.Controllers
private (string ClientName, string ClientVersion) GetRequestInformation() private (string ClientName, string ClientVersion) GetRequestInformation()
{ {
var clientName = ClaimHelpers.GetClient(HttpContext.User) ?? "unknown-client"; var clientName = HttpContext.User.GetClient() ?? "unknown-client";
var clientVersion = ClaimHelpers.GetIsApiKey(HttpContext.User) var clientVersion = HttpContext.User.GetIsApiKey()
? "apikey" ? "apikey"
: ClaimHelpers.GetVersion(HttpContext.User) ?? "unknown-version"; : HttpContext.User.GetVersion() ?? "unknown-version";
return (clientName, clientVersion); return (clientName, clientVersion);
} }

View file

@ -6,7 +6,6 @@ using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Collections; using MediaBrowser.Model.Collections;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -23,22 +22,18 @@ namespace Jellyfin.Api.Controllers
{ {
private readonly ICollectionManager _collectionManager; private readonly ICollectionManager _collectionManager;
private readonly IDtoService _dtoService; private readonly IDtoService _dtoService;
private readonly IAuthorizationContext _authContext;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CollectionController"/> class. /// Initializes a new instance of the <see cref="CollectionController"/> class.
/// </summary> /// </summary>
/// <param name="collectionManager">Instance of <see cref="ICollectionManager"/> interface.</param> /// <param name="collectionManager">Instance of <see cref="ICollectionManager"/> interface.</param>
/// <param name="dtoService">Instance of <see cref="IDtoService"/> interface.</param> /// <param name="dtoService">Instance of <see cref="IDtoService"/> interface.</param>
/// <param name="authContext">Instance of <see cref="IAuthorizationContext"/> interface.</param>
public CollectionController( public CollectionController(
ICollectionManager collectionManager, ICollectionManager collectionManager,
IDtoService dtoService, IDtoService dtoService)
IAuthorizationContext authContext)
{ {
_collectionManager = collectionManager; _collectionManager = collectionManager;
_dtoService = dtoService; _dtoService = dtoService;
_authContext = authContext;
} }
/// <summary> /// <summary>
@ -58,7 +53,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] Guid? parentId, [FromQuery] Guid? parentId,
[FromQuery] bool isLocked = false) [FromQuery] bool isLocked = false)
{ {
var userId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).UserId; var userId = User.GetUserId();
var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions
{ {
@ -69,7 +64,7 @@ namespace Jellyfin.Api.Controllers
UserIds = new[] { userId } UserIds = new[] { userId }
}).ConfigureAwait(false); }).ConfigureAwait(false);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var dto = _dtoService.GetBaseItemDto(item, dtoOptions); var dto = _dtoService.GetBaseItemDto(item, dtoOptions);

View file

@ -20,7 +20,6 @@ using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
@ -46,7 +45,6 @@ namespace Jellyfin.Api.Controllers
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IDlnaManager _dlnaManager; private readonly IDlnaManager _dlnaManager;
private readonly IAuthorizationContext _authContext;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
@ -65,7 +63,6 @@ namespace Jellyfin.Api.Controllers
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
@ -80,7 +77,6 @@ namespace Jellyfin.Api.Controllers
ILibraryManager libraryManager, ILibraryManager libraryManager,
IUserManager userManager, IUserManager userManager,
IDlnaManager dlnaManager, IDlnaManager dlnaManager,
IAuthorizationContext authContext,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder, IMediaEncoder mediaEncoder,
@ -95,7 +91,6 @@ namespace Jellyfin.Api.Controllers
_libraryManager = libraryManager; _libraryManager = libraryManager;
_userManager = userManager; _userManager = userManager;
_dlnaManager = dlnaManager; _dlnaManager = dlnaManager;
_authContext = authContext;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
@ -287,8 +282,7 @@ namespace Jellyfin.Api.Controllers
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var state = await StreamingHelpers.GetStreamingState( var state = await StreamingHelpers.GetStreamingState(
streamingRequest, streamingRequest,
Request, HttpContext,
_authContext,
_mediaSourceManager, _mediaSourceManager,
_userManager, _userManager,
_libraryManager, _libraryManager,
@ -1393,8 +1387,7 @@ namespace Jellyfin.Api.Controllers
{ {
using var state = await StreamingHelpers.GetStreamingState( using var state = await StreamingHelpers.GetStreamingState(
streamingRequest, streamingRequest,
Request, HttpContext,
_authContext,
_mediaSourceManager, _mediaSourceManager,
_userManager, _userManager,
_libraryManager, _libraryManager,
@ -1434,8 +1427,7 @@ namespace Jellyfin.Api.Controllers
var state = await StreamingHelpers.GetStreamingState( var state = await StreamingHelpers.GetStreamingState(
streamingRequest, streamingRequest,
Request, HttpContext,
_authContext,
_mediaSourceManager, _mediaSourceManager,
_userManager, _userManager,
_libraryManager, _libraryManager,

View file

@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true) [FromQuery] bool enableTotalRecordCount = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
User? user = userId is null || userId.Value.Equals(default) User? user = userId is null || userId.Value.Equals(default)
@ -157,7 +157,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<BaseItemDto> GetGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) public ActionResult<BaseItemDto> GetGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId)
{ {
var dtoOptions = new DtoOptions() var dtoOptions = new DtoOptions()
.AddClientFields(Request); .AddClientFields(User);
Genre? item; Genre? item;
if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase)) if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase))

View file

@ -17,7 +17,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Branding; using MediaBrowser.Model.Branding;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
@ -44,11 +43,9 @@ namespace Jellyfin.Api.Controllers
private readonly IProviderManager _providerManager; private readonly IProviderManager _providerManager;
private readonly IImageProcessor _imageProcessor; private readonly IImageProcessor _imageProcessor;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IAuthorizationContext _authContext;
private readonly ILogger<ImageController> _logger; private readonly ILogger<ImageController> _logger;
private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly IImageEncoder _imageEncoder;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ImageController"/> class. /// Initializes a new instance of the <see cref="ImageController"/> class.
@ -58,33 +55,27 @@ namespace Jellyfin.Api.Controllers
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param> /// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
/// <param name="imageProcessor">Instance of the <see cref="IImageProcessor"/> interface.</param> /// <param name="imageProcessor">Instance of the <see cref="IImageProcessor"/> interface.</param>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{ImageController}"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{ImageController}"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param> /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
/// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param>
public ImageController( public ImageController(
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IProviderManager providerManager, IProviderManager providerManager,
IImageProcessor imageProcessor, IImageProcessor imageProcessor,
IFileSystem fileSystem, IFileSystem fileSystem,
IAuthorizationContext authContext,
ILogger<ImageController> logger, ILogger<ImageController> logger,
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
IApplicationPaths appPaths, IApplicationPaths appPaths)
IImageEncoder imageEncoder)
{ {
_userManager = userManager; _userManager = userManager;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_providerManager = providerManager; _providerManager = providerManager;
_imageProcessor = imageProcessor; _imageProcessor = imageProcessor;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_authContext = authContext;
_logger = logger; _logger = logger;
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
_appPaths = appPaths; _appPaths = appPaths;
_imageEncoder = imageEncoder;
} }
/// <summary> /// <summary>
@ -108,7 +99,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromQuery] int? index = null) [FromQuery] int? index = null)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image.");
} }
@ -155,7 +146,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute] int index) [FromRoute] int index)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image.");
} }
@ -201,7 +192,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromQuery] int? index = null) [FromQuery] int? index = null)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image.");
} }
@ -245,7 +236,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute] int index) [FromRoute] int index)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image.");
} }

View file

@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
return GetResult(items, user, limit, dtoOptions); return GetResult(items, user, limit, dtoOptions);
@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions); var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions);
return GetResult(items, user, limit, dtoOptions); return GetResult(items, user, limit, dtoOptions);
@ -151,7 +151,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions); var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions);
return GetResult(items, user, limit, dtoOptions); return GetResult(items, user, limit, dtoOptions);
@ -186,7 +186,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions); var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions);
return GetResult(items, user, limit, dtoOptions); return GetResult(items, user, limit, dtoOptions);
@ -222,7 +222,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
return GetResult(items, user, limit, dtoOptions); return GetResult(items, user, limit, dtoOptions);
@ -258,7 +258,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
return GetResult(items, user, limit, dtoOptions); return GetResult(items, user, limit, dtoOptions);
@ -331,7 +331,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
return GetResult(items, user, limit, dtoOptions); return GetResult(items, user, limit, dtoOptions);

View file

@ -10,7 +10,6 @@ using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -34,7 +33,6 @@ namespace Jellyfin.Api.Controllers
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly IDtoService _dtoService; private readonly IDtoService _dtoService;
private readonly IAuthorizationContext _authContext;
private readonly ILogger<ItemsController> _logger; private readonly ILogger<ItemsController> _logger;
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
@ -45,7 +43,6 @@ namespace Jellyfin.Api.Controllers
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
/// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
public ItemsController( public ItemsController(
@ -53,7 +50,6 @@ namespace Jellyfin.Api.Controllers
ILibraryManager libraryManager, ILibraryManager libraryManager,
ILocalizationManager localization, ILocalizationManager localization,
IDtoService dtoService, IDtoService dtoService,
IAuthorizationContext authContext,
ILogger<ItemsController> logger, ILogger<ItemsController> logger,
ISessionManager sessionManager) ISessionManager sessionManager)
{ {
@ -61,7 +57,6 @@ namespace Jellyfin.Api.Controllers
_libraryManager = libraryManager; _libraryManager = libraryManager;
_localization = localization; _localization = localization;
_dtoService = dtoService; _dtoService = dtoService;
_authContext = authContext;
_logger = logger; _logger = logger;
_sessionManager = sessionManager; _sessionManager = sessionManager;
} }
@ -244,21 +239,20 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true, [FromQuery] bool enableTotalRecordCount = true,
[FromQuery] bool? enableImages = true) [FromQuery] bool? enableImages = true)
{ {
var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var isApiKey = User.GetIsApiKey();
// if api key is used (auth.IsApiKey == true), then `user` will be null throughout this method // if api key is used (auth.IsApiKey == true), then `user` will be null throughout this method
var user = !auth.IsApiKey && userId.HasValue && !userId.Value.Equals(default) var user = !isApiKey && userId.HasValue && !userId.Value.Equals(default)
? _userManager.GetUserById(userId.Value) ? _userManager.GetUserById(userId.Value)
: null; : null;
// beyond this point, we're either using an api key or we have a valid user // beyond this point, we're either using an api key or we have a valid user
if (!auth.IsApiKey && user is null) if (!isApiKey && user is null)
{ {
return BadRequest("userId is required"); return BadRequest("userId is required");
} }
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
if (includeItemTypes.Length == 1 if (includeItemTypes.Length == 1
@ -288,12 +282,12 @@ namespace Jellyfin.Api.Controllers
includeItemTypes = new[] { BaseItemKind.Playlist }; includeItemTypes = new[] { BaseItemKind.Playlist };
} }
var enabledChannels = auth.IsApiKey var enabledChannels = isApiKey
? Array.Empty<Guid>() ? Array.Empty<Guid>()
: user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels); : user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels);
// api keys are always enabled for all folders // api keys are always enabled for all folders
bool isInEnabledFolder = auth.IsApiKey bool isInEnabledFolder = isApiKey
|| Array.IndexOf(user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders), item.Id) != -1 || Array.IndexOf(user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledFolders), item.Id) != -1
// Assume all folders inside an EnabledChannel are enabled // Assume all folders inside an EnabledChannel are enabled
|| Array.IndexOf(enabledChannels, item.Id) != -1 || Array.IndexOf(enabledChannels, item.Id) != -1
@ -850,7 +844,7 @@ namespace Jellyfin.Api.Controllers
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var parentIdGuid = parentId ?? Guid.Empty; var parentIdGuid = parentId ?? Guid.Empty;
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var ancestorIds = Array.Empty<Guid>(); var ancestorIds = Array.Empty<Guid>();

View file

@ -24,7 +24,6 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Activity; using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
@ -50,7 +49,6 @@ namespace Jellyfin.Api.Controllers
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IDtoService _dtoService; private readonly IDtoService _dtoService;
private readonly IAuthorizationContext _authContext;
private readonly IActivityManager _activityManager; private readonly IActivityManager _activityManager;
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly ILibraryMonitor _libraryMonitor; private readonly ILibraryMonitor _libraryMonitor;
@ -64,7 +62,6 @@ namespace Jellyfin.Api.Controllers
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="activityManager">Instance of the <see cref="IActivityManager"/> interface.</param> /// <param name="activityManager">Instance of the <see cref="IActivityManager"/> interface.</param>
/// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
/// <param name="libraryMonitor">Instance of the <see cref="ILibraryMonitor"/> interface.</param> /// <param name="libraryMonitor">Instance of the <see cref="ILibraryMonitor"/> interface.</param>
@ -75,7 +72,6 @@ namespace Jellyfin.Api.Controllers
ILibraryManager libraryManager, ILibraryManager libraryManager,
IUserManager userManager, IUserManager userManager,
IDtoService dtoService, IDtoService dtoService,
IAuthorizationContext authContext,
IActivityManager activityManager, IActivityManager activityManager,
ILocalizationManager localization, ILocalizationManager localization,
ILibraryMonitor libraryMonitor, ILibraryMonitor libraryMonitor,
@ -86,7 +82,6 @@ namespace Jellyfin.Api.Controllers
_libraryManager = libraryManager; _libraryManager = libraryManager;
_userManager = userManager; _userManager = userManager;
_dtoService = dtoService; _dtoService = dtoService;
_authContext = authContext;
_activityManager = activityManager; _activityManager = activityManager;
_localization = localization; _localization = localization;
_libraryMonitor = libraryMonitor; _libraryMonitor = libraryMonitor;
@ -184,7 +179,7 @@ namespace Jellyfin.Api.Controllers
item = parent; item = parent;
} }
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var items = themeItems var items = themeItems
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
.ToArray(); .ToArray();
@ -250,7 +245,7 @@ namespace Jellyfin.Api.Controllers
item = parent; item = parent;
} }
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var items = themeItems var items = themeItems
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
.ToArray(); .ToArray();
@ -331,11 +326,10 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult> DeleteItem(Guid itemId) public ActionResult DeleteItem(Guid itemId)
{ {
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var user = _userManager.GetUserById(User.GetUserId());
var user = auth.User;
if (!item.CanDelete(user)) if (!item.CanDelete(user))
{ {
@ -361,7 +355,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<ActionResult> DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids) public ActionResult DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids)
{ {
if (ids.Length == 0) if (ids.Length == 0)
{ {
@ -371,8 +365,7 @@ namespace Jellyfin.Api.Controllers
foreach (var i in ids) foreach (var i in ids)
{ {
var item = _libraryManager.GetItemById(i); var item = _libraryManager.GetItemById(i);
var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var user = _userManager.GetUserById(User.GetUserId());
var user = auth.User;
if (!item.CanDelete(user)) if (!item.CanDelete(user))
{ {
@ -453,7 +446,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
BaseItem? parent = item.GetParent(); BaseItem? parent = item.GetParent();
while (parent != null) while (parent != null)
@ -505,7 +498,7 @@ namespace Jellyfin.Api.Controllers
items = items.Where(i => i.IsHidden == val).ToList(); items = items.Where(i => i.IsHidden == val).ToList();
} }
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions); var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions);
return new QueryResult<BaseItemDto>(resultArray); return new QueryResult<BaseItemDto>(resultArray);
} }
@ -622,9 +615,7 @@ namespace Jellyfin.Api.Controllers
return NotFound(); return NotFound();
} }
var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); var user = _userManager.GetUserById(User.GetUserId());
var user = auth.User;
if (user != null) if (user != null)
{ {
@ -643,7 +634,7 @@ namespace Jellyfin.Api.Controllers
if (user != null) if (user != null)
{ {
await LogDownloadAsync(item, user, auth).ConfigureAwait(false); await LogDownloadAsync(item, user).ConfigureAwait(false);
} }
var path = item.Path; var path = item.Path;
@ -704,7 +695,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request); .AddClientFields(User);
var program = item as IHasProgramAttributes; var program = item as IHasProgramAttributes;
bool? isMovie = item is Movie || (program != null && program.IsMovie) || item is Trailer; bool? isMovie = item is Movie || (program != null && program.IsMovie) || item is Trailer;
@ -892,16 +883,16 @@ namespace Jellyfin.Api.Controllers
: item; : item;
} }
private async Task LogDownloadAsync(BaseItem item, User user, AuthorizationInfo auth) private async Task LogDownloadAsync(BaseItem item, User user)
{ {
try try
{ {
await _activityManager.CreateAsync(new ActivityLog( await _activityManager.CreateAsync(new ActivityLog(
string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name), string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name),
"UserDownloadingContent", "UserDownloadingContent",
auth.UserId) User.GetUserId())
{ {
ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device), ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), User.GetClient(), User.GetDevice()),
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
catch catch

View file

@ -17,6 +17,7 @@ using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.LiveTvDtos; using Jellyfin.Api.Models.LiveTvDtos;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
@ -24,6 +25,7 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.LiveTv;
@ -45,10 +47,10 @@ namespace Jellyfin.Api.Controllers
private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpClientFactory _httpClientFactory;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IDtoService _dtoService; private readonly IDtoService _dtoService;
private readonly ISessionContext _sessionContext;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IConfigurationManager _configurationManager; private readonly IConfigurationManager _configurationManager;
private readonly TranscodingJobHelper _transcodingJobHelper; private readonly TranscodingJobHelper _transcodingJobHelper;
private readonly ISessionManager _sessionManager;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LiveTvController"/> class. /// Initializes a new instance of the <see cref="LiveTvController"/> class.
@ -58,30 +60,30 @@ namespace Jellyfin.Api.Controllers
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param> /// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
/// <param name="sessionContext">Instance of the <see cref="ISessionContext"/> interface.</param>
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param> /// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param>
/// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> class.</param> /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> class.</param>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
public LiveTvController( public LiveTvController(
ILiveTvManager liveTvManager, ILiveTvManager liveTvManager,
IUserManager userManager, IUserManager userManager,
IHttpClientFactory httpClientFactory, IHttpClientFactory httpClientFactory,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IDtoService dtoService, IDtoService dtoService,
ISessionContext sessionContext,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
IConfigurationManager configurationManager, IConfigurationManager configurationManager,
TranscodingJobHelper transcodingJobHelper) TranscodingJobHelper transcodingJobHelper,
ISessionManager sessionManager)
{ {
_liveTvManager = liveTvManager; _liveTvManager = liveTvManager;
_userManager = userManager; _userManager = userManager;
_httpClientFactory = httpClientFactory; _httpClientFactory = httpClientFactory;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_dtoService = dtoService; _dtoService = dtoService;
_sessionContext = sessionContext;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_configurationManager = configurationManager; _configurationManager = configurationManager;
_transcodingJobHelper = transcodingJobHelper; _transcodingJobHelper = transcodingJobHelper;
_sessionManager = sessionManager;
} }
/// <summary> /// <summary>
@ -154,7 +156,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool addCurrentProgram = true) [FromQuery] bool addCurrentProgram = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var channelResult = _liveTvManager.GetInternalChannels( var channelResult = _liveTvManager.GetInternalChannels(
@ -219,7 +221,7 @@ namespace Jellyfin.Api.Controllers
: _libraryManager.GetItemById(channelId); : _libraryManager.GetItemById(channelId);
var dtoOptions = new DtoOptions() var dtoOptions = new DtoOptions()
.AddClientFields(Request); .AddClientFields(User);
return _dtoService.GetBaseItemDto(item, dtoOptions, user); return _dtoService.GetBaseItemDto(item, dtoOptions, user);
} }
@ -272,7 +274,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true) [FromQuery] bool enableTotalRecordCount = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
return _liveTvManager.GetRecordings( return _liveTvManager.GetRecordings(
@ -410,7 +412,7 @@ namespace Jellyfin.Api.Controllers
var item = recordingId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId); var item = recordingId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId);
var dtoOptions = new DtoOptions() var dtoOptions = new DtoOptions()
.AddClientFields(Request); .AddClientFields(User);
return _dtoService.GetBaseItemDto(item, dtoOptions, user); return _dtoService.GetBaseItemDto(item, dtoOptions, user);
} }
@ -599,7 +601,7 @@ namespace Jellyfin.Api.Controllers
} }
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
} }
@ -653,7 +655,7 @@ namespace Jellyfin.Api.Controllers
} }
var dtoOptions = new DtoOptions { Fields = body.Fields } var dtoOptions = new DtoOptions { Fields = body.Fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes); .AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes);
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
} }
@ -719,7 +721,7 @@ namespace Jellyfin.Api.Controllers
}; };
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
} }
@ -1210,9 +1212,16 @@ namespace Jellyfin.Api.Controllers
private async Task AssertUserCanManageLiveTv() private async Task AssertUserCanManageLiveTv()
{ {
var user = await _sessionContext.GetUser(Request).ConfigureAwait(false); var user = _userManager.GetUserById(User.GetUserId());
var session = await _sessionManager.LogSessionActivity(
User.GetClient(),
User.GetVersion(),
User.GetDeviceId(),
User.GetDevice(),
HttpContext.GetNormalizedRemoteIp().ToString(),
user).ConfigureAwait(false);
if (user == null) if (session.UserId.Equals(default))
{ {
throw new SecurityException("Anonymous live tv management is not allowed."); throw new SecurityException("Anonymous live tv management is not allowed.");
} }

View file

@ -6,12 +6,12 @@ using System.Net.Mime;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.MediaInfoDtos; using Jellyfin.Api.Models.MediaInfoDtos;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -31,7 +31,6 @@ namespace Jellyfin.Api.Controllers
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IDeviceManager _deviceManager; private readonly IDeviceManager _deviceManager;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IAuthorizationContext _authContext;
private readonly ILogger<MediaInfoController> _logger; private readonly ILogger<MediaInfoController> _logger;
private readonly MediaInfoHelper _mediaInfoHelper; private readonly MediaInfoHelper _mediaInfoHelper;
@ -41,21 +40,18 @@ namespace Jellyfin.Api.Controllers
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{MediaInfoController}"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{MediaInfoController}"/> interface.</param>
/// <param name="mediaInfoHelper">Instance of the <see cref="MediaInfoHelper"/>.</param> /// <param name="mediaInfoHelper">Instance of the <see cref="MediaInfoHelper"/>.</param>
public MediaInfoController( public MediaInfoController(
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
IDeviceManager deviceManager, IDeviceManager deviceManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IAuthorizationContext authContext,
ILogger<MediaInfoController> logger, ILogger<MediaInfoController> logger,
MediaInfoHelper mediaInfoHelper) MediaInfoHelper mediaInfoHelper)
{ {
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_deviceManager = deviceManager; _deviceManager = deviceManager;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_authContext = authContext;
_logger = logger; _logger = logger;
_mediaInfoHelper = mediaInfoHelper; _mediaInfoHelper = mediaInfoHelper;
} }
@ -122,14 +118,12 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ParameterObsolete] bool? allowAudioStreamCopy, [FromQuery, ParameterObsolete] bool? allowAudioStreamCopy,
[FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] PlaybackInfoDto? playbackInfoDto) [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] PlaybackInfoDto? playbackInfoDto)
{ {
var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false);
var profile = playbackInfoDto?.DeviceProfile; var profile = playbackInfoDto?.DeviceProfile;
_logger.LogDebug("GetPostedPlaybackInfo profile: {@Profile}", profile); _logger.LogDebug("GetPostedPlaybackInfo profile: {@Profile}", profile);
if (profile == null) if (profile == null)
{ {
var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); var caps = _deviceManager.GetCapabilities(User.GetDeviceId());
if (caps != null) if (caps != null)
{ {
profile = caps.DeviceProfile; profile = caps.DeviceProfile;
@ -176,7 +170,7 @@ namespace Jellyfin.Api.Controllers
item, item,
mediaSource, mediaSource,
profile, profile,
authInfo, User,
maxStreamingBitrate ?? profile.MaxStreamingBitrate, maxStreamingBitrate ?? profile.MaxStreamingBitrate,
startTimeTicks ?? 0, startTimeTicks ?? 0,
mediaSourceId ?? string.Empty, mediaSourceId ?? string.Empty,
@ -203,7 +197,7 @@ namespace Jellyfin.Api.Controllers
if (mediaSource != null && mediaSource.RequiresOpening && string.IsNullOrWhiteSpace(mediaSource.LiveStreamId)) if (mediaSource != null && mediaSource.RequiresOpening && string.IsNullOrWhiteSpace(mediaSource.LiveStreamId))
{ {
var openStreamResult = await _mediaInfoHelper.OpenMediaSource( var openStreamResult = await _mediaInfoHelper.OpenMediaSource(
Request, HttpContext,
new LiveStreamRequest new LiveStreamRequest
{ {
AudioStreamIndex = audioStreamIndex, AudioStreamIndex = audioStreamIndex,
@ -276,7 +270,7 @@ namespace Jellyfin.Api.Controllers
EnableDirectStream = enableDirectStream ?? openLiveStreamDto?.EnableDirectStream ?? true, EnableDirectStream = enableDirectStream ?? openLiveStreamDto?.EnableDirectStream ?? true,
DirectPlayProtocols = openLiveStreamDto?.DirectPlayProtocols ?? new[] { MediaProtocol.Http } DirectPlayProtocols = openLiveStreamDto?.DirectPlayProtocols ?? new[] { MediaProtocol.Http }
}; };
return await _mediaInfoHelper.OpenMediaSource(Request, request).ConfigureAwait(false); return await _mediaInfoHelper.OpenMediaSource(HttpContext, request).ConfigureAwait(false);
} }
/// <summary> /// <summary>

View file

@ -72,7 +72,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId.Value); : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request); .AddClientFields(User);
var categories = new List<RecommendationDto>(); var categories = new List<RecommendationDto>();

View file

@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true) [FromQuery] bool enableTotalRecordCount = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
User? user = userId is null || userId.Value.Equals(default) User? user = userId is null || userId.Value.Equals(default)
@ -145,7 +145,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<BaseItemDto> GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) public ActionResult<BaseItemDto> GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId)
{ {
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
MusicGenre? item; MusicGenre? item;

View file

@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true) [FromQuery] bool? enableImages = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
User? user = userId is null || userId.Value.Equals(default) User? user = userId is null || userId.Value.Equals(default)
@ -119,7 +119,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<BaseItemDto> GetPerson([FromRoute, Required] string name, [FromQuery] Guid? userId) public ActionResult<BaseItemDto> GetPerson([FromRoute, Required] string name, [FromQuery] Guid? userId)
{ {
var dtoOptions = new DtoOptions() var dtoOptions = new DtoOptions()
.AddClientFields(Request); .AddClientFields(User);
var item = _libraryManager.GetPerson(name); var item = _libraryManager.GetPerson(name);
if (item == null) if (item == null)

View file

@ -200,7 +200,7 @@ namespace Jellyfin.Api.Controllers
} }
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user); var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);

View file

@ -3,11 +3,11 @@ using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
@ -29,7 +29,6 @@ namespace Jellyfin.Api.Controllers
private readonly IUserDataManager _userDataRepository; private readonly IUserDataManager _userDataRepository;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
private readonly IAuthorizationContext _authContext;
private readonly ILogger<PlaystateController> _logger; private readonly ILogger<PlaystateController> _logger;
private readonly TranscodingJobHelper _transcodingJobHelper; private readonly TranscodingJobHelper _transcodingJobHelper;
@ -40,7 +39,6 @@ namespace Jellyfin.Api.Controllers
/// <param name="userDataRepository">Instance of the <see cref="IUserDataManager"/> interface.</param> /// <param name="userDataRepository">Instance of the <see cref="IUserDataManager"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
/// <param name="transcodingJobHelper">Th <see cref="TranscodingJobHelper"/> singleton.</param> /// <param name="transcodingJobHelper">Th <see cref="TranscodingJobHelper"/> singleton.</param>
public PlaystateController( public PlaystateController(
@ -48,7 +46,6 @@ namespace Jellyfin.Api.Controllers
IUserDataManager userDataRepository, IUserDataManager userDataRepository,
ILibraryManager libraryManager, ILibraryManager libraryManager,
ISessionManager sessionManager, ISessionManager sessionManager,
IAuthorizationContext authContext,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
TranscodingJobHelper transcodingJobHelper) TranscodingJobHelper transcodingJobHelper)
{ {
@ -56,7 +53,6 @@ namespace Jellyfin.Api.Controllers
_userDataRepository = userDataRepository; _userDataRepository = userDataRepository;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_sessionManager = sessionManager; _sessionManager = sessionManager;
_authContext = authContext;
_logger = loggerFactory.CreateLogger<PlaystateController>(); _logger = loggerFactory.CreateLogger<PlaystateController>();
_transcodingJobHelper = transcodingJobHelper; _transcodingJobHelper = transcodingJobHelper;
@ -78,7 +74,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed) [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed)
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var dto = UpdatePlayedStatus(user, itemId, true, datePlayed); var dto = UpdatePlayedStatus(user, itemId, true, datePlayed);
foreach (var additionalUserInfo in session.AdditionalUsers) foreach (var additionalUserInfo in session.AdditionalUsers)
{ {
@ -101,7 +97,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var dto = UpdatePlayedStatus(user, itemId, false, null); var dto = UpdatePlayedStatus(user, itemId, false, null);
foreach (var additionalUserInfo in session.AdditionalUsers) foreach (var additionalUserInfo in session.AdditionalUsers)
{ {
@ -123,7 +119,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> ReportPlaybackStart([FromBody] PlaybackStartInfo playbackStartInfo) public async Task<ActionResult> ReportPlaybackStart([FromBody] PlaybackStartInfo playbackStartInfo)
{ {
playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId);
playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -139,7 +135,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> ReportPlaybackProgress([FromBody] PlaybackProgressInfo playbackProgressInfo) public async Task<ActionResult> ReportPlaybackProgress([FromBody] PlaybackProgressInfo playbackProgressInfo)
{ {
playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId);
playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -171,11 +167,10 @@ namespace Jellyfin.Api.Controllers
_logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty);
if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId))
{ {
var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false);
await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false);
} }
playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -221,7 +216,7 @@ namespace Jellyfin.Api.Controllers
}; };
playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId);
playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -279,7 +274,7 @@ namespace Jellyfin.Api.Controllers
}; };
playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId);
playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);;
await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -321,11 +316,10 @@ namespace Jellyfin.Api.Controllers
_logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty);
if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId))
{ {
var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false);
await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false);
} }
playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);;
await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }

View file

@ -1,6 +1,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Authentication;
@ -104,15 +105,15 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<ActionResult<bool>> AuthorizeQuickConnect([FromQuery, Required] string code) public async Task<ActionResult<bool>> AuthorizeQuickConnect([FromQuery, Required] string code)
{ {
var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); var userId = User.GetUserId();
if (!userId.HasValue) if (userId.Equals(default))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "Unknown user id"); return StatusCode(StatusCodes.Status403Forbidden, "Unknown user id");
} }
try try
{ {
return await _quickConnect.AuthorizeRequest(userId.Value, code).ConfigureAwait(false); return await _quickConnect.AuthorizeRequest(userId, code).ConfigureAwait(false);
} }
catch (AuthenticationException) catch (AuthenticationException)
{ {

View file

@ -5,13 +5,13 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.SessionDtos; using Jellyfin.Api.Models.SessionDtos;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
@ -29,7 +29,6 @@ namespace Jellyfin.Api.Controllers
{ {
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IAuthorizationContext _authContext;
private readonly IDeviceManager _deviceManager; private readonly IDeviceManager _deviceManager;
/// <summary> /// <summary>
@ -37,17 +36,14 @@ namespace Jellyfin.Api.Controllers
/// </summary> /// </summary>
/// <param name="sessionManager">Instance of <see cref="ISessionManager"/> interface.</param> /// <param name="sessionManager">Instance of <see cref="ISessionManager"/> interface.</param>
/// <param name="userManager">Instance of <see cref="IUserManager"/> interface.</param> /// <param name="userManager">Instance of <see cref="IUserManager"/> interface.</param>
/// <param name="authContext">Instance of <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="deviceManager">Instance of <see cref="IDeviceManager"/> interface.</param> /// <param name="deviceManager">Instance of <see cref="IDeviceManager"/> interface.</param>
public SessionController( public SessionController(
ISessionManager sessionManager, ISessionManager sessionManager,
IUserManager userManager, IUserManager userManager,
IAuthorizationContext authContext,
IDeviceManager deviceManager) IDeviceManager deviceManager)
{ {
_sessionManager = sessionManager; _sessionManager = sessionManager;
_userManager = userManager; _userManager = userManager;
_authContext = authContext;
_deviceManager = deviceManager; _deviceManager = deviceManager;
} }
@ -139,7 +135,7 @@ namespace Jellyfin.Api.Controllers
}; };
await _sessionManager.SendBrowseCommand( await _sessionManager.SendBrowseCommand(
await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false),
sessionId, sessionId,
command, command,
CancellationToken.None) CancellationToken.None)
@ -186,7 +182,7 @@ namespace Jellyfin.Api.Controllers
}; };
await _sessionManager.SendPlayCommand( await _sessionManager.SendPlayCommand(
await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false),
sessionId, sessionId,
playRequest, playRequest,
CancellationToken.None) CancellationToken.None)
@ -214,7 +210,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? controllingUserId) [FromQuery] string? controllingUserId)
{ {
await _sessionManager.SendPlaystateCommand( await _sessionManager.SendPlaystateCommand(
await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false),
sessionId, sessionId,
new PlaystateRequest() new PlaystateRequest()
{ {
@ -242,14 +238,14 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] GeneralCommandType command) [FromRoute, Required] GeneralCommandType command)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var generalCommand = new GeneralCommand var generalCommand = new GeneralCommand
{ {
Name = command, Name = command,
ControllingUserId = currentSession.UserId ControllingUserId = currentSession.UserId
}; };
await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None); await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -268,7 +264,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] GeneralCommandType command) [FromRoute, Required] GeneralCommandType command)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var generalCommand = new GeneralCommand var generalCommand = new GeneralCommand
{ {
@ -296,8 +292,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromBody, Required] GeneralCommand command) [FromBody, Required] GeneralCommand command)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request) var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
.ConfigureAwait(false);
if (command == null) if (command == null)
{ {
@ -336,7 +331,7 @@ namespace Jellyfin.Api.Controllers
} }
await _sessionManager.SendMessageCommand( await _sessionManager.SendMessageCommand(
await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false),
sessionId, sessionId,
command, command,
CancellationToken.None) CancellationToken.None)
@ -405,7 +400,7 @@ namespace Jellyfin.Api.Controllers
{ {
if (string.IsNullOrWhiteSpace(id)) if (string.IsNullOrWhiteSpace(id))
{ {
id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); id = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
} }
_sessionManager.ReportCapabilities(id, new ClientCapabilities _sessionManager.ReportCapabilities(id, new ClientCapabilities
@ -435,7 +430,7 @@ namespace Jellyfin.Api.Controllers
{ {
if (string.IsNullOrWhiteSpace(id)) if (string.IsNullOrWhiteSpace(id))
{ {
id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); id = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
} }
_sessionManager.ReportCapabilities(id, capabilities.ToClientCapabilities()); _sessionManager.ReportCapabilities(id, capabilities.ToClientCapabilities());
@ -457,7 +452,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? sessionId, [FromQuery] string? sessionId,
[FromQuery, Required] string? itemId) [FromQuery, Required] string? itemId)
{ {
string session = sessionId ?? await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); string session = sessionId ?? await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
_sessionManager.ReportNowViewingItem(session, itemId); _sessionManager.ReportNowViewingItem(session, itemId);
return NoContent(); return NoContent();
@ -473,9 +468,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> ReportSessionEnded() public async Task<ActionResult> ReportSessionEnded()
{ {
AuthorizationInfo auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); await _sessionManager.Logout(User.GetToken()).ConfigureAwait(false);
await _sessionManager.Logout(auth.Token).ConfigureAwait(false);
return NoContent(); return NoContent();
} }

View file

@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true) [FromQuery] bool enableTotalRecordCount = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
User? user = userId is null || userId.Value.Equals(default) User? user = userId is null || userId.Value.Equals(default)
@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<BaseItemDto> GetStudio([FromRoute, Required] string name, [FromQuery] Guid? userId) public ActionResult<BaseItemDto> GetStudio([FromRoute, Required] string name, [FromQuery] Guid? userId)
{ {
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var item = _libraryManager.GetStudio(name); var item = _libraryManager.GetStudio(name);
if (userId.HasValue && !userId.Equals(default)) if (userId.HasValue && !userId.Equals(default))

View file

@ -11,13 +11,13 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Models.SubtitleDtos; using Jellyfin.Api.Models.SubtitleDtos;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles; using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -45,7 +45,6 @@ namespace Jellyfin.Api.Controllers
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IProviderManager _providerManager; private readonly IProviderManager _providerManager;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IAuthorizationContext _authContext;
private readonly ILogger<SubtitleController> _logger; private readonly ILogger<SubtitleController> _logger;
/// <summary> /// <summary>
@ -58,7 +57,6 @@ namespace Jellyfin.Api.Controllers
/// <param name="mediaSourceManager">Instance of <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="providerManager">Instance of <see cref="IProviderManager"/> interface.</param> /// <param name="providerManager">Instance of <see cref="IProviderManager"/> interface.</param>
/// <param name="fileSystem">Instance of <see cref="IFileSystem"/> interface.</param> /// <param name="fileSystem">Instance of <see cref="IFileSystem"/> interface.</param>
/// <param name="authContext">Instance of <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="logger">Instance of <see cref="ILogger{SubtitleController}"/> interface.</param> /// <param name="logger">Instance of <see cref="ILogger{SubtitleController}"/> interface.</param>
public SubtitleController( public SubtitleController(
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
@ -68,7 +66,6 @@ namespace Jellyfin.Api.Controllers
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
IProviderManager providerManager, IProviderManager providerManager,
IFileSystem fileSystem, IFileSystem fileSystem,
IAuthorizationContext authContext,
ILogger<SubtitleController> logger) ILogger<SubtitleController> logger)
{ {
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
@ -78,7 +75,6 @@ namespace Jellyfin.Api.Controllers
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_providerManager = providerManager; _providerManager = providerManager;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_authContext = authContext;
_logger = logger; _logger = logger;
} }
@ -361,7 +357,7 @@ namespace Jellyfin.Api.Controllers
long positionTicks = 0; long positionTicks = 0;
var accessToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; var accessToken = User.GetToken();
while (positionTicks < runtime) while (positionTicks < runtime)
{ {

View file

@ -67,7 +67,7 @@ namespace Jellyfin.Api.Controllers
? null ? null
: _userManager.GetUserById(userId); : _userManager.GetUserById(userId);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user) var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{ {
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) }, OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) },

View file

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.SyncPlayDtos; using Jellyfin.Api.Models.SyncPlayDtos;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.SyncPlay; using MediaBrowser.Controller.SyncPlay;
using MediaBrowser.Controller.SyncPlay.PlaybackRequests; using MediaBrowser.Controller.SyncPlay.PlaybackRequests;
@ -24,23 +24,23 @@ namespace Jellyfin.Api.Controllers
public class SyncPlayController : BaseJellyfinApiController public class SyncPlayController : BaseJellyfinApiController
{ {
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
private readonly IAuthorizationContext _authorizationContext;
private readonly ISyncPlayManager _syncPlayManager; private readonly ISyncPlayManager _syncPlayManager;
private readonly IUserManager _userManager;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SyncPlayController"/> class. /// Initializes a new instance of the <see cref="SyncPlayController"/> class.
/// </summary> /// </summary>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
/// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="syncPlayManager">Instance of the <see cref="ISyncPlayManager"/> interface.</param> /// <param name="syncPlayManager">Instance of the <see cref="ISyncPlayManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
public SyncPlayController( public SyncPlayController(
ISessionManager sessionManager, ISessionManager sessionManager,
IAuthorizationContext authorizationContext, ISyncPlayManager syncPlayManager,
ISyncPlayManager syncPlayManager) IUserManager userManager)
{ {
_sessionManager = sessionManager; _sessionManager = sessionManager;
_authorizationContext = authorizationContext;
_syncPlayManager = syncPlayManager; _syncPlayManager = syncPlayManager;
_userManager = userManager;
} }
/// <summary> /// <summary>
@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayCreateGroup( public async Task<ActionResult> SyncPlayCreateGroup(
[FromBody, Required] NewGroupRequestDto requestData) [FromBody, Required] NewGroupRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new NewGroupRequest(requestData.GroupName); var syncPlayRequest = new NewGroupRequest(requestData.GroupName);
_syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayJoinGroup( public async Task<ActionResult> SyncPlayJoinGroup(
[FromBody, Required] JoinGroupRequestDto requestData) [FromBody, Required] JoinGroupRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new JoinGroupRequest(requestData.GroupId); var syncPlayRequest = new JoinGroupRequest(requestData.GroupId);
_syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public async Task<ActionResult> SyncPlayLeaveGroup() public async Task<ActionResult> SyncPlayLeaveGroup()
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new LeaveGroupRequest(); var syncPlayRequest = new LeaveGroupRequest();
_syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -105,7 +105,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayJoinGroup)] [Authorize(Policy = Policies.SyncPlayJoinGroup)]
public async Task<ActionResult<IEnumerable<GroupInfoDto>>> SyncPlayGetGroups() public async Task<ActionResult<IEnumerable<GroupInfoDto>>> SyncPlayGetGroups()
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new ListGroupsRequest(); var syncPlayRequest = new ListGroupsRequest();
return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest)); return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest));
} }
@ -122,7 +122,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetNewQueue( public async Task<ActionResult> SyncPlaySetNewQueue(
[FromBody, Required] PlayRequestDto requestData) [FromBody, Required] PlayRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new PlayGroupRequest( var syncPlayRequest = new PlayGroupRequest(
requestData.PlayingQueue, requestData.PlayingQueue,
requestData.PlayingItemPosition, requestData.PlayingItemPosition,
@ -143,7 +143,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetPlaylistItem( public async Task<ActionResult> SyncPlaySetPlaylistItem(
[FromBody, Required] SetPlaylistItemRequestDto requestData) [FromBody, Required] SetPlaylistItemRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new SetPlaylistItemGroupRequest(requestData.PlaylistItemId); var syncPlayRequest = new SetPlaylistItemGroupRequest(requestData.PlaylistItemId);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayRemoveFromPlaylist( public async Task<ActionResult> SyncPlayRemoveFromPlaylist(
[FromBody, Required] RemoveFromPlaylistRequestDto requestData) [FromBody, Required] RemoveFromPlaylistRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new RemoveFromPlaylistGroupRequest(requestData.PlaylistItemIds, requestData.ClearPlaylist, requestData.ClearPlayingItem); var syncPlayRequest = new RemoveFromPlaylistGroupRequest(requestData.PlaylistItemIds, requestData.ClearPlaylist, requestData.ClearPlayingItem);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayMovePlaylistItem( public async Task<ActionResult> SyncPlayMovePlaylistItem(
[FromBody, Required] MovePlaylistItemRequestDto requestData) [FromBody, Required] MovePlaylistItemRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new MovePlaylistItemGroupRequest(requestData.PlaylistItemId, requestData.NewIndex); var syncPlayRequest = new MovePlaylistItemGroupRequest(requestData.PlaylistItemId, requestData.NewIndex);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -197,7 +197,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayQueue( public async Task<ActionResult> SyncPlayQueue(
[FromBody, Required] QueueRequestDto requestData) [FromBody, Required] QueueRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new QueueGroupRequest(requestData.ItemIds, requestData.Mode); var syncPlayRequest = new QueueGroupRequest(requestData.ItemIds, requestData.Mode);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -213,7 +213,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public async Task<ActionResult> SyncPlayUnpause() public async Task<ActionResult> SyncPlayUnpause()
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new UnpauseGroupRequest(); var syncPlayRequest = new UnpauseGroupRequest();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -229,7 +229,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public async Task<ActionResult> SyncPlayPause() public async Task<ActionResult> SyncPlayPause()
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new PauseGroupRequest(); var syncPlayRequest = new PauseGroupRequest();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -245,7 +245,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public async Task<ActionResult> SyncPlayStop() public async Task<ActionResult> SyncPlayStop()
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new StopGroupRequest(); var syncPlayRequest = new StopGroupRequest();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -263,7 +263,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySeek( public async Task<ActionResult> SyncPlaySeek(
[FromBody, Required] SeekRequestDto requestData) [FromBody, Required] SeekRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new SeekGroupRequest(requestData.PositionTicks); var syncPlayRequest = new SeekGroupRequest(requestData.PositionTicks);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -281,7 +281,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayBuffering( public async Task<ActionResult> SyncPlayBuffering(
[FromBody, Required] BufferRequestDto requestData) [FromBody, Required] BufferRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new BufferGroupRequest( var syncPlayRequest = new BufferGroupRequest(
requestData.When, requestData.When,
requestData.PositionTicks, requestData.PositionTicks,
@ -303,7 +303,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayReady( public async Task<ActionResult> SyncPlayReady(
[FromBody, Required] ReadyRequestDto requestData) [FromBody, Required] ReadyRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new ReadyGroupRequest( var syncPlayRequest = new ReadyGroupRequest(
requestData.When, requestData.When,
requestData.PositionTicks, requestData.PositionTicks,
@ -325,7 +325,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetIgnoreWait( public async Task<ActionResult> SyncPlaySetIgnoreWait(
[FromBody, Required] IgnoreWaitRequestDto requestData) [FromBody, Required] IgnoreWaitRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new IgnoreWaitGroupRequest(requestData.IgnoreWait); var syncPlayRequest = new IgnoreWaitGroupRequest(requestData.IgnoreWait);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -343,7 +343,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayNextItem( public async Task<ActionResult> SyncPlayNextItem(
[FromBody, Required] NextItemRequestDto requestData) [FromBody, Required] NextItemRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new NextItemGroupRequest(requestData.PlaylistItemId); var syncPlayRequest = new NextItemGroupRequest(requestData.PlaylistItemId);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -361,7 +361,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayPreviousItem( public async Task<ActionResult> SyncPlayPreviousItem(
[FromBody, Required] PreviousItemRequestDto requestData) [FromBody, Required] PreviousItemRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new PreviousItemGroupRequest(requestData.PlaylistItemId); var syncPlayRequest = new PreviousItemGroupRequest(requestData.PlaylistItemId);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -379,7 +379,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetRepeatMode( public async Task<ActionResult> SyncPlaySetRepeatMode(
[FromBody, Required] SetRepeatModeRequestDto requestData) [FromBody, Required] SetRepeatModeRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new SetRepeatModeGroupRequest(requestData.Mode); var syncPlayRequest = new SetRepeatModeGroupRequest(requestData.Mode);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -397,7 +397,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetShuffleMode( public async Task<ActionResult> SyncPlaySetShuffleMode(
[FromBody, Required] SetShuffleModeRequestDto requestData) [FromBody, Required] SetShuffleModeRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new SetShuffleModeGroupRequest(requestData.Mode); var syncPlayRequest = new SetShuffleModeGroupRequest(requestData.Mode);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -414,7 +414,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayPing( public async Task<ActionResult> SyncPlayPing(
[FromBody, Required] PingRequestDto requestData) [FromBody, Required] PingRequestDto requestData)
{ {
var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new PingGroupRequest(requestData.Ping); var syncPlayRequest = new PingGroupRequest(requestData.Ping);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();

View file

@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableRewatching = false) [FromQuery] bool enableRewatching = false)
{ {
var options = new DtoOptions { Fields = fields } var options = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var result = _tvSeriesManager.GetNextUp( var result = _tvSeriesManager.GetNextUp(
@ -154,7 +154,7 @@ namespace Jellyfin.Api.Controllers
var parentIdGuid = parentId ?? Guid.Empty; var parentIdGuid = parentId ?? Guid.Empty;
var options = new DtoOptions { Fields = fields } var options = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers
List<BaseItem> episodes; List<BaseItem> episodes;
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
if (seasonId.HasValue) // Season id was supplied. Get episodes by season id. if (seasonId.HasValue) // Season id was supplied. Get episodes by season id.
@ -349,7 +349,7 @@ namespace Jellyfin.Api.Controllers
}); });
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user); var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user);

View file

@ -6,13 +6,13 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@ -28,7 +28,6 @@ namespace Jellyfin.Api.Controllers
[Route("")] [Route("")]
public class UniversalAudioController : BaseJellyfinApiController public class UniversalAudioController : BaseJellyfinApiController
{ {
private readonly IAuthorizationContext _authorizationContext;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILogger<UniversalAudioController> _logger; private readonly ILogger<UniversalAudioController> _logger;
private readonly MediaInfoHelper _mediaInfoHelper; private readonly MediaInfoHelper _mediaInfoHelper;
@ -38,21 +37,18 @@ namespace Jellyfin.Api.Controllers
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UniversalAudioController"/> class. /// Initializes a new instance of the <see cref="UniversalAudioController"/> class.
/// </summary> /// </summary>
/// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{UniversalAudioController}"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{UniversalAudioController}"/> interface.</param>
/// <param name="mediaInfoHelper">Instance of <see cref="MediaInfoHelper"/>.</param> /// <param name="mediaInfoHelper">Instance of <see cref="MediaInfoHelper"/>.</param>
/// <param name="audioHelper">Instance of <see cref="AudioHelper"/>.</param> /// <param name="audioHelper">Instance of <see cref="AudioHelper"/>.</param>
/// <param name="dynamicHlsHelper">Instance of <see cref="DynamicHlsHelper"/>.</param> /// <param name="dynamicHlsHelper">Instance of <see cref="DynamicHlsHelper"/>.</param>
public UniversalAudioController( public UniversalAudioController(
IAuthorizationContext authorizationContext,
ILibraryManager libraryManager, ILibraryManager libraryManager,
ILogger<UniversalAudioController> logger, ILogger<UniversalAudioController> logger,
MediaInfoHelper mediaInfoHelper, MediaInfoHelper mediaInfoHelper,
AudioHelper audioHelper, AudioHelper audioHelper,
DynamicHlsHelper dynamicHlsHelper) DynamicHlsHelper dynamicHlsHelper)
{ {
_authorizationContext = authorizationContext;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = logger; _logger = logger;
_mediaInfoHelper = mediaInfoHelper; _mediaInfoHelper = mediaInfoHelper;
@ -111,16 +107,12 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableRedirection = true) [FromQuery] bool enableRedirection = true)
{ {
var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels);
var authorizationInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false);
authorizationInfo.DeviceId = deviceId;
if (!userId.HasValue || userId.Value.Equals(Guid.Empty)) if (!userId.HasValue || userId.Value.Equals(Guid.Empty))
{ {
userId = authorizationInfo.UserId; userId = User.GetUserId();
} }
var authInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false);
_logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", deviceProfile); _logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", deviceProfile);
var info = await _mediaInfoHelper.GetPlaybackInfo( var info = await _mediaInfoHelper.GetPlaybackInfo(
@ -138,7 +130,7 @@ namespace Jellyfin.Api.Controllers
item, item,
sourceInfo, sourceInfo,
deviceProfile, deviceProfile,
authInfo, User,
maxStreamingBitrate ?? deviceProfile.MaxStreamingBitrate, maxStreamingBitrate ?? deviceProfile.MaxStreamingBitrate,
startTimeTicks ?? 0, startTimeTicks ?? 0,
mediaSourceId ?? string.Empty, mediaSourceId ?? string.Empty,

View file

@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.UserDtos; using Jellyfin.Api.Models.UserDtos;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
@ -264,7 +265,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromBody, Required] UpdateUserPassword request) [FromBody, Required] UpdateUserPassword request)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the password."); return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the password.");
} }
@ -282,7 +283,7 @@ namespace Jellyfin.Api.Controllers
} }
else else
{ {
if (!HttpContext.User.IsInRole(UserRoles.Administrator)) if (!User.IsInRole(UserRoles.Administrator))
{ {
var success = await _userManager.AuthenticateUser( var success = await _userManager.AuthenticateUser(
user.Username, user.Username,
@ -299,7 +300,7 @@ namespace Jellyfin.Api.Controllers
await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false); await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false);
var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; var currentToken = User.GetToken();
await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false);
} }
@ -325,7 +326,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromBody, Required] UpdateUserEasyPassword request) [FromBody, Required] UpdateUserEasyPassword request)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the easy password."); return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the easy password.");
} }
@ -367,7 +368,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromBody, Required] UserDto updateUser) [FromBody, Required] UserDto updateUser)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User update not allowed."); return StatusCode(StatusCodes.Status403Forbidden, "User update not allowed.");
} }
@ -427,7 +428,7 @@ namespace Jellyfin.Api.Controllers
return StatusCode(StatusCodes.Status403Forbidden, "There must be at least one enabled user in the system."); return StatusCode(StatusCodes.Status403Forbidden, "There must be at least one enabled user in the system.");
} }
var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; var currentToken = User.GetToken();
await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false);
} }
@ -452,7 +453,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromBody, Required] UserConfiguration userConfig) [FromBody, Required] UserConfiguration userConfig)
{ {
if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
{ {
return StatusCode(StatusCodes.Status403Forbidden, "User configuration update not allowed"); return StatusCode(StatusCodes.Status403Forbidden, "User configuration update not allowed");
} }
@ -536,13 +537,13 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<UserDto> GetCurrentUser() public ActionResult<UserDto> GetCurrentUser()
{ {
var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); var userId = User.GetUserId();
if (userId is null) if (userId.Equals(default))
{ {
return BadRequest(); return BadRequest();
} }
var user = _userManager.GetUserById(userId.Value); var user = _userManager.GetUserById(userId);
if (user == null) if (user == null)
{ {
return BadRequest(); return BadRequest();
@ -567,7 +568,7 @@ namespace Jellyfin.Api.Controllers
if (filterByDevice) if (filterByDevice)
{ {
var deviceId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId; var deviceId = User.GetDeviceId();
if (!string.IsNullOrWhiteSpace(deviceId)) if (!string.IsNullOrWhiteSpace(deviceId))
{ {

View file

@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers
await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false); await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
return _dtoService.GetBaseItemDto(item, dtoOptions, user); return _dtoService.GetBaseItemDto(item, dtoOptions, user);
} }
@ -98,7 +98,7 @@ namespace Jellyfin.Api.Controllers
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var item = _libraryManager.GetUserRootFolder(); var item = _libraryManager.GetUserRootFolder();
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
return _dtoService.GetBaseItemDto(item, dtoOptions, user); return _dtoService.GetBaseItemDto(item, dtoOptions, user);
} }
@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers
: _libraryManager.GetItemById(itemId); : _libraryManager.GetItemById(itemId);
var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false); var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray(); var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
return new QueryResult<BaseItemDto>(dtos); return new QueryResult<BaseItemDto>(dtos);
@ -200,7 +200,7 @@ namespace Jellyfin.Api.Controllers
? _libraryManager.GetUserRootFolder() ? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId); : _libraryManager.GetItemById(itemId);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
if (item is IHasTrailers hasTrailers) if (item is IHasTrailers hasTrailers)
{ {
@ -230,7 +230,7 @@ namespace Jellyfin.Api.Controllers
? _libraryManager.GetUserRootFolder() ? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId); : _libraryManager.GetItemById(itemId);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
return Ok(item return Ok(item
.GetExtras() .GetExtras()
@ -280,7 +280,7 @@ namespace Jellyfin.Api.Controllers
} }
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var list = _userViewManager.GetLatestItems( var list = _userViewManager.GetLatestItems(

View file

@ -85,7 +85,7 @@ namespace Jellyfin.Api.Controllers
var folders = _userViewManager.GetUserViews(query); var folders = _userViewManager.GetUserViews(query);
var dtoOptions = new DtoOptions().AddClientFields(Request); var dtoOptions = new DtoOptions().AddClientFields(User);
var fields = dtoOptions.Fields.ToList(); var fields = dtoOptions.Fields.ToList();
fields.Add(ItemFields.PrimaryImageAspectRatio); fields.Add(ItemFields.PrimaryImageAspectRatio);

View file

@ -43,7 +43,6 @@ namespace Jellyfin.Api.Controllers
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IDtoService _dtoService; private readonly IDtoService _dtoService;
private readonly IDlnaManager _dlnaManager; private readonly IDlnaManager _dlnaManager;
private readonly IAuthorizationContext _authContext;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
@ -61,7 +60,6 @@ namespace Jellyfin.Api.Controllers
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param> /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
/// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
@ -74,7 +72,6 @@ namespace Jellyfin.Api.Controllers
IUserManager userManager, IUserManager userManager,
IDtoService dtoService, IDtoService dtoService,
IDlnaManager dlnaManager, IDlnaManager dlnaManager,
IAuthorizationContext authContext,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder, IMediaEncoder mediaEncoder,
@ -87,7 +84,6 @@ namespace Jellyfin.Api.Controllers
_userManager = userManager; _userManager = userManager;
_dtoService = dtoService; _dtoService = dtoService;
_dlnaManager = dlnaManager; _dlnaManager = dlnaManager;
_authContext = authContext;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
@ -120,7 +116,7 @@ namespace Jellyfin.Api.Controllers
: _libraryManager.GetItemById(itemId); : _libraryManager.GetItemById(itemId);
var dtoOptions = new DtoOptions(); var dtoOptions = new DtoOptions();
dtoOptions = dtoOptions.AddClientFields(Request); dtoOptions = dtoOptions.AddClientFields(User);
BaseItemDto[] items; BaseItemDto[] items;
if (item is Video video) if (item is Video video)
@ -429,8 +425,7 @@ namespace Jellyfin.Api.Controllers
var state = await StreamingHelpers.GetStreamingState( var state = await StreamingHelpers.GetStreamingState(
streamingRequest, streamingRequest,
Request, HttpContext,
_authContext,
_mediaSourceManager, _mediaSourceManager,
_userManager, _userManager,
_libraryManager, _libraryManager,

View file

@ -87,7 +87,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true) [FromQuery] bool? enableImages = true)
{ {
var dtoOptions = new DtoOptions { Fields = fields } var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request) .AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
User? user = userId is null || userId.Value.Equals(default) User? user = userId is null || userId.Value.Equals(default)
@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers
} }
var dtoOptions = new DtoOptions() var dtoOptions = new DtoOptions()
.AddClientFields(Request); .AddClientFields(User);
if (userId.HasValue && !userId.Value.Equals(default)) if (userId.HasValue && !userId.Value.Equals(default))
{ {

View file

@ -0,0 +1,81 @@
using System;
using System.Linq;
using System.Security.Claims;
using Jellyfin.Api.Constants;
namespace Jellyfin.Api.Extensions;
/// <summary>
/// Extensions for <see cref="ClaimsPrincipal"/>.
/// </summary>
public static class ClaimsPrincipalExtensions
{
/// <summary>
/// Get user id from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>User id.</returns>
public static Guid GetUserId(this ClaimsPrincipal user)
{
var value = GetClaimValue(user, InternalClaimTypes.UserId);
return string.IsNullOrEmpty(value)
? default
: Guid.Parse(value);
}
/// <summary>
/// Get device id from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Device id.</returns>
public static string? GetDeviceId(this ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.DeviceId);
/// <summary>
/// Get device from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Device.</returns>
public static string? GetDevice(this ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Device);
/// <summary>
/// Get client from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Client.</returns>
public static string? GetClient(this ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Client);
/// <summary>
/// Get version from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Version.</returns>
public static string? GetVersion(this ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Version);
/// <summary>
/// Get token from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Token.</returns>
public static string? GetToken(this ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Token);
/// <summary>
/// Gets a flag specifying whether the request is using an api key.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>The flag specifying whether the request is using an api key.</returns>
public static bool GetIsApiKey(this ClaimsPrincipal user)
{
var claimValue = GetClaimValue(user, InternalClaimTypes.IsApiKey);
return !string.IsNullOrEmpty(claimValue)
&& bool.TryParse(claimValue, out var parsedClaimValue)
&& parsedClaimValue;
}
private static string? GetClaimValue(in ClaimsPrincipal user, string name)
=> user.Claims.FirstOrDefault(claim => claim.Type.Equals(name, StringComparison.OrdinalIgnoreCase))?.Value;
}

View file

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Jellyfin.Api.Helpers; using System.Security.Claims;
using Jellyfin.Extensions; using Jellyfin.Extensions;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -22,14 +22,14 @@ namespace Jellyfin.Api.Extensions
/// Legacy order: 2. /// Legacy order: 2.
/// </remarks> /// </remarks>
/// <param name="dtoOptions">DtoOptions object.</param> /// <param name="dtoOptions">DtoOptions object.</param>
/// <param name="request">Current request.</param> /// <param name="user">Current claims principal.</param>
/// <returns>Modified DtoOptions object.</returns> /// <returns>Modified DtoOptions object.</returns>
internal static DtoOptions AddClientFields( internal static DtoOptions AddClientFields(
this DtoOptions dtoOptions, HttpRequest request) this DtoOptions dtoOptions, ClaimsPrincipal user)
{ {
dtoOptions.Fields ??= Array.Empty<ItemFields>(); dtoOptions.Fields ??= Array.Empty<ItemFields>();
string? client = ClaimHelpers.GetClient(request.HttpContext.User); string? client = user.GetClient();
// No client in claim // No client in claim
if (string.IsNullOrEmpty(client)) if (string.IsNullOrEmpty(client))

View file

@ -11,7 +11,6 @@ using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -25,7 +24,6 @@ namespace Jellyfin.Api.Helpers
public class AudioHelper public class AudioHelper
{ {
private readonly IDlnaManager _dlnaManager; private readonly IDlnaManager _dlnaManager;
private readonly IAuthorizationContext _authContext;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
@ -41,7 +39,6 @@ namespace Jellyfin.Api.Helpers
/// Initializes a new instance of the <see cref="AudioHelper"/> class. /// Initializes a new instance of the <see cref="AudioHelper"/> class.
/// </summary> /// </summary>
/// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
@ -54,7 +51,6 @@ namespace Jellyfin.Api.Helpers
/// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
public AudioHelper( public AudioHelper(
IDlnaManager dlnaManager, IDlnaManager dlnaManager,
IAuthorizationContext authContext,
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
@ -67,7 +63,6 @@ namespace Jellyfin.Api.Helpers
EncodingHelper encodingHelper) EncodingHelper encodingHelper)
{ {
_dlnaManager = dlnaManager; _dlnaManager = dlnaManager;
_authContext = authContext;
_userManager = userManager; _userManager = userManager;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
@ -102,8 +97,7 @@ namespace Jellyfin.Api.Helpers
using var state = await StreamingHelpers.GetStreamingState( using var state = await StreamingHelpers.GetStreamingState(
streamingRequest, streamingRequest,
_httpContextAccessor.HttpContext.Request, _httpContextAccessor.HttpContext,
_authContext,
_mediaSourceManager, _mediaSourceManager,
_userManager, _userManager,
_libraryManager, _libraryManager,

View file

@ -1,88 +0,0 @@
using System;
using System.Linq;
using System.Security.Claims;
using Jellyfin.Api.Constants;
namespace Jellyfin.Api.Helpers
{
/// <summary>
/// Claim Helpers.
/// </summary>
public static class ClaimHelpers
{
/// <summary>
/// Get user id from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>User id.</returns>
public static Guid? GetUserId(in ClaimsPrincipal user)
{
var value = GetClaimValue(user, InternalClaimTypes.UserId);
return string.IsNullOrEmpty(value)
? null
: Guid.Parse(value);
}
/// <summary>
/// Get device id from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Device id.</returns>
public static string? GetDeviceId(in ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.DeviceId);
/// <summary>
/// Get device from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Device.</returns>
public static string? GetDevice(in ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Device);
/// <summary>
/// Get client from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Client.</returns>
public static string? GetClient(in ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Client);
/// <summary>
/// Get version from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Version.</returns>
public static string? GetVersion(in ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Version);
/// <summary>
/// Get token from claims.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>Token.</returns>
public static string? GetToken(in ClaimsPrincipal user)
=> GetClaimValue(user, InternalClaimTypes.Token);
/// <summary>
/// Gets a flag specifying whether the request is using an api key.
/// </summary>
/// <param name="user">Current claims principal.</param>
/// <returns>The flag specifying whether the request is using an api key.</returns>
public static bool GetIsApiKey(in ClaimsPrincipal user)
{
var claimValue = GetClaimValue(user, InternalClaimTypes.IsApiKey);
return !string.IsNullOrEmpty(claimValue)
&& bool.TryParse(claimValue, out var parsedClaimValue)
&& parsedClaimValue;
}
private static string? GetClaimValue(in ClaimsPrincipal user, string name)
{
return user?.Identities
.SelectMany(c => c.Claims)
.Where(claim => claim.Type.Equals(name, StringComparison.OrdinalIgnoreCase))
.Select(claim => claim.Value)
.FirstOrDefault();
}
}
}

View file

@ -7,6 +7,7 @@ using System.Security.Claims;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
@ -15,7 +16,6 @@ using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
@ -34,7 +34,6 @@ namespace Jellyfin.Api.Helpers
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IDlnaManager _dlnaManager; private readonly IDlnaManager _dlnaManager;
private readonly IAuthorizationContext _authContext;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
@ -51,7 +50,6 @@ namespace Jellyfin.Api.Helpers
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param> /// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
@ -65,7 +63,6 @@ namespace Jellyfin.Api.Helpers
ILibraryManager libraryManager, ILibraryManager libraryManager,
IUserManager userManager, IUserManager userManager,
IDlnaManager dlnaManager, IDlnaManager dlnaManager,
IAuthorizationContext authContext,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder, IMediaEncoder mediaEncoder,
@ -79,7 +76,6 @@ namespace Jellyfin.Api.Helpers
_libraryManager = libraryManager; _libraryManager = libraryManager;
_userManager = userManager; _userManager = userManager;
_dlnaManager = dlnaManager; _dlnaManager = dlnaManager;
_authContext = authContext;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
@ -128,8 +124,7 @@ namespace Jellyfin.Api.Helpers
using var state = await StreamingHelpers.GetStreamingState( using var state = await StreamingHelpers.GetStreamingState(
streamingRequest, streamingRequest,
_httpContextAccessor.HttpContext.Request, _httpContextAccessor.HttpContext,
_authContext,
_mediaSourceManager, _mediaSourceManager,
_userManager, _userManager,
_libraryManager, _libraryManager,
@ -483,7 +478,7 @@ namespace Jellyfin.Api.Helpers
state.Request.MediaSourceId, state.Request.MediaSourceId,
stream.Index.ToString(CultureInfo.InvariantCulture), stream.Index.ToString(CultureInfo.InvariantCulture),
30.ToString(CultureInfo.InvariantCulture), 30.ToString(CultureInfo.InvariantCulture),
ClaimHelpers.GetToken(user)); user.GetToken());
var line = string.Format( var line = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,

View file

@ -2,9 +2,11 @@
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Security.Claims;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
@ -15,7 +17,6 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -39,7 +40,6 @@ namespace Jellyfin.Api.Helpers
private readonly ILogger<MediaInfoHelper> _logger; private readonly ILogger<MediaInfoHelper> _logger;
private readonly INetworkManager _networkManager; private readonly INetworkManager _networkManager;
private readonly IDeviceManager _deviceManager; private readonly IDeviceManager _deviceManager;
private readonly IAuthorizationContext _authContext;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MediaInfoHelper"/> class. /// Initializes a new instance of the <see cref="MediaInfoHelper"/> class.
@ -52,7 +52,6 @@ namespace Jellyfin.Api.Helpers
/// <param name="logger">Instance of the <see cref="ILogger{MediaInfoHelper}"/> interface.</param> /// <param name="logger">Instance of the <see cref="ILogger{MediaInfoHelper}"/> interface.</param>
/// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param> /// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param> /// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
public MediaInfoHelper( public MediaInfoHelper(
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -61,8 +60,7 @@ namespace Jellyfin.Api.Helpers
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
ILogger<MediaInfoHelper> logger, ILogger<MediaInfoHelper> logger,
INetworkManager networkManager, INetworkManager networkManager,
IDeviceManager deviceManager, IDeviceManager deviceManager)
IAuthorizationContext authContext)
{ {
_userManager = userManager; _userManager = userManager;
_libraryManager = libraryManager; _libraryManager = libraryManager;
@ -72,7 +70,6 @@ namespace Jellyfin.Api.Helpers
_logger = logger; _logger = logger;
_networkManager = networkManager; _networkManager = networkManager;
_deviceManager = deviceManager; _deviceManager = deviceManager;
_authContext = authContext;
} }
/// <summary> /// <summary>
@ -147,7 +144,7 @@ namespace Jellyfin.Api.Helpers
/// <param name="item">Item to set data for.</param> /// <param name="item">Item to set data for.</param>
/// <param name="mediaSource">Media source info.</param> /// <param name="mediaSource">Media source info.</param>
/// <param name="profile">Device profile.</param> /// <param name="profile">Device profile.</param>
/// <param name="auth">Authorization info.</param> /// <param name="claimsPrincipal">Current claims principal.</param>
/// <param name="maxBitrate">Max bitrate.</param> /// <param name="maxBitrate">Max bitrate.</param>
/// <param name="startTimeTicks">Start time ticks.</param> /// <param name="startTimeTicks">Start time ticks.</param>
/// <param name="mediaSourceId">Media source id.</param> /// <param name="mediaSourceId">Media source id.</param>
@ -166,7 +163,7 @@ namespace Jellyfin.Api.Helpers
BaseItem item, BaseItem item,
MediaSourceInfo mediaSource, MediaSourceInfo mediaSource,
DeviceProfile profile, DeviceProfile profile,
AuthorizationInfo auth, ClaimsPrincipal claimsPrincipal,
int? maxBitrate, int? maxBitrate,
long startTimeTicks, long startTimeTicks,
string mediaSourceId, string mediaSourceId,
@ -188,7 +185,7 @@ namespace Jellyfin.Api.Helpers
{ {
MediaSources = new[] { mediaSource }, MediaSources = new[] { mediaSource },
Context = EncodingContext.Streaming, Context = EncodingContext.Streaming,
DeviceId = auth.DeviceId, DeviceId = claimsPrincipal.GetDeviceId(),
ItemId = item.Id, ItemId = item.Id,
Profile = profile, Profile = profile,
MaxAudioChannels = maxAudioChannels, MaxAudioChannels = maxAudioChannels,
@ -290,7 +287,7 @@ namespace Jellyfin.Api.Helpers
mediaSource.SupportsDirectPlay = false; mediaSource.SupportsDirectPlay = false;
mediaSource.SupportsDirectStream = false; mediaSource.SupportsDirectStream = false;
mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); mediaSource.TranscodingUrl = streamInfo.ToUrl("-", claimsPrincipal.GetToken()).TrimStart('-');
mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
mediaSource.TranscodingContainer = streamInfo.Container; mediaSource.TranscodingContainer = streamInfo.Container;
@ -301,7 +298,7 @@ namespace Jellyfin.Api.Helpers
if (!mediaSource.SupportsDirectPlay && (mediaSource.SupportsTranscoding || mediaSource.SupportsDirectStream)) if (!mediaSource.SupportsDirectPlay && (mediaSource.SupportsTranscoding || mediaSource.SupportsDirectStream))
{ {
streamInfo.PlayMethod = PlayMethod.Transcode; streamInfo.PlayMethod = PlayMethod.Transcode;
mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); mediaSource.TranscodingUrl = streamInfo.ToUrl("-", claimsPrincipal.GetToken()).TrimStart('-');
if (!allowVideoStreamCopy) if (!allowVideoStreamCopy)
{ {
@ -316,7 +313,7 @@ namespace Jellyfin.Api.Helpers
} }
// Do this after the above so that StartPositionTicks is set // Do this after the above so that StartPositionTicks is set
SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, claimsPrincipal.GetToken());
mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex; mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex;
} }
@ -384,19 +381,17 @@ namespace Jellyfin.Api.Helpers
/// <summary> /// <summary>
/// Open media source. /// Open media source.
/// </summary> /// </summary>
/// <param name="httpRequest">Http Request.</param> /// <param name="httpContext">Http Context.</param>
/// <param name="request">Live stream request.</param> /// <param name="request">Live stream request.</param>
/// <returns>A <see cref="Task"/> containing the <see cref="LiveStreamResponse"/>.</returns> /// <returns>A <see cref="Task"/> containing the <see cref="LiveStreamResponse"/>.</returns>
public async Task<LiveStreamResponse> OpenMediaSource(HttpRequest httpRequest, LiveStreamRequest request) public async Task<LiveStreamResponse> OpenMediaSource(HttpContext httpContext, LiveStreamRequest request)
{ {
var authInfo = await _authContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false);
var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false);
var profile = request.DeviceProfile; var profile = request.DeviceProfile;
if (profile == null) if (profile == null)
{ {
var clientCapabilities = _deviceManager.GetCapabilities(authInfo.DeviceId); var clientCapabilities = _deviceManager.GetCapabilities(httpContext.User.GetDeviceId());
if (clientCapabilities != null) if (clientCapabilities != null)
{ {
profile = clientCapabilities.DeviceProfile; profile = clientCapabilities.DeviceProfile;
@ -411,7 +406,7 @@ namespace Jellyfin.Api.Helpers
item, item,
result.MediaSource, result.MediaSource,
profile, profile,
authInfo, httpContext.User,
request.MaxStreamingBitrate, request.MaxStreamingBitrate,
request.StartTimeTicks ?? 0, request.StartTimeTicks ?? 0,
result.MediaSource.Id, result.MediaSource.Id,
@ -425,7 +420,7 @@ namespace Jellyfin.Api.Helpers
true, true,
true, true,
true, true,
httpRequest.HttpContext.GetNormalizedRemoteIp()); httpContext.GetNormalizedRemoteIp());
} }
else else
{ {

View file

@ -1,13 +1,16 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
@ -55,37 +58,42 @@ namespace Jellyfin.Api.Helpers
/// <summary> /// <summary>
/// Checks if the user can update an entry. /// Checks if the user can update an entry.
/// </summary> /// </summary>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param> /// <param name="userManager">An instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="requestContext">The <see cref="HttpRequest"/>.</param> /// <param name="claimsPrincipal">The <see cref="ClaimsPrincipal"/> for the current request.</param>
/// <param name="userId">The user id.</param> /// <param name="userId">The user id.</param>
/// <param name="restrictUserPreferences">Whether to restrict the user preferences.</param> /// <param name="restrictUserPreferences">Whether to restrict the user preferences.</param>
/// <returns>A <see cref="bool"/> whether the user can update the entry.</returns> /// <returns>A <see cref="bool"/> whether the user can update the entry.</returns>
internal static async Task<bool> AssertCanUpdateUser(IAuthorizationContext authContext, HttpRequest requestContext, Guid userId, bool restrictUserPreferences) internal static bool AssertCanUpdateUser(IUserManager userManager, ClaimsPrincipal claimsPrincipal, Guid userId, bool restrictUserPreferences)
{ {
var auth = await authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); var authenticatedUserId = claimsPrincipal.GetUserId();
var isAdministrator = claimsPrincipal.IsInRole(UserRoles.Administrator);
var authenticatedUser = auth.User;
// If they're going to update the record of another user, they must be an administrator // If they're going to update the record of another user, they must be an administrator
if ((!userId.Equals(auth.UserId) && !authenticatedUser.HasPermission(PermissionKind.IsAdministrator)) if (!userId.Equals(authenticatedUserId) && !isAdministrator)
|| (restrictUserPreferences && !authenticatedUser.EnableUserPreferenceAccess))
{ {
return false; return false;
} }
return true; // TODO the EnableUserPreferenceAccess policy does not seem to be used elsewhere
if (!restrictUserPreferences || isAdministrator)
{
return true;
}
var user = userManager.GetUserById(userId);
return user.EnableUserPreferenceAccess;
} }
internal static async Task<SessionInfo> GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) internal static async Task<SessionInfo> GetSession(ISessionManager sessionManager, IUserManager userManager, HttpContext httpContext)
{ {
var authorization = await authContext.GetAuthorizationInfo(request).ConfigureAwait(false); var userId = httpContext.User.GetUserId();
var user = authorization.User; var user = userManager.GetUserById(userId);
var session = await sessionManager.LogSessionActivity( var session = await sessionManager.LogSessionActivity(
authorization.Client, httpContext.User.GetClient(),
authorization.Version, httpContext.User.GetVersion(),
authorization.DeviceId, httpContext.User.GetDeviceId(),
authorization.Device, httpContext.User.GetDevice(),
request.HttpContext.GetNormalizedRemoteIp().ToString(), httpContext.GetNormalizedRemoteIp().ToString(),
user).ConfigureAwait(false); user).ConfigureAwait(false);
if (session == null) if (session == null)
@ -96,9 +104,9 @@ namespace Jellyfin.Api.Helpers
return session; return session;
} }
internal static async Task<string> GetSessionId(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) internal static async Task<string> GetSessionId(ISessionManager sessionManager, IUserManager userManager, HttpContext httpContext)
{ {
var session = await GetSession(sessionManager, authContext, request).ConfigureAwait(false); var session = await GetSession(sessionManager, userManager, httpContext).ConfigureAwait(false);
return session.Id; return session.Id;
} }

View file

@ -5,6 +5,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;
using Jellyfin.Extensions; using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
@ -14,7 +15,6 @@ using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -33,8 +33,7 @@ namespace Jellyfin.Api.Helpers
/// Gets the current streaming state. /// Gets the current streaming state.
/// </summary> /// </summary>
/// <param name="streamingRequest">The <see cref="StreamingRequestDto"/>.</param> /// <param name="streamingRequest">The <see cref="StreamingRequestDto"/>.</param>
/// <param name="httpRequest">The <see cref="HttpRequest"/>.</param> /// <param name="httpContext">The <see cref="HttpContext"/>.</param>
/// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param> /// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
@ -49,8 +48,7 @@ namespace Jellyfin.Api.Helpers
/// <returns>A <see cref="Task"/> containing the current <see cref="StreamState"/>.</returns> /// <returns>A <see cref="Task"/> containing the current <see cref="StreamState"/>.</returns>
public static async Task<StreamState> GetStreamingState( public static async Task<StreamState> GetStreamingState(
StreamingRequestDto streamingRequest, StreamingRequestDto streamingRequest,
HttpRequest httpRequest, HttpContext httpContext,
IAuthorizationContext authorizationContext,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
@ -63,6 +61,7 @@ namespace Jellyfin.Api.Helpers
TranscodingJobType transcodingJobType, TranscodingJobType transcodingJobType,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var httpRequest = httpContext.Request;
// Parse the DLNA time seek header // Parse the DLNA time seek header
if (!streamingRequest.StartTimeTicks.HasValue) if (!streamingRequest.StartTimeTicks.HasValue)
{ {
@ -101,10 +100,10 @@ namespace Jellyfin.Api.Helpers
EnableDlnaHeaders = enableDlnaHeaders EnableDlnaHeaders = enableDlnaHeaders
}; };
var auth = await authorizationContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false); var userId = httpContext.User.GetUserId();
if (!auth.UserId.Equals(default)) if (!userId.Equals(default))
{ {
state.User = userManager.GetUserById(auth.UserId); state.User = userManager.GetUserById(userId);
} }
if (state.IsVideoRequest && !string.IsNullOrWhiteSpace(state.Request.VideoCodec)) if (state.IsVideoRequest && !string.IsNullOrWhiteSpace(state.Request.VideoCodec))

View file

@ -8,6 +8,7 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.PlaybackDtos;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
@ -17,7 +18,6 @@ using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -46,7 +46,6 @@ namespace Jellyfin.Api.Helpers
private readonly IAttachmentExtractor _attachmentExtractor; private readonly IAttachmentExtractor _attachmentExtractor;
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly IAuthorizationContext _authorizationContext;
private readonly EncodingHelper _encodingHelper; private readonly EncodingHelper _encodingHelper;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILogger<TranscodingJobHelper> _logger; private readonly ILogger<TranscodingJobHelper> _logger;
@ -55,6 +54,7 @@ namespace Jellyfin.Api.Helpers
private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
private readonly ILoggerFactory _loggerFactory; private readonly ILoggerFactory _loggerFactory;
private readonly IUserManager _userManager;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TranscodingJobHelper"/> class. /// Initializes a new instance of the <see cref="TranscodingJobHelper"/> class.
@ -67,9 +67,9 @@ namespace Jellyfin.Api.Helpers
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param> /// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param> /// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
/// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param> /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param> /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
public TranscodingJobHelper( public TranscodingJobHelper(
IAttachmentExtractor attachmentExtractor, IAttachmentExtractor attachmentExtractor,
IApplicationPaths appPaths, IApplicationPaths appPaths,
@ -79,9 +79,9 @@ namespace Jellyfin.Api.Helpers
IMediaEncoder mediaEncoder, IMediaEncoder mediaEncoder,
IServerConfigurationManager serverConfigurationManager, IServerConfigurationManager serverConfigurationManager,
ISessionManager sessionManager, ISessionManager sessionManager,
IAuthorizationContext authorizationContext,
EncodingHelper encodingHelper, EncodingHelper encodingHelper,
ILoggerFactory loggerFactory) ILoggerFactory loggerFactory,
IUserManager userManager)
{ {
_attachmentExtractor = attachmentExtractor; _attachmentExtractor = attachmentExtractor;
_appPaths = appPaths; _appPaths = appPaths;
@ -91,9 +91,9 @@ namespace Jellyfin.Api.Helpers
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
_serverConfigurationManager = serverConfigurationManager; _serverConfigurationManager = serverConfigurationManager;
_sessionManager = sessionManager; _sessionManager = sessionManager;
_authorizationContext = authorizationContext;
_encodingHelper = encodingHelper; _encodingHelper = encodingHelper;
_loggerFactory = loggerFactory; _loggerFactory = loggerFactory;
_userManager = userManager;
DeleteEncodedMediaCache(); DeleteEncodedMediaCache();
@ -512,8 +512,9 @@ namespace Jellyfin.Api.Helpers
if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec))
{ {
var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false); var userId = request.HttpContext.User.GetUserId();
if (auth.User != null && !auth.User.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) var user = userId.Equals(default) ? null : _userManager.GetUserById(userId);
if (user != null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding))
{ {
this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state); this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state);

View file

@ -1,20 +0,0 @@
#pragma warning disable CS1591
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Session;
using Microsoft.AspNetCore.Http;
namespace MediaBrowser.Controller.Net
{
public interface ISessionContext
{
Task<SessionInfo> GetSession(object requestContext);
Task<User?> GetUser(object requestContext);
Task<SessionInfo> GetSession(HttpContext requestContext);
Task<User?> GetUser(HttpContext requestContext);
}
}