aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs13
-rw-r--r--Jellyfin.Data/Entities/User.cs5
-rw-r--r--Jellyfin.Server.Implementations/Users/UserManager.cs2
-rw-r--r--MediaBrowser.Model/Users/UserPolicy.cs6
4 files changed, 26 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index e42d47853..5903d395a 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -1484,6 +1484,19 @@ namespace Emby.Server.Implementations.Session
throw new SecurityException("User is not allowed access from this device.");
}
+ var sessionsCount = Sessions.Where(i => string.Equals(i.UserId, user.Id)).ToList().Count;
+ int maxActiveSessions = user.MaxActiveSessions;
+ _logger.LogDebug("Current/Max sessions for user {User}: {Sessions}/{Max}", user.Username, sessionsCount, maxActiveSessions);
+ if (maxActiveSessions >= 0 && sessionsCount >= maxActiveSessions)
+ {
+ throw new SecurityException(
+ "User {User} is at their maximum number of sessions ({Sessions}/{Max}).",
+ user.Username,
+ sessionsCount,
+ maxActiveSessions
+ )
+ }
+
var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
var session = LogSessionActivity(
diff --git a/Jellyfin.Data/Entities/User.cs b/Jellyfin.Data/Entities/User.cs
index f7ab57a1b..daa4de0b5 100644
--- a/Jellyfin.Data/Entities/User.cs
+++ b/Jellyfin.Data/Entities/User.cs
@@ -189,6 +189,11 @@ namespace Jellyfin.Data.Entities
public int? LoginAttemptsBeforeLockout { get; set; }
/// <summary>
+ /// Gets or sets the maximum number of active sessions the user can have at once.
+ /// </summary>
+ public int? MaxActiveSessions { get; set; }
+
+ /// <summary>
/// Gets or sets the subtitle mode.
/// </summary>
/// <remarks>
diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs
index 8f04baa08..43698efb7 100644
--- a/Jellyfin.Server.Implementations/Users/UserManager.cs
+++ b/Jellyfin.Server.Implementations/Users/UserManager.cs
@@ -379,6 +379,7 @@ namespace Jellyfin.Server.Implementations.Users
PasswordResetProviderId = user.PasswordResetProviderId,
InvalidLoginAttemptCount = user.InvalidLoginAttemptCount,
LoginAttemptsBeforeLockout = user.LoginAttemptsBeforeLockout ?? -1,
+ MaxActiveSessions = user.MaxActiveSessions ?? -1,
IsAdministrator = user.HasPermission(PermissionKind.IsAdministrator),
IsHidden = user.HasPermission(PermissionKind.IsHidden),
IsDisabled = user.HasPermission(PermissionKind.IsDisabled),
@@ -701,6 +702,7 @@ namespace Jellyfin.Server.Implementations.Users
user.PasswordResetProviderId = policy.PasswordResetProviderId;
user.InvalidLoginAttemptCount = policy.InvalidLoginAttemptCount;
user.LoginAttemptsBeforeLockout = maxLoginAttempts;
+ user.MaxActiveSessions = policy.MaxActiveSessions;
user.SyncPlayAccess = policy.SyncPlayAccess;
user.SetPermission(PermissionKind.IsAdministrator, policy.IsAdministrator);
user.SetPermission(PermissionKind.IsHidden, policy.IsHidden);
diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs
index a1f01f7e8..53dcb6bbd 100644
--- a/MediaBrowser.Model/Users/UserPolicy.cs
+++ b/MediaBrowser.Model/Users/UserPolicy.cs
@@ -92,6 +92,10 @@ namespace MediaBrowser.Model.Users
public int LoginAttemptsBeforeLockout { get; set; }
+ public int ActiveSessionCount { get; set; }
+
+ public int MaxActiveSessions { get; set; }
+
public bool EnablePublicSharing { get; set; }
public Guid[] BlockedMediaFolders { get; set; }
@@ -144,6 +148,8 @@ namespace MediaBrowser.Model.Users
LoginAttemptsBeforeLockout = -1;
+ MaxActiveSessions = -1;
+
EnableAllChannels = true;
EnabledChannels = Array.Empty<Guid>();