Tim Eisele 1 month ago committed by GitHub
commit f119dc069a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -34,20 +34,9 @@ namespace Jellyfin.Api.Auth.LocalAccessOrRequiresElevationPolicy
var ip = _httpContextAccessor.HttpContext?.GetNormalizedRemoteIP(); var ip = _httpContextAccessor.HttpContext?.GetNormalizedRemoteIP();
// Loopback will be on LAN, so we can accept null. // Loopback will be on LAN, so we can accept null.
if (ip is null || _networkManager.IsInLocalNetwork(ip)) if (ip is null || _networkManager.IsInLocalNetwork(ip) || context.User.IsInRole(UserRoles.Administrator))
{ {
context.Succeed(requirement); context.Succeed(requirement);
return Task.CompletedTask;
}
if (context.User.IsInRole(UserRoles.Administrator))
{
context.Succeed(requirement);
}
else
{
context.Fail();
} }
return Task.CompletedTask; return Task.CompletedTask;

@ -4,10 +4,11 @@ using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Api;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Streaming; using MediaBrowser.Controller.Streaming;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -16,6 +17,7 @@ namespace Jellyfin.Api.Controllers;
/// <summary> /// <summary>
/// The audio controller. /// The audio controller.
/// </summary> /// </summary>
[Authorize(Policy = Policies.Playback)]
public class AudioController : BaseJellyfinApiController public class AudioController : BaseJellyfinApiController
{ {
private readonly AudioHelper _audioHelper; private readonly AudioHelper _audioHelper;

@ -15,6 +15,7 @@ using Jellyfin.Api.Models.StreamingDtos;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using Jellyfin.Extensions; using Jellyfin.Extensions;
using Jellyfin.MediaEncoding.Hls.Playlist; using Jellyfin.MediaEncoding.Hls.Playlist;
using MediaBrowser.Common.Api;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
@ -36,16 +37,14 @@ namespace Jellyfin.Api.Controllers;
/// <summary> /// <summary>
/// Dynamic hls controller. /// Dynamic hls controller.
/// </summary> /// </summary>
[Route("")] [Authorize(Policy = Policies.Playback)]
[Authorize]
public class DynamicHlsController : BaseJellyfinApiController public class DynamicHlsController : BaseJellyfinApiController
{ {
private const string DefaultVodEncoderPreset = "veryfast"; private const string DefaultVodEncoderPreset = "veryfast";
private const string DefaultEventEncoderPreset = "superfast"; private const string DefaultEventEncoderPreset = "superfast";
private const TranscodingJobType TranscodingJobType = MediaBrowser.Controller.MediaEncoding.TranscodingJobType.Hls; private const TranscodingJobType DefaultTranscodingJobType = TranscodingJobType.Hls;
private readonly Version _minFFmpegFlacInMp4 = new Version(6, 0); private readonly Version _minFFmpegFlacInMp4 = new Version(6, 0);
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
@ -285,7 +284,7 @@ public class DynamicHlsController : BaseJellyfinApiController
_mediaEncoder, _mediaEncoder,
_encodingHelper, _encodingHelper,
_transcodeManager, _transcodeManager,
TranscodingJobType, DefaultTranscodingJobType,
cancellationToken) cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
@ -306,7 +305,7 @@ public class DynamicHlsController : BaseJellyfinApiController
playlistPath, playlistPath,
GetCommandLineArguments(playlistPath, state, true, 0), GetCommandLineArguments(playlistPath, state, true, 0),
Request.HttpContext.User.GetUserId(), Request.HttpContext.User.GetUserId(),
TranscodingJobType, DefaultTranscodingJobType,
cancellationTokenSource) cancellationTokenSource)
.ConfigureAwait(false); .ConfigureAwait(false);
job.IsLiveOutput = true; job.IsLiveOutput = true;
@ -326,7 +325,7 @@ public class DynamicHlsController : BaseJellyfinApiController
} }
} }
job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
if (job is not null) if (job is not null)
{ {
@ -508,7 +507,7 @@ public class DynamicHlsController : BaseJellyfinApiController
EnableTrickplay = enableTrickplay EnableTrickplay = enableTrickplay
}; };
return await _dynamicHlsHelper.GetMasterHlsPlaylist(TranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false); return await _dynamicHlsHelper.GetMasterHlsPlaylist(DefaultTranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
} }
/// <summary> /// <summary>
@ -674,7 +673,7 @@ public class DynamicHlsController : BaseJellyfinApiController
EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming
}; };
return await _dynamicHlsHelper.GetMasterHlsPlaylist(TranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false); return await _dynamicHlsHelper.GetMasterHlsPlaylist(DefaultTranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
} }
/// <summary> /// <summary>
@ -1379,7 +1378,7 @@ public class DynamicHlsController : BaseJellyfinApiController
_mediaEncoder, _mediaEncoder,
_encodingHelper, _encodingHelper,
_transcodeManager, _transcodeManager,
TranscodingJobType, DefaultTranscodingJobType,
cancellationTokenSource.Token) cancellationTokenSource.Token)
.ConfigureAwait(false); .ConfigureAwait(false);
@ -1417,7 +1416,7 @@ public class DynamicHlsController : BaseJellyfinApiController
_mediaEncoder, _mediaEncoder,
_encodingHelper, _encodingHelper,
_transcodeManager, _transcodeManager,
TranscodingJobType, DefaultTranscodingJobType,
cancellationToken) cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
@ -1431,7 +1430,7 @@ public class DynamicHlsController : BaseJellyfinApiController
if (System.IO.File.Exists(segmentPath)) if (System.IO.File.Exists(segmentPath))
{ {
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
_logger.LogDebug("returning {0} [it exists, try 1]", segmentPath); _logger.LogDebug("returning {0} [it exists, try 1]", segmentPath);
return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false); return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false);
} }
@ -1441,7 +1440,7 @@ public class DynamicHlsController : BaseJellyfinApiController
var startTranscoding = false; var startTranscoding = false;
if (System.IO.File.Exists(segmentPath)) if (System.IO.File.Exists(segmentPath))
{ {
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
_logger.LogDebug("returning {0} [it exists, try 2]", segmentPath); _logger.LogDebug("returning {0} [it exists, try 2]", segmentPath);
return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false); return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false);
} }
@ -1492,7 +1491,7 @@ public class DynamicHlsController : BaseJellyfinApiController
playlistPath, playlistPath,
GetCommandLineArguments(playlistPath, state, false, segmentId), GetCommandLineArguments(playlistPath, state, false, segmentId),
Request.HttpContext.User.GetUserId(), Request.HttpContext.User.GetUserId(),
TranscodingJobType, DefaultTranscodingJobType,
cancellationTokenSource).ConfigureAwait(false); cancellationTokenSource).ConfigureAwait(false);
} }
catch catch
@ -1505,7 +1504,7 @@ public class DynamicHlsController : BaseJellyfinApiController
} }
else else
{ {
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
if (job?.TranscodingThrottler is not null) if (job?.TranscodingThrottler is not null)
{ {
await job.TranscodingThrottler.UnpauseTranscoding().ConfigureAwait(false); await job.TranscodingThrottler.UnpauseTranscoding().ConfigureAwait(false);
@ -1514,7 +1513,7 @@ public class DynamicHlsController : BaseJellyfinApiController
} }
_logger.LogDebug("returning {0} [general case]", segmentPath); _logger.LogDebug("returning {0} [general case]", segmentPath);
job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false); return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false);
} }
@ -1970,7 +1969,7 @@ public class DynamicHlsController : BaseJellyfinApiController
private int? GetCurrentTranscodingIndex(string playlist, string segmentExtension) private int? GetCurrentTranscodingIndex(string playlist, string segmentExtension)
{ {
var job = _transcodeManager.GetTranscodingJob(playlist, TranscodingJobType); var job = _transcodeManager.GetTranscodingJob(playlist, DefaultTranscodingJobType);
if (job is null || job.HasExited) if (job is null || job.HasExited)
{ {

@ -5,6 +5,7 @@ using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Jellyfin.Api.Attributes; using Jellyfin.Api.Attributes;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using MediaBrowser.Common.Api;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
@ -20,6 +21,7 @@ namespace Jellyfin.Api.Controllers;
/// The hls segment controller. /// The hls segment controller.
/// </summary> /// </summary>
[Route("")] [Route("")]
[Authorize(Policy = Policies.Playback)]
public class HlsSegmentController : BaseJellyfinApiController public class HlsSegmentController : BaseJellyfinApiController
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;

@ -1156,6 +1156,7 @@ public class LiveTvController : BaseJellyfinApiController
/// or a <see cref="NotFoundResult"/> if recording not found. /// or a <see cref="NotFoundResult"/> if recording not found.
/// </returns> /// </returns>
[HttpGet("LiveRecordings/{recordingId}/stream")] [HttpGet("LiveRecordings/{recordingId}/stream")]
[Authorize(Policy = Policies.Playback)]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesVideoFile] [ProducesVideoFile]
@ -1183,6 +1184,7 @@ public class LiveTvController : BaseJellyfinApiController
/// or a <see cref="NotFoundResult"/> if stream not found. /// or a <see cref="NotFoundResult"/> if stream not found.
/// </returns> /// </returns>
[HttpGet("LiveStreamFiles/{streamId}/stream.{container}")] [HttpGet("LiveStreamFiles/{streamId}/stream.{container}")]
[Authorize(Policy = Policies.Playback)]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesVideoFile] [ProducesVideoFile]

@ -8,6 +8,7 @@ using Jellyfin.Api.Attributes;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Api.Models.StreamingDtos;
using MediaBrowser.Common.Api;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using Jellyfin.Extensions; using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
@ -28,6 +29,7 @@ namespace Jellyfin.Api.Controllers;
/// The universal audio controller. /// The universal audio controller.
/// </summary> /// </summary>
[Route("")] [Route("")]
[Authorize(Policy = Policies.Playback)]
public class UniversalAudioController : BaseJellyfinApiController public class UniversalAudioController : BaseJellyfinApiController
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
@ -89,7 +91,6 @@ public class UniversalAudioController : BaseJellyfinApiController
/// <returns>A <see cref="Task"/> containing the audio file.</returns> /// <returns>A <see cref="Task"/> containing the audio file.</returns>
[HttpGet("Audio/{itemId}/universal")] [HttpGet("Audio/{itemId}/universal")]
[HttpHead("Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")] [HttpHead("Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status302Found)] [ProducesResponseType(StatusCodes.Status302Found)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]

@ -10,6 +10,7 @@ using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -19,6 +20,7 @@ namespace Jellyfin.Api.Controllers;
/// Attachments controller. /// Attachments controller.
/// </summary> /// </summary>
[Route("Videos")] [Route("Videos")]
[Authorize]
public class VideoAttachmentsController : BaseJellyfinApiController public class VideoAttachmentsController : BaseJellyfinApiController
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;

@ -310,6 +310,7 @@ public class VideosController : BaseJellyfinApiController
/// <returns>A <see cref="FileResult"/> containing the audio file.</returns> /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
[HttpGet("{itemId}/stream")] [HttpGet("{itemId}/stream")]
[HttpHead("{itemId}/stream", Name = "HeadVideoStream")] [HttpHead("{itemId}/stream", Name = "HeadVideoStream")]
[Authorize(Policy = Policies.Playback)]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesVideoFile] [ProducesVideoFile]
public async Task<ActionResult> GetVideoStream( public async Task<ActionResult> GetVideoStream(
@ -548,6 +549,7 @@ public class VideosController : BaseJellyfinApiController
/// <returns>A <see cref="FileResult"/> containing the audio file.</returns> /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
[HttpGet("{itemId}/stream.{container}")] [HttpGet("{itemId}/stream.{container}")]
[HttpHead("{itemId}/stream.{container}", Name = "HeadVideoStreamByContainer")] [HttpHead("{itemId}/stream.{container}", Name = "HeadVideoStreamByContainer")]
[Authorize(Policy = Policies.Playback)]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesVideoFile] [ProducesVideoFile]
public Task<ActionResult> GetVideoStreamByContainer( public Task<ActionResult> GetVideoStreamByContainer(

@ -77,6 +77,7 @@ namespace Jellyfin.Server.Extensions
options.AddPolicy(Policies.LiveTvAccess, new UserPermissionRequirement(PermissionKind.EnableLiveTvAccess)); options.AddPolicy(Policies.LiveTvAccess, new UserPermissionRequirement(PermissionKind.EnableLiveTvAccess));
options.AddPolicy(Policies.LiveTvManagement, new UserPermissionRequirement(PermissionKind.EnableLiveTvManagement)); options.AddPolicy(Policies.LiveTvManagement, new UserPermissionRequirement(PermissionKind.EnableLiveTvManagement));
options.AddPolicy(Policies.LocalAccessOrRequiresElevation, new LocalAccessOrRequiresElevationRequirement()); options.AddPolicy(Policies.LocalAccessOrRequiresElevation, new LocalAccessOrRequiresElevationRequirement());
options.AddPolicy(Policies.Playback, new UserPermissionRequirement(PermissionKind.EnableMediaPlayback));
options.AddPolicy(Policies.SyncPlayHasAccess, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.HasAccess)); options.AddPolicy(Policies.SyncPlayHasAccess, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.HasAccess));
options.AddPolicy(Policies.SyncPlayCreateGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.CreateGroup)); options.AddPolicy(Policies.SyncPlayCreateGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.CreateGroup));
options.AddPolicy(Policies.SyncPlayJoinGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.JoinGroup)); options.AddPolicy(Policies.SyncPlayJoinGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.JoinGroup));

@ -94,4 +94,9 @@ public static class Policies
/// Policy name for accessing lyric management. /// Policy name for accessing lyric management.
/// </summary> /// </summary>
public const string LyricManagement = "LyricManagement"; public const string LyricManagement = "LyricManagement";
/// <summary>
/// Policy name for playback.
/// </summary>
public const string Playback = "Playback";
} }

Loading…
Cancel
Save