Browse Source

Add active session tracking

Adds a flag for a maximum number of user sessions, as well as an
authentication check to ensure that the user is not above this level.
Joshua M. Boniface 4 năm trước cách đây
mục cha
commit
5a7dda337f

+ 13 - 0
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(

+ 5 - 0
Jellyfin.Data/Entities/User.cs

@@ -188,6 +188,11 @@ namespace Jellyfin.Data.Entities
         /// </summary>
         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>

+ 2 - 0
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);

+ 6 - 0
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>();