aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api')
-rw-r--r--Jellyfin.Api/Controllers/ImageController.cs14
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs8
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs14
-rw-r--r--Jellyfin.Api/Controllers/LiveTvController.cs2
-rw-r--r--Jellyfin.Api/Controllers/MusicGenresController.cs5
-rw-r--r--Jellyfin.Api/Controllers/PlaystateController.cs20
-rw-r--r--Jellyfin.Api/Controllers/SessionController.cs4
-rw-r--r--Jellyfin.Api/Controllers/UserController.cs25
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs41
-rw-r--r--Jellyfin.Api/Controllers/VideosController.cs7
-rw-r--r--Jellyfin.Api/Helpers/MediaInfoHelper.cs2
-rw-r--r--Jellyfin.Api/Helpers/RequestHelpers.cs7
-rw-r--r--Jellyfin.Api/Models/UserDtos/CreateUserByName.cs7
-rw-r--r--Jellyfin.Api/Models/UserDtos/ForgotPasswordDto.cs2
-rw-r--r--Jellyfin.Api/Models/UserDtos/ForgotPasswordPinDto.cs2
15 files changed, 143 insertions, 17 deletions
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index b2adb6a2d..aecdf00dc 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -99,12 +99,17 @@ public class ImageController : BaseJellyfinApiController
[FromRoute, Required] ImageType imageType,
[FromQuery] int? index = null)
{
+ var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true))
{
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image.");
}
- var user = _userManager.GetUserById(userId);
var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
await using (memoryStream.ConfigureAwait(false))
{
@@ -148,12 +153,17 @@ public class ImageController : BaseJellyfinApiController
[FromRoute, Required] ImageType imageType,
[FromRoute] int index)
{
+ var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true))
{
return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image.");
}
- var user = _userManager.GetUserById(userId);
var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
await using (memoryStream.ConfigureAwait(false))
{
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 97922d5db..99366e80c 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -5,6 +5,7 @@ using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -240,7 +241,7 @@ public class ItemsController : BaseJellyfinApiController
var isApiKey = User.GetIsApiKey();
// if api key is used (auth.IsApiKey == true), then `user` will be null throughout this method
var user = !isApiKey && userId.HasValue && !userId.Value.Equals(default)
- ? _userManager.GetUserById(userId.Value)
+ ? _userManager.GetUserById(userId.Value) ?? throw new ResourceNotFoundException()
: null;
// beyond this point, we're either using an api key or we have a valid user
@@ -814,6 +815,11 @@ public class ItemsController : BaseJellyfinApiController
[FromQuery] bool excludeActiveSessions = false)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
var parentIdGuid = parentId ?? Guid.Empty;
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(User)
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index e1ad87412..e8b68c7c3 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -283,6 +283,11 @@ public class LibraryController : BaseJellyfinApiController
userId,
inheritFromParent);
+ if (themeSongs.Result is NotFoundObjectResult || themeVideos.Result is NotFoundObjectResult)
+ {
+ return NotFound();
+ }
+
return new AllThemeMediaResult
{
ThemeSongsResult = themeSongs?.Value,
@@ -452,6 +457,10 @@ public class LibraryController : BaseJellyfinApiController
if (user is not null)
{
parent = TranslateParentItem(parent, user);
+ if (parent is null)
+ {
+ break;
+ }
}
baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
@@ -672,6 +681,11 @@ public class LibraryController : BaseJellyfinApiController
: _libraryManager.GetUserRootFolder())
: _libraryManager.GetItemById(itemId);
+ if (item is null)
+ {
+ return NotFound();
+ }
+
if (item is Episode || (item is IItemByName && item is not MusicArtist))
{
return new QueryResult<BaseItemDto>();
diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs
index c1f5d74cd..3425c8589 100644
--- a/Jellyfin.Api/Controllers/LiveTvController.cs
+++ b/Jellyfin.Api/Controllers/LiveTvController.cs
@@ -1210,7 +1210,7 @@ public class LiveTvController : BaseJellyfinApiController
private async Task AssertUserCanManageLiveTv()
{
- var user = _userManager.GetUserById(User.GetUserId());
+ var user = _userManager.GetUserById(User.GetUserId()) ?? throw new ResourceNotFoundException();
var session = await _sessionManager.LogSessionActivity(
User.GetClient(),
User.GetVersion(),
diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs
index da1a6e832..3db1d89c1 100644
--- a/Jellyfin.Api/Controllers/MusicGenresController.cs
+++ b/Jellyfin.Api/Controllers/MusicGenresController.cs
@@ -157,6 +157,11 @@ public class MusicGenresController : BaseJellyfinApiController
item = _libraryManager.GetMusicGenre(genreName);
}
+ if (item is null)
+ {
+ return NotFound();
+ }
+
if (userId.HasValue && !userId.Value.Equals(default))
{
var user = _userManager.GetUserById(userId.Value);
diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs
index 11f3ddbb0..8ad553bcb 100644
--- a/Jellyfin.Api/Controllers/PlaystateController.cs
+++ b/Jellyfin.Api/Controllers/PlaystateController.cs
@@ -76,6 +76,11 @@ public class PlaystateController : BaseJellyfinApiController
[FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var item = _libraryManager.GetItemById(itemId);
@@ -88,6 +93,11 @@ public class PlaystateController : BaseJellyfinApiController
foreach (var additionalUserInfo in session.AdditionalUsers)
{
var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId);
+ if (additionalUser is null)
+ {
+ return NotFound();
+ }
+
UpdatePlayedStatus(additionalUser, item, true, datePlayed);
}
@@ -108,6 +118,11 @@ public class PlaystateController : BaseJellyfinApiController
public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var item = _libraryManager.GetItemById(itemId);
@@ -120,6 +135,11 @@ public class PlaystateController : BaseJellyfinApiController
foreach (var additionalUserInfo in session.AdditionalUsers)
{
var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId);
+ if (additionalUser is null)
+ {
+ return NotFound();
+ }
+
UpdatePlayedStatus(additionalUser, item, false, null);
}
diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs
index bae8e0a49..e93456de6 100644
--- a/Jellyfin.Api/Controllers/SessionController.cs
+++ b/Jellyfin.Api/Controllers/SessionController.cs
@@ -75,6 +75,10 @@ public class SessionController : BaseJellyfinApiController
result = result.Where(i => i.SupportsRemoteControl);
var user = _userManager.GetUserById(controllableByUserId.Value);
+ if (user is null)
+ {
+ return NotFound();
+ }
if (!user.HasPermission(PermissionKind.EnableRemoteControlOfOtherUsers))
{
diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs
index d9ea96f2d..b0973b8a1 100644
--- a/Jellyfin.Api/Controllers/UserController.cs
+++ b/Jellyfin.Api/Controllers/UserController.cs
@@ -147,6 +147,11 @@ public class UserController : BaseJellyfinApiController
public async Task<ActionResult> DeleteUser([FromRoute, Required] Guid userId)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
await _sessionManager.RevokeUserTokens(user.Id, null).ConfigureAwait(false);
await _userManager.DeleteUserAsync(userId).ConfigureAwait(false);
return NoContent();
@@ -281,8 +286,8 @@ public class UserController : BaseJellyfinApiController
{
var success = await _userManager.AuthenticateUser(
user.Username,
- request.CurrentPw,
- request.CurrentPw,
+ request.CurrentPw ?? string.Empty,
+ request.CurrentPw ?? string.Empty,
HttpContext.GetNormalizedRemoteIp().ToString(),
false).ConfigureAwait(false);
@@ -292,7 +297,7 @@ public class UserController : BaseJellyfinApiController
}
}
- await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false);
+ await _userManager.ChangePassword(user, request.NewPw ?? string.Empty).ConfigureAwait(false);
var currentToken = User.GetToken();
@@ -338,7 +343,7 @@ public class UserController : BaseJellyfinApiController
}
else
{
- await _userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword).ConfigureAwait(false);
+ await _userManager.ChangeEasyPassword(user, request.NewPw ?? string.Empty, request.NewPassword ?? string.Empty).ConfigureAwait(false);
}
return NoContent();
@@ -362,13 +367,17 @@ public class UserController : BaseJellyfinApiController
[FromRoute, Required] Guid userId,
[FromBody, Required] UserDto updateUser)
{
+ var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true))
{
return StatusCode(StatusCodes.Status403Forbidden, "User update not allowed.");
}
- var user = _userManager.GetUserById(userId);
-
if (!string.Equals(user.Username, updateUser.Name, StringComparison.Ordinal))
{
await _userManager.RenameUser(user, updateUser.Name).ConfigureAwait(false);
@@ -398,6 +407,10 @@ public class UserController : BaseJellyfinApiController
[FromBody, Required] UserPolicy newPolicy)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
// If removing admin access
if (!newPolicy.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator))
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index 93312b817..1233995b4 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -78,10 +78,18 @@ public class UserLibraryController : BaseJellyfinApiController
public async Task<ActionResult<BaseItemDto>> GetItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+ if (item is null)
+ {
+ return NotFound();
+ }
await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
@@ -101,6 +109,11 @@ public class UserLibraryController : BaseJellyfinApiController
public ActionResult<BaseItemDto> GetRootFolder([FromRoute, Required] Guid userId)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
+
var item = _libraryManager.GetUserRootFolder();
var dtoOptions = new DtoOptions().AddClientFields(User);
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
@@ -118,10 +131,18 @@ public class UserLibraryController : BaseJellyfinApiController
public async Task<ActionResult<QueryResult<BaseItemDto>>> GetIntros([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+ if (item is null)
+ {
+ return NotFound();
+ }
var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
var dtoOptions = new DtoOptions().AddClientFields(User);
@@ -199,10 +220,18 @@ public class UserLibraryController : BaseJellyfinApiController
public ActionResult<IEnumerable<BaseItemDto>> GetLocalTrailers([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+ if (item is null)
+ {
+ return NotFound();
+ }
var dtoOptions = new DtoOptions().AddClientFields(User);
@@ -229,10 +258,18 @@ public class UserLibraryController : BaseJellyfinApiController
public ActionResult<IEnumerable<BaseItemDto>> GetSpecialFeatures([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
+ if (item is null)
+ {
+ return NotFound();
+ }
var dtoOptions = new DtoOptions().AddClientFields(User);
@@ -274,6 +311,10 @@ public class UserLibraryController : BaseJellyfinApiController
[FromQuery] bool groupItems = true)
{
var user = _userManager.GetUserById(userId);
+ if (user is null)
+ {
+ return NotFound();
+ }
if (!isPlayed.HasValue)
{
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index 929999196..3a61367f7 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -155,7 +155,12 @@ public class VideosController : BaseJellyfinApiController
if (video.LinkedAlternateVersions.Length == 0)
{
- video = (Video)_libraryManager.GetItemById(video.PrimaryVersionId);
+ video = (Video?)_libraryManager.GetItemById(video.PrimaryVersionId);
+ }
+
+ if (video is null)
+ {
+ return NotFound();
}
foreach (var link in video.GetLinkedAlternateVersions())
diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
index df37d96c6..5910d8073 100644
--- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs
+++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
@@ -200,7 +200,7 @@ public class MediaInfoHelper
options.SubtitleStreamIndex = subtitleStreamIndex;
}
- var user = _userManager.GetUserById(userId);
+ var user = _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException();
if (!enableDirectPlay)
{
diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs
index 3ce2b834d..0b7a4fa1a 100644
--- a/Jellyfin.Api/Helpers/RequestHelpers.cs
+++ b/Jellyfin.Api/Helpers/RequestHelpers.cs
@@ -81,6 +81,11 @@ public static class RequestHelpers
}
var user = userManager.GetUserById(userId);
+ if (user is null)
+ {
+ throw new ResourceNotFoundException();
+ }
+
return user.EnableUserPreferenceAccess;
}
@@ -98,7 +103,7 @@ public static class RequestHelpers
if (session is null)
{
- throw new ArgumentException("Session not found.");
+ throw new ResourceNotFoundException("Session not found.");
}
return session;
diff --git a/Jellyfin.Api/Models/UserDtos/CreateUserByName.cs b/Jellyfin.Api/Models/UserDtos/CreateUserByName.cs
index 0503c5d57..6b6d9682b 100644
--- a/Jellyfin.Api/Models/UserDtos/CreateUserByName.cs
+++ b/Jellyfin.Api/Models/UserDtos/CreateUserByName.cs
@@ -1,4 +1,6 @@
-namespace Jellyfin.Api.Models.UserDtos;
+using System.ComponentModel.DataAnnotations;
+
+namespace Jellyfin.Api.Models.UserDtos;
/// <summary>
/// The create user by name request body.
@@ -8,7 +10,8 @@ public class CreateUserByName
/// <summary>
/// Gets or sets the username.
/// </summary>
- public string? Name { get; set; }
+ [Required]
+ required public string Name { get; set; }
/// <summary>
/// Gets or sets the password.
diff --git a/Jellyfin.Api/Models/UserDtos/ForgotPasswordDto.cs b/Jellyfin.Api/Models/UserDtos/ForgotPasswordDto.cs
index ebe9297ea..a0631fd07 100644
--- a/Jellyfin.Api/Models/UserDtos/ForgotPasswordDto.cs
+++ b/Jellyfin.Api/Models/UserDtos/ForgotPasswordDto.cs
@@ -11,5 +11,5 @@ public class ForgotPasswordDto
/// Gets or sets the entered username to have its password reset.
/// </summary>
[Required]
- public string? EnteredUsername { get; set; }
+ required public string EnteredUsername { get; set; }
}
diff --git a/Jellyfin.Api/Models/UserDtos/ForgotPasswordPinDto.cs b/Jellyfin.Api/Models/UserDtos/ForgotPasswordPinDto.cs
index 2949efe29..79b8a5d63 100644
--- a/Jellyfin.Api/Models/UserDtos/ForgotPasswordPinDto.cs
+++ b/Jellyfin.Api/Models/UserDtos/ForgotPasswordPinDto.cs
@@ -11,5 +11,5 @@ public class ForgotPasswordPinDto
/// Gets or sets the entered pin to have the password reset.
/// </summary>
[Required]
- public string? Pin { get; set; }
+ required public string Pin { get; set; }
}