fix: use HttpContext and ClaimsPrincipal instead of IAuthorizationContext

pull/8500/head
cvium 2 years ago
parent 927fe33d3a
commit 5dc30c6a6d

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

@ -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);
}
}
}

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

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

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

@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true)
{
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
User? user = null;
@ -323,7 +323,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true)
{
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
User? user = null;
@ -463,7 +463,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)]
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);

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

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

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

@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true)
{
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
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)
{
var dtoOptions = new DtoOptions()
.AddClientFields(Request);
.AddClientFields(User);
Genre? item;
if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase))

@ -17,7 +17,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Branding;
using MediaBrowser.Model.Drawing;
@ -44,11 +43,9 @@ namespace Jellyfin.Api.Controllers
private readonly IProviderManager _providerManager;
private readonly IImageProcessor _imageProcessor;
private readonly IFileSystem _fileSystem;
private readonly IAuthorizationContext _authContext;
private readonly ILogger<ImageController> _logger;
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IApplicationPaths _appPaths;
private readonly IImageEncoder _imageEncoder;
/// <summary>
/// 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="imageProcessor">Instance of the <see cref="IImageProcessor"/> 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="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> 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(
IUserManager userManager,
ILibraryManager libraryManager,
IProviderManager providerManager,
IImageProcessor imageProcessor,
IFileSystem fileSystem,
IAuthorizationContext authContext,
ILogger<ImageController> logger,
IServerConfigurationManager serverConfigurationManager,
IApplicationPaths appPaths,
IImageEncoder imageEncoder)
IApplicationPaths appPaths)
{
_userManager = userManager;
_libraryManager = libraryManager;
_providerManager = providerManager;
_imageProcessor = imageProcessor;
_fileSystem = fileSystem;
_authContext = authContext;
_logger = logger;
_serverConfigurationManager = serverConfigurationManager;
_appPaths = appPaths;
_imageEncoder = imageEncoder;
}
/// <summary>
@ -108,7 +99,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType,
[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.");
}
@ -155,7 +146,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType,
[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.");
}
@ -201,7 +192,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType,
[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.");
}
@ -245,7 +236,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType,
[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.");
}

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

@ -10,7 +10,6 @@ using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@ -34,7 +33,6 @@ namespace Jellyfin.Api.Controllers
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localization;
private readonly IDtoService _dtoService;
private readonly IAuthorizationContext _authContext;
private readonly ILogger<ItemsController> _logger;
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="localization">Instance of the <see cref="ILocalizationManager"/> 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="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
public ItemsController(
@ -53,7 +50,6 @@ namespace Jellyfin.Api.Controllers
ILibraryManager libraryManager,
ILocalizationManager localization,
IDtoService dtoService,
IAuthorizationContext authContext,
ILogger<ItemsController> logger,
ISessionManager sessionManager)
{
@ -61,7 +57,6 @@ namespace Jellyfin.Api.Controllers
_libraryManager = libraryManager;
_localization = localization;
_dtoService = dtoService;
_authContext = authContext;
_logger = logger;
_sessionManager = sessionManager;
}
@ -244,21 +239,20 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = 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
var user = !auth.IsApiKey && userId.HasValue && !userId.Value.Equals(default)
var user = !isApiKey && userId.HasValue && !userId.Value.Equals(default)
? _userManager.GetUserById(userId.Value)
: null;
// 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");
}
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
if (includeItemTypes.Length == 1
@ -288,12 +282,12 @@ namespace Jellyfin.Api.Controllers
includeItemTypes = new[] { BaseItemKind.Playlist };
}
var enabledChannels = auth.IsApiKey
var enabledChannels = isApiKey
? Array.Empty<Guid>()
: user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels);
// 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
// Assume all folders inside an EnabledChannel are enabled
|| Array.IndexOf(enabledChannels, item.Id) != -1
@ -850,7 +844,7 @@ namespace Jellyfin.Api.Controllers
var user = _userManager.GetUserById(userId);
var parentIdGuid = parentId ?? Guid.Empty;
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var ancestorIds = Array.Empty<Guid>();

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

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

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

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

@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true)
{
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
User? user = userId is null || userId.Value.Equals(default)
@ -145,7 +145,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)]
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;

