Add clearer exceptions, warnings and docs
This commit is contained in:
parent
fdb0c3a1df
commit
fef35d0505
|
@ -30,6 +30,9 @@ namespace Emby.Server.Implementations.Cryptography
|
||||||
|
|
||||||
private bool _disposed = false;
|
private bool _disposed = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CryptographyProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
public CryptographyProvider()
|
public CryptographyProvider()
|
||||||
{
|
{
|
||||||
// FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto
|
// FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto
|
||||||
|
@ -59,12 +62,6 @@ namespace Emby.Server.Implementations.Cryptography
|
||||||
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
|
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ComputeHash(string hashMethod, byte[] bytes)
|
|
||||||
=> ComputeHash(hashMethod, bytes, Array.Empty<byte>());
|
|
||||||
|
|
||||||
public byte[] ComputeHashWithDefaultMethod(byte[] bytes)
|
|
||||||
=> ComputeHash(DefaultHashMethod, bytes);
|
|
||||||
|
|
||||||
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
|
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
|
||||||
{
|
{
|
||||||
if (hashMethod == DefaultHashMethod)
|
if (hashMethod == DefaultHashMethod)
|
||||||
|
@ -90,7 +87,6 @@ namespace Emby.Server.Implementations.Cryptography
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
|
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
|
public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
|
||||||
|
|
|
@ -59,7 +59,10 @@ namespace Emby.Server.Implementations.Library
|
||||||
if (_cryptographyProvider.GetSupportedHashMethods().Contains(readyHash.Id)
|
if (_cryptographyProvider.GetSupportedHashMethods().Contains(readyHash.Id)
|
||||||
|| _cryptographyProvider.DefaultHashMethod == readyHash.Id)
|
|| _cryptographyProvider.DefaultHashMethod == readyHash.Id)
|
||||||
{
|
{
|
||||||
byte[] calculatedHash = _cryptographyProvider.ComputeHash(readyHash.Id, passwordbytes, readyHash.Salt);
|
byte[] calculatedHash = _cryptographyProvider.ComputeHash(
|
||||||
|
readyHash.Id,
|
||||||
|
passwordbytes,
|
||||||
|
readyHash.Salt);
|
||||||
|
|
||||||
if (calculatedHash.SequenceEqual(readyHash.Hash))
|
if (calculatedHash.SequenceEqual(readyHash.Hash))
|
||||||
{
|
{
|
||||||
|
|
|
@ -179,12 +179,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
_defaultPasswordResetProvider = passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
|
_defaultPasswordResetProvider = passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Gets a User by Id.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The id.</param>
|
|
||||||
/// <returns>User.</returns>
|
|
||||||
/// <exception cref="ArgumentException"></exception>
|
|
||||||
public User GetUserById(Guid id)
|
public User GetUserById(Guid id)
|
||||||
{
|
{
|
||||||
if (id == Guid.Empty)
|
if (id == Guid.Empty)
|
||||||
|
@ -196,11 +191,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// Gets the user by identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identifier.</param>
|
|
||||||
/// <returns>User.</returns>
|
|
||||||
public User GetUserById(string id)
|
public User GetUserById(string id)
|
||||||
=> GetUserById(new Guid(id));
|
=> GetUserById(new Guid(id));
|
||||||
|
|
||||||
|
@ -428,7 +419,6 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
var authenticationResult = provider is IRequiresResolvedUser requiresResolvedUser
|
var authenticationResult = provider is IRequiresResolvedUser requiresResolvedUser
|
||||||
? await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false)
|
? await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false)
|
||||||
: await provider.Authenticate(username, password).ConfigureAwait(false);
|
: await provider.Authenticate(username, password).ConfigureAwait(false);
|
||||||
|
@ -538,6 +528,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
defaultName = "MyJellyfinUser";
|
defaultName = "MyJellyfinUser";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogWarning("No users, creating one with username {UserName}", defaultName);
|
||||||
|
|
||||||
var name = MakeValidUsername(defaultName);
|
var name = MakeValidUsername(defaultName);
|
||||||
|
|
||||||
var user = InstantiateNewUser(name);
|
var user = InstantiateNewUser(name);
|
||||||
|
@ -601,7 +593,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions
|
// Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions
|
||||||
_logger.LogError(ex, "Error generating PrimaryImageAspectRatio for {user}", user.Name);
|
_logger.LogError(ex, "Error generating PrimaryImageAspectRatio for {User}", user.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,7 +617,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error getting {imageType} image info for {imagePath}", image.Type, image.Path);
|
_logger.LogError(ex, "Error getting {ImageType} image info for {ImagePath}", image.Type, image.Path);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,11 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
var user = _userManager.GetUserById(query.UserId);
|
var user = _userManager.GetUserById(query.UserId);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("User Id does not exists.", nameof(query));
|
||||||
|
}
|
||||||
|
|
||||||
var folders = _libraryManager.GetUserRootFolder()
|
var folders = _libraryManager.GetUserRootFolder()
|
||||||
.GetChildren(user, true)
|
.GetChildren(user, true)
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
|
@ -54,7 +59,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
foreach (var folder in folders)
|
foreach (var folder in folders)
|
||||||
{
|
{
|
||||||
var collectionFolder = folder as ICollectionFolder;
|
var collectionFolder = folder as ICollectionFolder;
|
||||||
var folderViewType = collectionFolder == null ? null : collectionFolder.CollectionType;
|
var folderViewType = collectionFolder?.CollectionType;
|
||||||
|
|
||||||
if (UserView.IsUserSpecific(folder))
|
if (UserView.IsUserSpecific(folder))
|
||||||
{
|
{
|
||||||
|
@ -130,17 +135,12 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
var index = orders.IndexOf(i.Id.ToString("N", CultureInfo.InvariantCulture));
|
var index = orders.IndexOf(i.Id.ToString("N", CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
if (index == -1)
|
if (index == -1
|
||||||
{
|
&& i is UserView view
|
||||||
var view = i as UserView;
|
&& view.DisplayParentId != Guid.Empty)
|
||||||
if (view != null)
|
|
||||||
{
|
|
||||||
if (!view.DisplayParentId.Equals(Guid.Empty))
|
|
||||||
{
|
{
|
||||||
index = orders.IndexOf(view.DisplayParentId.ToString("N", CultureInfo.InvariantCulture));
|
index = orders.IndexOf(view.DisplayParentId.ToString("N", CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return index == -1 ? int.MaxValue : index;
|
return index == -1 ? int.MaxValue : index;
|
||||||
})
|
})
|
||||||
|
|
|
@ -1388,29 +1388,30 @@ namespace Emby.Server.Implementations.Session
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
// TODO: Move this to userManager?
|
// TODO: Move this to userManager?
|
||||||
if (!string.IsNullOrEmpty(request.DeviceId))
|
if (!string.IsNullOrEmpty(request.DeviceId)
|
||||||
{
|
&& !_deviceManager.CanAccessDevice(user, request.DeviceId))
|
||||||
if (!_deviceManager.CanAccessDevice(user, request.DeviceId))
|
|
||||||
{
|
{
|
||||||
throw new SecurityException("User is not allowed access from this device.");
|
throw new SecurityException("User is not allowed access from this device.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (enforcePassword)
|
if (enforcePassword)
|
||||||
{
|
{
|
||||||
var result = await _userManager.AuthenticateUser(request.Username, request.Password, request.PasswordSha1, request.RemoteEndPoint, true).ConfigureAwait(false);
|
user = await _userManager.AuthenticateUser(
|
||||||
|
request.Username,
|
||||||
|
request.Password,
|
||||||
|
request.PasswordSha1,
|
||||||
|
request.RemoteEndPoint,
|
||||||
|
true).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (result == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
AuthenticationFailed?.Invoke(this, new GenericEventArgs<AuthenticationRequest>(request));
|
AuthenticationFailed?.Invoke(this, new GenericEventArgs<AuthenticationRequest>(request));
|
||||||
|
|
||||||
throw new SecurityException("Invalid user or password entered.");
|
throw new SecurityException("Invalid user or password entered.");
|
||||||
}
|
}
|
||||||
|
|
||||||
user = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
|
var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
|
||||||
|
|
||||||
var session = LogSessionActivity(
|
var session = LogSessionActivity(
|
||||||
|
|
|
@ -10,6 +10,7 @@ using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Library;
|
using MediaBrowser.Model.Library;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.UserLibrary
|
namespace MediaBrowser.Api.UserLibrary
|
||||||
{
|
{
|
||||||
|
@ -49,7 +50,12 @@ namespace MediaBrowser.Api.UserLibrary
|
||||||
private readonly IAuthorizationContext _authContext;
|
private readonly IAuthorizationContext _authContext;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
|
||||||
public UserViewsService(IUserManager userManager, IUserViewManager userViewManager, IDtoService dtoService, IAuthorizationContext authContext, ILibraryManager libraryManager)
|
public UserViewsService(
|
||||||
|
IUserManager userManager,
|
||||||
|
IUserViewManager userViewManager,
|
||||||
|
IDtoService dtoService,
|
||||||
|
IAuthorizationContext authContext,
|
||||||
|
ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_userViewManager = userViewManager;
|
_userViewManager = userViewManager;
|
||||||
|
|
|
@ -61,13 +61,13 @@ namespace MediaBrowser.Common.Cryptography
|
||||||
/// <value>Return the hashed password.</value>
|
/// <value>Return the hashed password.</value>
|
||||||
public byte[] Hash { get; }
|
public byte[] Hash { get; }
|
||||||
|
|
||||||
public static PasswordHash Parse(string storageString)
|
public static PasswordHash Parse(string hashString)
|
||||||
{
|
{
|
||||||
string[] splitted = storageString.Split('$');
|
string[] splitted = hashString.Split('$');
|
||||||
// The string should at least contain the hash function and the hash itself
|
// The string should at least contain the hash function and the hash itself
|
||||||
if (splitted.Length < 3)
|
if (splitted.Length < 3)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("String doesn't contain enough segments", nameof(storageString));
|
throw new ArgumentException("String doesn't contain enough segments", nameof(hashString));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start at 1, the first index shouldn't contain any data
|
// Start at 1, the first index shouldn't contain any data
|
||||||
|
|
|
@ -1152,6 +1152,11 @@ namespace MediaBrowser.Controller.Entities
|
||||||
|
|
||||||
public List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
public List<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
{
|
{
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
}
|
||||||
|
|
||||||
return GetChildren(user, includeLinkedChildren, null);
|
return GetChildren(user, includeLinkedChildren, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,7 +1168,10 @@ namespace MediaBrowser.Controller.Entities
|
||||||
}
|
}
|
||||||
|
|
||||||
//the true root should return our users root folder children
|
//the true root should return our users root folder children
|
||||||
if (IsPhysicalRoot) return LibraryManager.GetUserRootFolder().GetChildren(user, includeLinkedChildren);
|
if (IsPhysicalRoot)
|
||||||
|
{
|
||||||
|
return LibraryManager.GetUserRootFolder().GetChildren(user, includeLinkedChildren);
|
||||||
|
}
|
||||||
|
|
||||||
var result = new Dictionary<Guid, BaseItem>();
|
var result = new Dictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
|
|
|
@ -39,17 +39,21 @@ namespace MediaBrowser.Controller.Library
|
||||||
event EventHandler<GenericEventArgs<User>> UserDeleted;
|
event EventHandler<GenericEventArgs<User>> UserDeleted;
|
||||||
|
|
||||||
event EventHandler<GenericEventArgs<User>> UserCreated;
|
event EventHandler<GenericEventArgs<User>> UserCreated;
|
||||||
|
|
||||||
event EventHandler<GenericEventArgs<User>> UserPolicyUpdated;
|
event EventHandler<GenericEventArgs<User>> UserPolicyUpdated;
|
||||||
|
|
||||||
event EventHandler<GenericEventArgs<User>> UserConfigurationUpdated;
|
event EventHandler<GenericEventArgs<User>> UserConfigurationUpdated;
|
||||||
|
|
||||||
event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
|
event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
|
||||||
|
|
||||||
event EventHandler<GenericEventArgs<User>> UserLockedOut;
|
event EventHandler<GenericEventArgs<User>> UserLockedOut;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a User by Id
|
/// Gets a User by Id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The id.</param>
|
/// <param name="id">The id.</param>
|
||||||
/// <returns>User.</returns>
|
/// <returns>The user with the specified Id, or <c>null</c> id the user doesn't exist.</returns>
|
||||||
/// <exception cref="ArgumentNullException"></exception>
|
/// <exception cref="ArgumentException"><c>id</c> is an empty Guid.</exception>
|
||||||
User GetUserById(Guid id);
|
User GetUserById(Guid id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -8,10 +8,6 @@ namespace MediaBrowser.Model.Cryptography
|
||||||
|
|
||||||
IEnumerable<string> GetSupportedHashMethods();
|
IEnumerable<string> GetSupportedHashMethods();
|
||||||
|
|
||||||
byte[] ComputeHash(string HashMethod, byte[] bytes);
|
|
||||||
|
|
||||||
byte[] ComputeHashWithDefaultMethod(byte[] bytes);
|
|
||||||
|
|
||||||
byte[] ComputeHash(string HashMethod, byte[] bytes, byte[] salt);
|
byte[] ComputeHash(string HashMethod, byte[] bytes, byte[] salt);
|
||||||
|
|
||||||
byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt);
|
byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user