diff --git a/Jellyfin.Api/Constants/Policies.cs b/Jellyfin.Api/Constants/Policies.cs index 53841b0c4..02fdef150 100644 --- a/Jellyfin.Api/Constants/Policies.cs +++ b/Jellyfin.Api/Constants/Policies.cs @@ -84,4 +84,9 @@ public static class Policies /// Policy name for managing LiveTV. /// public const string LiveTvManagement = "LiveTvManagement"; + + /// + /// Policy name for accessing subtitles management. + /// + public const string SubtitleManagement = "SubtitleManagement"; } diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index fb89e9610..c9e256af3 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -115,7 +115,7 @@ public class SubtitleController : BaseJellyfinApiController /// Subtitles retrieved. /// An array of . [HttpGet("Items/{itemId}/RemoteSearch/Subtitles/{language}")] - [Authorize] + [Authorize(Policy = Policies.SubtitleManagement)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task>> SearchRemoteSubtitles( [FromRoute, Required] Guid itemId, @@ -135,7 +135,7 @@ public class SubtitleController : BaseJellyfinApiController /// Subtitle downloaded. /// A . [HttpPost("Items/{itemId}/RemoteSearch/Subtitles/{subtitleId}")] - [Authorize] + [Authorize(Policy = Policies.SubtitleManagement)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task DownloadRemoteSubtitles( [FromRoute, Required] Guid itemId, @@ -399,7 +399,7 @@ public class SubtitleController : BaseJellyfinApiController /// Subtitle uploaded. /// A . [HttpPost("Videos/{itemId}/Subtitles")] - [Authorize(Policy = Policies.RequiresElevation)] + [Authorize(Policy = Policies.SubtitleManagement)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task UploadSubtitle( [FromRoute, Required] Guid itemId, diff --git a/Jellyfin.Data/Entities/User.cs b/Jellyfin.Data/Entities/User.cs index 5c3e0338d..ea0de3016 100644 --- a/Jellyfin.Data/Entities/User.cs +++ b/Jellyfin.Data/Entities/User.cs @@ -505,6 +505,7 @@ namespace Jellyfin.Data.Entities Permissions.Add(new Permission(PermissionKind.ForceRemoteSourceTranscoding, false)); Permissions.Add(new Permission(PermissionKind.EnableRemoteControlOfOtherUsers, false)); Permissions.Add(new Permission(PermissionKind.EnableCollectionManagement, false)); + Permissions.Add(new Permission(PermissionKind.EnableSubtitleManagement, false)); } /// diff --git a/Jellyfin.Data/Enums/PermissionKind.cs b/Jellyfin.Data/Enums/PermissionKind.cs index 40280b95e..6644f0151 100644 --- a/Jellyfin.Data/Enums/PermissionKind.cs +++ b/Jellyfin.Data/Enums/PermissionKind.cs @@ -113,6 +113,11 @@ namespace Jellyfin.Data.Enums /// /// Whether the user can create, modify and delete collections. /// - EnableCollectionManagement = 21 + EnableCollectionManagement = 21, + + /// + /// Whether the user can edit subtitles. + /// + EnableSubtitleManagement = 22 } } diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index b2cb589f7..edae4cfc5 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -359,6 +359,7 @@ namespace Jellyfin.Server.Implementations.Users ForceRemoteSourceTranscoding = user.HasPermission(PermissionKind.ForceRemoteSourceTranscoding), EnablePublicSharing = user.HasPermission(PermissionKind.EnablePublicSharing), EnableCollectionManagement = user.HasPermission(PermissionKind.EnableCollectionManagement), + EnableSubtitleManagement = user.HasPermission(PermissionKind.EnableSubtitleManagement), AccessSchedules = user.AccessSchedules.ToArray(), BlockedTags = user.GetPreference(PreferenceKind.BlockedTags), AllowedTags = user.GetPreference(PreferenceKind.AllowedTags), @@ -683,6 +684,7 @@ namespace Jellyfin.Server.Implementations.Users user.SetPermission(PermissionKind.EnableRemoteControlOfOtherUsers, policy.EnableRemoteControlOfOtherUsers); user.SetPermission(PermissionKind.EnablePlaybackRemuxing, policy.EnablePlaybackRemuxing); user.SetPermission(PermissionKind.EnableCollectionManagement, policy.EnableCollectionManagement); + user.SetPermission(PermissionKind.EnableSubtitleManagement, policy.EnableSubtitleManagement); user.SetPermission(PermissionKind.ForceRemoteSourceTranscoding, policy.ForceRemoteSourceTranscoding); user.SetPermission(PermissionKind.EnablePublicSharing, policy.EnablePublicSharing); diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index cb1680558..b7e71a81d 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -82,6 +82,7 @@ namespace Jellyfin.Server.Extensions options.AddPolicy(Policies.SyncPlayCreateGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.CreateGroup)); options.AddPolicy(Policies.SyncPlayJoinGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.JoinGroup)); options.AddPolicy(Policies.SyncPlayIsInGroup, new SyncPlayAccessRequirement(SyncPlayAccessRequirementType.IsInGroup)); + options.AddPolicy(Policies.SubtitleManagement, new UserPermissionRequirement(PermissionKind.EnableSubtitleManagement)); options.AddPolicy( Policies.RequiresElevation, policy => policy.AddAuthenticationSchemes(AuthenticationSchemes.CustomAuthentication) diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs index 8354c60ef..f5aff07db 100644 --- a/MediaBrowser.Model/Users/UserPolicy.cs +++ b/MediaBrowser.Model/Users/UserPolicy.cs @@ -15,6 +15,7 @@ namespace MediaBrowser.Model.Users { IsHidden = true; EnableCollectionManagement = false; + EnableSubtitleManagement = false; EnableContentDeletion = false; EnableContentDeletionFromFolders = Array.Empty(); @@ -83,6 +84,13 @@ namespace MediaBrowser.Model.Users [DefaultValue(false)] public bool EnableCollectionManagement { get; set; } + /// + /// Gets or sets a value indicating whether this instance can manage subtitles. + /// + /// true if this instance is allowed; otherwise, false. + [DefaultValue(false)] + public bool EnableSubtitleManagement { get; set; } + /// /// Gets or sets a value indicating whether this instance is disabled. ///