aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Controllers')
-rw-r--r--Jellyfin.Api/Controllers/ItemUpdateController.cs12
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/PlaylistsController.cs6
-rw-r--r--Jellyfin.Api/Controllers/StartupController.cs4
-rw-r--r--Jellyfin.Api/Controllers/SystemController.cs12
-rw-r--r--Jellyfin.Api/Controllers/UserController.cs26
6 files changed, 33 insertions, 28 deletions
diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs
index ece053a9a..504f2fa1d 100644
--- a/Jellyfin.Api/Controllers/ItemUpdateController.cs
+++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs
@@ -251,8 +251,6 @@ public class ItemUpdateController : BaseJellyfinApiController
channel.Height = request.Height.Value;
}
- item.Tags = request.Tags;
-
if (request.Taglines is not null)
{
item.Tagline = request.Taglines.FirstOrDefault();
@@ -276,12 +274,19 @@ public class ItemUpdateController : BaseJellyfinApiController
item.OfficialRating = request.OfficialRating;
item.CustomRating = request.CustomRating;
+ var currentTags = item.Tags;
+ var newTags = request.Tags;
+ var removedTags = currentTags.Except(newTags).ToList();
+ var addedTags = newTags.Except(currentTags).ToList();
+ item.Tags = newTags;
+
if (item is Series rseries)
{
foreach (Season season in rseries.Children)
{
season.OfficialRating = request.OfficialRating;
season.CustomRating = request.CustomRating;
+ season.Tags = season.Tags.Concat(addedTags).Except(removedTags).Distinct().ToArray();
season.OnMetadataChanged();
await season.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
@@ -289,6 +294,7 @@ public class ItemUpdateController : BaseJellyfinApiController
{
ep.OfficialRating = request.OfficialRating;
ep.CustomRating = request.CustomRating;
+ ep.Tags = ep.Tags.Concat(addedTags).Except(removedTags).Distinct().ToArray();
ep.OnMetadataChanged();
await ep.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
}
@@ -300,6 +306,7 @@ public class ItemUpdateController : BaseJellyfinApiController
{
ep.OfficialRating = request.OfficialRating;
ep.CustomRating = request.CustomRating;
+ ep.Tags = ep.Tags.Concat(addedTags).Except(removedTags).Distinct().ToArray();
ep.OnMetadataChanged();
await ep.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
}
@@ -310,6 +317,7 @@ public class ItemUpdateController : BaseJellyfinApiController
{
track.OfficialRating = request.OfficialRating;
track.CustomRating = request.CustomRating;
+ track.Tags = track.Tags.Concat(addedTags).Except(removedTags).Distinct().ToArray();
track.OnMetadataChanged();
await track.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
}
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 377526729..7650b861f 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -503,6 +503,7 @@ public class ItemsController : BaseJellyfinApiController
}
}
+ query.Parent = null;
result = folder.GetItems(query);
}
else
diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs
index c6dbea5e2..8d2a738d4 100644
--- a/Jellyfin.Api/Controllers/PlaylistsController.cs
+++ b/Jellyfin.Api/Controllers/PlaylistsController.cs
@@ -64,6 +64,7 @@ public class PlaylistsController : BaseJellyfinApiController
/// <param name="userId">The user id.</param>
/// <param name="mediaType">The media type.</param>
/// <param name="createPlaylistRequest">The create playlist payload.</param>
+ /// <response code="200">Playlist created.</response>
/// <returns>
/// A <see cref="Task" /> that represents the asynchronous operation to create a playlist.
/// The task result contains an <see cref="OkResult"/> indicating success.
@@ -167,6 +168,8 @@ public class PlaylistsController : BaseJellyfinApiController
/// <response code="404">Playlist not found.</response>
/// <returns>The original playlist items.</returns>
[HttpGet("{playlistId}/Items")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<QueryResult<BaseItemDto>> GetPlaylistItems(
[FromRoute, Required] Guid playlistId,
[FromQuery, Required] Guid userId,
@@ -189,9 +192,7 @@ public class PlaylistsController : BaseJellyfinApiController
: _userManager.GetUserById(userId);
var items = playlist.GetManageableItems().ToArray();
-
var count = items.Length;
-
if (startIndex.HasValue)
{
items = items.Skip(startIndex.Value).ToArray();
@@ -207,7 +208,6 @@ public class PlaylistsController : BaseJellyfinApiController
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
-
for (int index = 0; index < dtos.Count; index++)
{
dtos[index].PlaylistItemId = items[index].Item1.Id;
diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs
index aab390d1f..1098733b2 100644
--- a/Jellyfin.Api/Controllers/StartupController.cs
+++ b/Jellyfin.Api/Controllers/StartupController.cs
@@ -131,6 +131,10 @@ public class StartupController : BaseJellyfinApiController
public async Task<ActionResult> UpdateStartupUser([FromBody] StartupUserDto startupUserDto)
{
var user = _userManager.Users.First();
+ if (string.IsNullOrWhiteSpace(startupUserDto.Password))
+ {
+ return BadRequest("Password must not be empty");
+ }
if (startupUserDto.Name is not null)
{
diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs
index 4ab705f40..9ed69f420 100644
--- a/Jellyfin.Api/Controllers/SystemController.cs
+++ b/Jellyfin.Api/Controllers/SystemController.cs
@@ -59,10 +59,12 @@ public class SystemController : BaseJellyfinApiController
/// Gets information about the server.
/// </summary>
/// <response code="200">Information retrieved.</response>
+ /// <response code="403">User does not have permission to retrieve information.</response>
/// <returns>A <see cref="SystemInfo"/> with info about the system.</returns>
[HttpGet("Info")]
[Authorize(Policy = Policies.FirstTimeSetupOrIgnoreParentalControl)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
public ActionResult<SystemInfo> GetSystemInfo()
{
return _appHost.GetSystemInfo(Request);
@@ -97,10 +99,12 @@ public class SystemController : BaseJellyfinApiController
/// Restarts the application.
/// </summary>
/// <response code="204">Server restarted.</response>
+ /// <response code="403">User does not have permission to restart server.</response>
/// <returns>No content. Server restarted.</returns>
[HttpPost("Restart")]
[Authorize(Policy = Policies.LocalAccessOrRequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
public ActionResult RestartApplication()
{
Task.Run(async () =>
@@ -115,10 +119,12 @@ public class SystemController : BaseJellyfinApiController
/// Shuts down the application.
/// </summary>
/// <response code="204">Server shut down.</response>
+ /// <response code="403">User does not have permission to shutdown server.</response>
/// <returns>No content. Server shut down.</returns>
[HttpPost("Shutdown")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
public ActionResult ShutdownApplication()
{
Task.Run(async () =>
@@ -133,10 +139,12 @@ public class SystemController : BaseJellyfinApiController
/// Gets a list of available server log files.
/// </summary>
/// <response code="200">Information retrieved.</response>
+ /// <response code="403">User does not have permission to get server logs.</response>
/// <returns>An array of <see cref="LogFile"/> with the available log files.</returns>
[HttpGet("Logs")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
public ActionResult<LogFile[]> GetServerLogs()
{
IEnumerable<FileSystemMetadata> files;
@@ -170,10 +178,12 @@ public class SystemController : BaseJellyfinApiController
/// Gets information about the request endpoint.
/// </summary>
/// <response code="200">Information retrieved.</response>
+ /// <response code="403">User does not have permission to get endpoint information.</response>
/// <returns><see cref="EndPointInfo"/> with information about the endpoint.</returns>
[HttpGet("Endpoint")]
[Authorize]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
public ActionResult<EndPointInfo> GetEndpointInfo()
{
return new EndPointInfo
@@ -188,10 +198,12 @@ public class SystemController : BaseJellyfinApiController
/// </summary>
/// <param name="name">The name of the log file to get.</param>
/// <response code="200">Log file retrieved.</response>
+ /// <response code="403">User does not have permission to get log files.</response>
/// <returns>The log file.</returns>
[HttpGet("Logs/Log")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesFile(MediaTypeNames.Text.Plain)]
public ActionResult GetLogFile([FromQuery, Required] string name)
{
diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs
index e49528867..530bd9603 100644
--- a/Jellyfin.Api/Controllers/UserController.cs
+++ b/Jellyfin.Api/Controllers/UserController.cs
@@ -323,36 +323,16 @@ public class UserController : BaseJellyfinApiController
/// <response code="404">User not found.</response>
/// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="ForbidResult"/> or a <see cref="NotFoundResult"/> on failure.</returns>
[HttpPost("{userId}/EasyPassword")]
+ [Obsolete("Use Quick Connect instead")]
[Authorize]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task<ActionResult> UpdateUserEasyPassword(
+ public ActionResult UpdateUserEasyPassword(
[FromRoute, Required] Guid userId,
[FromBody, Required] UpdateUserEasyPassword request)
{
- if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
- {
- return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the easy password.");
- }
-
- var user = _userManager.GetUserById(userId);
-
- if (user is null)
- {
- return NotFound("User not found");
- }
-
- if (request.ResetPassword)
- {
- await _userManager.ResetEasyPassword(user).ConfigureAwait(false);
- }
- else
- {
- await _userManager.ChangeEasyPassword(user, request.NewPw ?? string.Empty, request.NewPassword ?? string.Empty).ConfigureAwait(false);
- }
-
- return NoContent();
+ return Forbid();
}
/// <summary>