@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true)
{
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
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)
{
var dtoOptions = new DtoOptions()
.AddClientFields(Request);
.AddClientFields(User);
var item = _libraryManager.GetPerson(name);
if (item == null)

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

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

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

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

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

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

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

@ -5,7 +5,7 @@ using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.SyncPlayDtos;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.SyncPlay;
using MediaBrowser.Controller.SyncPlay.PlaybackRequests;
@ -24,23 +24,23 @@ namespace Jellyfin.Api.Controllers
public class SyncPlayController : BaseJellyfinApiController
{
private readonly ISessionManager _sessionManager;
private readonly IAuthorizationContext _authorizationContext;
private readonly ISyncPlayManager _syncPlayManager;
private readonly IUserManager _userManager;
/// <summary>
/// Initializes a new instance of the <see cref="SyncPlayController"/> class.
/// </summary>
/// <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="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
public SyncPlayController(
ISessionManager sessionManager,
IAuthorizationContext authorizationContext,
ISyncPlayManager syncPlayManager)
ISyncPlayManager syncPlayManager,
IUserManager userManager)
{
_sessionManager = sessionManager;
_authorizationContext = authorizationContext;
_syncPlayManager = syncPlayManager;
_userManager = userManager;
}
/// <summary>
@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayCreateGroup(
[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);
_syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayJoinGroup(
[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);
_syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)]
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();
_syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -105,7 +105,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayJoinGroup)]
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();
return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest));
}
@ -122,7 +122,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetNewQueue(
[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(
requestData.PlayingQueue,
requestData.PlayingItemPosition,
@ -143,7 +143,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetPlaylistItem(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayRemoveFromPlaylist(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayMovePlaylistItem(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -197,7 +197,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayQueue(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -213,7 +213,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)]
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();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -229,7 +229,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)]
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();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -245,7 +245,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.SyncPlayIsInGroup)]
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();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -263,7 +263,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySeek(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -281,7 +281,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayBuffering(
[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(
requestData.When,
requestData.PositionTicks,
@ -303,7 +303,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayReady(
[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(
requestData.When,
requestData.PositionTicks,
@ -325,7 +325,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetIgnoreWait(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -343,7 +343,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayNextItem(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -361,7 +361,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayPreviousItem(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -379,7 +379,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetRepeatMode(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -397,7 +397,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlaySetShuffleMode(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();
@ -414,7 +414,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SyncPlayPing(
[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);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent();

@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableRewatching = false)
{
var options = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var result = _tvSeriesManager.GetNextUp(
@ -154,7 +154,7 @@ namespace Jellyfin.Api.Controllers
var parentIdGuid = parentId ?? Guid.Empty;
var options = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers
List<BaseItem> episodes;
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
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 }
.AddClientFields(Request)
.AddClientFields(User)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user);

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

@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.UserDtos;
using Jellyfin.Data.Enums;
@ -264,7 +265,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId,
[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.");
}
@ -282,7 +283,7 @@ namespace Jellyfin.Api.Controllers
}
else
{
if (!HttpContext.User.IsInRole(UserRoles.Administrator))
if (!User.IsInRole(UserRoles.Administrator))
{
var success = await _userManager.AuthenticateUser(
user.Username,
@ -299,7 +300,7 @@ namespace Jellyfin.Api.Controllers
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);
}
@ -325,7 +326,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId,
[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.");
}
@ -367,7 +368,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId,
[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.");
}
@ -427,7 +428,7 @@ namespace Jellyfin.Api.Controllers
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);
}
@ -452,7 +453,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId,
[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");
}
@ -536,13 +537,13 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<UserDto> GetCurrentUser()
{
var userId = ClaimHelpers.GetUserId(Request.HttpContext.User);
if (userId is null)
var userId = User.GetUserId();
if (userId.Equals(default))
{
return BadRequest();
}
var user = _userManager.GetUserById(userId.Value);
var user = _userManager.GetUserById(userId);
if (user == null)
{
return BadRequest();
@ -567,7 +568,7 @@ namespace Jellyfin.Api.Controllers
if (filterByDevice)
{
var deviceId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId;
var deviceId = User.GetDeviceId();
if (!string.IsNullOrWhiteSpace(deviceId))
{

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

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

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

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

@ -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;
}

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

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

@ -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();
}
}
}

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

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

@ -1,13 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@ -55,37 +58,42 @@ namespace Jellyfin.Api.Helpers
/// <summary>
/// Checks if the user can update an entry.
/// </summary>
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="requestContext">The <see cref="HttpRequest"/>.</param>
/// <param name="userManager">An instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="claimsPrincipal">The <see cref="ClaimsPrincipal"/> for the current request.</param>
/// <param name="userId">The user id.</param>
/// <param name="restrictUserPreferences">Whether to restrict the user preferences.</param>
/// <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 authenticatedUser = auth.User;
var authenticatedUserId = claimsPrincipal.GetUserId();
var isAdministrator = claimsPrincipal.IsInRole(UserRoles.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))
|| (restrictUserPreferences && !authenticatedUser.EnableUserPreferenceAccess))
if (!userId.Equals(authenticatedUserId) && !isAdministrator)
{
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 user = authorization.User;
var userId = httpContext.User.GetUserId();
var user = userManager.GetUserById(userId);
var session = await sessionManager.LogSessionActivity(
authorization.Client,
authorization.Version,
authorization.DeviceId,
authorization.Device,
request.HttpContext.GetNormalizedRemoteIp().ToString(),
httpContext.User.GetClient(),
httpContext.User.GetVersion(),
httpContext.User.GetDeviceId(),
httpContext.User.GetDevice(),
httpContext.GetNormalizedRemoteIp().ToString(),
user).ConfigureAwait(false);
if (session == null)
@ -96,9 +104,9 @@ namespace Jellyfin.Api.Helpers
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;
}

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

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

@ -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);
}
}
Loading…
Cancel
Save