aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server.Implementations/Users/UserManager.cs
diff options
context:
space:
mode:
authorcrobibero <cody@robibe.ro>2020-06-22 20:23:06 -0600
committercrobibero <cody@robibe.ro>2020-06-22 20:23:06 -0600
commitf4d8e0e20cca81b68919ac8d242fa793612d8c85 (patch)
treefe995b8cde09125bebc7cd250693599c26faf2a4 /Jellyfin.Server.Implementations/Users/UserManager.cs
parent3d87c4c1b6bca920f444b4a16a99553d0ff6879e (diff)
parent0be10db5a5ea5f284b310e55ee572016a177decd (diff)
Merge remote-tracking branch 'upstream/master' into easypassword
Diffstat (limited to 'Jellyfin.Server.Implementations/Users/UserManager.cs')
-rw-r--r--Jellyfin.Server.Implementations/Users/UserManager.cs106
1 files changed, 80 insertions, 26 deletions
diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs
index 35ec78f5c..97ea03596 100644
--- a/Jellyfin.Server.Implementations/Users/UserManager.cs
+++ b/Jellyfin.Server.Implementations/Users/UserManager.cs
@@ -1,4 +1,5 @@
-#pragma warning disable CA1307
+#nullable enable
+#pragma warning disable CA1307
using System;
using System.Collections.Generic;
@@ -37,11 +38,11 @@ namespace Jellyfin.Server.Implementations.Users
private readonly IImageProcessor _imageProcessor;
private readonly ILogger<UserManager> _logger;
- private IAuthenticationProvider[] _authenticationProviders;
- private DefaultAuthenticationProvider _defaultAuthenticationProvider;
- private InvalidAuthProvider _invalidAuthProvider;
- private IPasswordResetProvider[] _passwordResetProviders;
- private DefaultPasswordResetProvider _defaultPasswordResetProvider;
+ private IAuthenticationProvider[] _authenticationProviders = null!;
+ private DefaultAuthenticationProvider _defaultAuthenticationProvider = null!;
+ private InvalidAuthProvider _invalidAuthProvider = null!;
+ private IPasswordResetProvider[] _passwordResetProviders = null!;
+ private DefaultPasswordResetProvider _defaultPasswordResetProvider = null!;
/// <summary>
/// Initializes a new instance of the <see cref="UserManager"/> class.
@@ -69,19 +70,19 @@ namespace Jellyfin.Server.Implementations.Users
}
/// <inheritdoc/>
- public event EventHandler<GenericEventArgs<User>> OnUserPasswordChanged;
+ public event EventHandler<GenericEventArgs<User>>? OnUserPasswordChanged;
/// <inheritdoc/>
- public event EventHandler<GenericEventArgs<User>> OnUserUpdated;
+ public event EventHandler<GenericEventArgs<User>>? OnUserUpdated;
/// <inheritdoc/>
- public event EventHandler<GenericEventArgs<User>> OnUserCreated;
+ public event EventHandler<GenericEventArgs<User>>? OnUserCreated;
/// <inheritdoc/>
- public event EventHandler<GenericEventArgs<User>> OnUserDeleted;
+ public event EventHandler<GenericEventArgs<User>>? OnUserDeleted;
/// <inheritdoc/>
- public event EventHandler<GenericEventArgs<User>> OnUserLockedOut;
+ public event EventHandler<GenericEventArgs<User>>? OnUserLockedOut;
/// <inheritdoc/>
public IEnumerable<User> Users => _dbProvider.CreateContext().Users;
@@ -90,7 +91,7 @@ namespace Jellyfin.Server.Implementations.Users
public IEnumerable<Guid> UsersIds => _dbProvider.CreateContext().Users.Select(u => u.Id);
/// <inheritdoc/>
- public User GetUserById(Guid id)
+ public User? GetUserById(Guid id)
{
if (id == Guid.Empty)
{
@@ -101,7 +102,7 @@ namespace Jellyfin.Server.Implementations.Users
}
/// <inheritdoc/>
- public User GetUserByName(string name)
+ public User? GetUserByName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
@@ -173,7 +174,7 @@ namespace Jellyfin.Server.Implementations.Users
var dbContext = _dbProvider.CreateContext();
// TODO: Remove after user item data is migrated.
- var max = dbContext.Users.Select(u => u.InternalId).Max();
+ var max = dbContext.Users.Any() ? dbContext.Users.Select(u => u.InternalId).Max() : 0;
var newUser = new User(
name,
@@ -260,7 +261,7 @@ namespace Jellyfin.Server.Implementations.Users
}
/// <inheritdoc/>
- public void ChangeEasyPassword(User user, string newPassword, string newPasswordSha1)
+ public void ChangeEasyPassword(User user, string newPassword, string? newPasswordSha1)
{
user.EasyPassword = _cryptoProvider.CreatePasswordHash(newPassword).ToString();
UpdateUser(user);
@@ -269,14 +270,17 @@ namespace Jellyfin.Server.Implementations.Users
}
/// <inheritdoc/>
- public UserDto GetUserDto(User user, string remoteEndPoint = null)
+ public UserDto GetUserDto(User user, string? remoteEndPoint = null)
{
+ var hasPassword = GetAuthenticationProvider(user).HasPassword(user);
return new UserDto
{
Name = user.Username,
Id = user.Id,
ServerId = _appHost.SystemId,
- HasPassword = user.Password != null,
+ HasPassword = hasPassword,
+ HasConfiguredPassword = hasPassword,
+ HasConfiguredEasyPassword = !string.IsNullOrEmpty(user.EasyPassword),
EnableAutoLogin = user.EnableAutoLogin,
LastLoginDate = user.LastLoginDate,
LastActivityDate = user.LastActivityDate,
@@ -303,7 +307,7 @@ namespace Jellyfin.Server.Implementations.Users
{
MaxParentalRating = user.MaxParentalAgeRating,
EnableUserPreferenceAccess = user.EnableUserPreferenceAccess,
- RemoteClientBitrateLimit = user.RemoteClientBitrateLimit ?? -1,
+ RemoteClientBitrateLimit = user.RemoteClientBitrateLimit ?? 0,
AuthenticationProviderId = user.AuthenticationProviderId,
PasswordResetProviderId = user.PasswordResetProviderId,
InvalidLoginAttemptCount = user.InvalidLoginAttemptCount,
@@ -335,13 +339,16 @@ namespace Jellyfin.Server.Implementations.Users
EnabledDevices = user.GetPreference(PreferenceKind.EnabledDevices),
EnabledFolders = user.GetPreference(PreferenceKind.EnabledFolders),
EnableContentDeletionFromFolders = user.GetPreference(PreferenceKind.EnableContentDeletionFromFolders),
- SyncPlayAccess = user.SyncPlayAccess
+ SyncPlayAccess = user.SyncPlayAccess,
+ BlockedChannels = user.GetPreference(PreferenceKind.BlockedChannels),
+ BlockedMediaFolders = user.GetPreference(PreferenceKind.BlockedMediaFolders),
+ BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems).Select(Enum.Parse<UnratedItem>).ToArray()
}
};
}
/// <inheritdoc/>
- public async Task<User> AuthenticateUser(
+ public async Task<User?> AuthenticateUser(
string username,
string password,
string passwordSha1,
@@ -356,7 +363,7 @@ namespace Jellyfin.Server.Implementations.Users
var user = Users.ToList().FirstOrDefault(i => string.Equals(username, i.Username, StringComparison.OrdinalIgnoreCase));
bool success;
- IAuthenticationProvider authenticationProvider;
+ IAuthenticationProvider? authenticationProvider;
if (user != null)
{
@@ -516,6 +523,39 @@ namespace Jellyfin.Server.Implementations.Users
_defaultPasswordResetProvider = _passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
}
+ /// <inheritdoc />
+ public void Initialize()
+ {
+ // TODO: Refactor the startup wizard so that it doesn't require a user to already exist.
+ var dbContext = _dbProvider.CreateContext();
+
+ if (dbContext.Users.Any())
+ {
+ return;
+ }
+
+ var defaultName = Environment.UserName;
+ if (string.IsNullOrWhiteSpace(defaultName))
+ {
+ defaultName = "MyJellyfinUser";
+ }
+
+ _logger.LogWarning("No users, creating one with username {UserName}", defaultName);
+
+ if (!IsValidUsername(defaultName))
+ {
+ throw new ArgumentException("Provided username is not valid!", defaultName);
+ }
+
+ var newUser = CreateUser(defaultName);
+ newUser.SetPermission(PermissionKind.IsAdministrator, true);
+ newUser.SetPermission(PermissionKind.EnableContentDeletion, true);
+ newUser.SetPermission(PermissionKind.EnableRemoteControlOfOtherUsers, true);
+
+ dbContext.Users.Update(newUser);
+ dbContext.SaveChanges();
+ }
+
/// <inheritdoc/>
public NameIdPair[] GetAuthenticationProviders()
{
@@ -577,6 +617,8 @@ namespace Jellyfin.Server.Implementations.Users
{
var dbContext = _dbProvider.CreateContext();
var user = dbContext.Users.Find(userId) ?? throw new ArgumentException("No user exists with given Id!");
+
+ // The default number of login attempts is 3, but for some god forsaken reason it's sent to the server as "0"
int? maxLoginAttempts = policy.LoginAttemptsBeforeLockout switch
{
-1 => null,
@@ -620,6 +662,10 @@ namespace Jellyfin.Server.Implementations.Users
user.AccessSchedules.Add(policyAccessSchedule);
}
+ // TODO: fix this at some point
+ user.SetPreference(
+ PreferenceKind.BlockUnratedItems,
+ policy.BlockUnratedItems?.Select(i => i.ToString()).ToArray() ?? Array.Empty<string>());
user.SetPreference(PreferenceKind.BlockedTags, policy.BlockedTags);
user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels);
user.SetPreference(PreferenceKind.EnabledDevices, policy.EnabledDevices);
@@ -630,6 +676,14 @@ namespace Jellyfin.Server.Implementations.Users
dbContext.SaveChanges();
}
+ /// <inheritdoc/>
+ public void ClearProfileImage(User user)
+ {
+ var dbContext = _dbProvider.CreateContext();
+ dbContext.Remove(user.ProfileImage);
+ dbContext.SaveChanges();
+ }
+
private static bool IsValidUsername(string name)
{
// This is some regex that matches only on unicode "word" characters, as well as -, _ and @
@@ -648,7 +702,7 @@ namespace Jellyfin.Server.Implementations.Users
return GetPasswordResetProviders(user)[0];
}
- private IList<IAuthenticationProvider> GetAuthenticationProviders(User user)
+ private IList<IAuthenticationProvider> GetAuthenticationProviders(User? user)
{
var authenticationProviderId = user?.AuthenticationProviderId;
@@ -698,14 +752,14 @@ namespace Jellyfin.Server.Implementations.Users
return providers;
}
- private async Task<(IAuthenticationProvider authenticationProvider, string username, bool success)> AuthenticateLocalUser(
+ private async Task<(IAuthenticationProvider? authenticationProvider, string username, bool success)> AuthenticateLocalUser(
string username,
string password,
- User user,
+ User? user,
string remoteEndPoint)
{
bool success = false;
- IAuthenticationProvider authenticationProvider = null;
+ IAuthenticationProvider? authenticationProvider = null;
foreach (var provider in GetAuthenticationProviders(user))
{
@@ -743,7 +797,7 @@ namespace Jellyfin.Server.Implementations.Users
IAuthenticationProvider provider,
string username,
string password,
- User resolvedUser)
+ User? resolvedUser)
{
try
{