diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-01-03 21:35:41 -0500 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-01-03 21:35:41 -0500 |
| commit | 135168b0e0640211aee5cda9285cffb184385e83 (patch) | |
| tree | ccbdd9a8a5299aa557b888919b1884e5705ed05e /MediaBrowser.Server.Implementations/Session | |
| parent | 6da42312441dcdad2fbbd831a219398371340b43 (diff) | |
support adding additional users to sessions
Diffstat (limited to 'MediaBrowser.Server.Implementations/Session')
| -rw-r--r-- | MediaBrowser.Server.Implementations/Session/SessionManager.cs | 236 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs | 6 |
2 files changed, 193 insertions, 49 deletions
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 37b695776..7a253b89b 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -39,6 +39,7 @@ namespace MediaBrowser.Server.Implementations.Session private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; + private readonly IUserManager _userManager; /// <summary> /// Gets or sets the configuration manager. @@ -75,13 +76,14 @@ namespace MediaBrowser.Server.Implementations.Session /// <param name="logger">The logger.</param> /// <param name="userRepository">The user repository.</param> /// <param name="libraryManager">The library manager.</param> - public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager) + public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager) { _userDataRepository = userDataRepository; _configurationManager = configurationManager; _logger = logger; _userRepository = userRepository; _libraryManager = libraryManager; + _userManager = userManager; } /// <summary> @@ -140,7 +142,10 @@ namespace MediaBrowser.Server.Implementations.Session var activityDate = DateTime.UtcNow; - var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, remoteEndPoint, user); + var userId = user == null ? (Guid?)null : user.Id; + var username = user == null ? null : user.Name; + + var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, remoteEndPoint, userId, username); session.LastActivityDate = activityDate; @@ -209,9 +214,10 @@ namespace MediaBrowser.Server.Implementations.Session /// <param name="deviceId">The device id.</param> /// <param name="deviceName">Name of the device.</param> /// <param name="remoteEndPoint">The remote end point.</param> - /// <param name="user">The user.</param> + /// <param name="userId">The user identifier.</param> + /// <param name="username">The username.</param> /// <returns>SessionInfo.</returns> - private SessionInfo GetSessionInfo(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user) + private SessionInfo GetSessionInfo(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Guid? userId, string username) { var key = clientType + deviceId + appVersion; @@ -224,9 +230,15 @@ namespace MediaBrowser.Server.Implementations.Session }); connection.DeviceName = deviceName; - connection.User = user; + connection.UserId = userId; + connection.UserName = username; connection.RemoteEndPoint = remoteEndPoint; + if (!userId.HasValue) + { + connection.AdditionalUsersPresent.Clear(); + } + if (connection.SessionController == null) { connection.SessionController = _sessionFactories @@ -237,6 +249,31 @@ namespace MediaBrowser.Server.Implementations.Session return connection; } + private List<User> GetUsers(SessionInfo session) + { + var users = new List<User>(); + + if (session.UserId.HasValue) + { + var user = _userManager.GetUserById(session.UserId.Value); + + if (user == null) + { + throw new InvalidOperationException("User not found"); + } + + users.Add(user); + + var additionalUsers = session.AdditionalUsersPresent + .Select(i => _userManager.GetUserById(new Guid(i.UserId))) + .Where(i => i != null); + + users.AddRange(additionalUsers); + } + + return users; + } + /// <summary> /// Used to report that playback has started for an item /// </summary> @@ -265,32 +302,46 @@ namespace MediaBrowser.Server.Implementations.Session var key = item.GetUserDataKey(); - var user = session.User; - - var data = _userDataRepository.GetUserData(user.Id, key); - - data.PlayCount++; - data.LastPlayedDate = DateTime.UtcNow; + var users = GetUsers(session); - if (!(item is Video)) + foreach (var user in users) { - data.Played = true; + await OnPlaybackStart(user.Id, key, item).ConfigureAwait(false); } - await _userDataRepository.SaveUserData(user.Id, info.Item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false); - // Nothing to save here // Fire events to inform plugins EventHelper.QueueEventIfNotNull(PlaybackStart, this, new PlaybackProgressEventArgs { Item = item, - User = user, - UserData = data + Users = users }, _logger); } /// <summary> + /// Called when [playback start]. + /// </summary> + /// <param name="userId">The user identifier.</param> + /// <param name="userDataKey">The user data key.</param> + /// <param name="item">The item.</param> + /// <returns>Task.</returns> + private async Task OnPlaybackStart(Guid userId, string userDataKey, IHasUserData item) + { + var data = _userDataRepository.GetUserData(userId, userDataKey); + + data.PlayCount++; + data.LastPlayedDate = DateTime.UtcNow; + + if (!(item is Video)) + { + data.Played = true; + } + + await _userDataRepository.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false); + } + + /// <summary> /// Used to report playback progress for an item /// </summary> /// <param name="info">The info.</param> @@ -315,27 +366,34 @@ namespace MediaBrowser.Server.Implementations.Session var key = info.Item.GetUserDataKey(); - var user = session.User; + var users = GetUsers(session); - var data = _userDataRepository.GetUserData(user.Id, key); - - if (info.PositionTicks.HasValue) + foreach (var user in users) { - UpdatePlayState(info.Item, data, info.PositionTicks.Value); - - await _userDataRepository.SaveUserData(user.Id, info.Item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None).ConfigureAwait(false); + await OnPlaybackProgress(user.Id, key, info.Item, info.PositionTicks).ConfigureAwait(false); } EventHelper.QueueEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs { Item = info.Item, - User = user, - PlaybackPositionTicks = info.PositionTicks, - UserData = data + Users = users, + PlaybackPositionTicks = info.PositionTicks }, _logger); } + private async Task OnPlaybackProgress(Guid userId, string userDataKey, BaseItem item, long? positionTicks) + { + var data = _userDataRepository.GetUserData(userId, userDataKey); + + if (positionTicks.HasValue) + { + UpdatePlayState(item, data, positionTicks.Value); + + await _userDataRepository.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None).ConfigureAwait(false); + } + } + /// <summary> /// Used to report that playback has ended for an item /// </summary> @@ -371,14 +429,32 @@ namespace MediaBrowser.Server.Implementations.Session var key = info.Item.GetUserDataKey(); - var user = session.User; + var users = GetUsers(session); + + var playedToCompletion = false; + foreach (var user in users) + { + playedToCompletion = await OnPlaybackStopped(user.Id, key, info.Item, info.PositionTicks).ConfigureAwait(false); + } + + EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackStopEventArgs + { + Item = info.Item, + Users = users, + PlaybackPositionTicks = info.PositionTicks, + PlayedToCompletion = playedToCompletion + + }, _logger); + } - var data = _userDataRepository.GetUserData(user.Id, key); + private async Task<bool> OnPlaybackStopped(Guid userId, string userDataKey, BaseItem item, long? positionTicks) + { + var data = _userDataRepository.GetUserData(userId, userDataKey); bool playedToCompletion; - if (info.PositionTicks.HasValue) + if (positionTicks.HasValue) { - playedToCompletion = UpdatePlayState(info.Item, data, info.PositionTicks.Value); + playedToCompletion = UpdatePlayState(item, data, positionTicks.Value); } else { @@ -389,19 +465,11 @@ namespace MediaBrowser.Server.Implementations.Session playedToCompletion = true; } - await _userDataRepository.SaveUserData(user.Id, info.Item, data, UserDataSaveReason.PlaybackFinished, CancellationToken.None).ConfigureAwait(false); - - EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackStopEventArgs - { - Item = info.Item, - User = user, - PlaybackPositionTicks = info.PositionTicks, - UserData = data, - PlayedToCompletion = playedToCompletion + await _userDataRepository.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackFinished, CancellationToken.None).ConfigureAwait(false); - }, _logger); + return playedToCompletion; } - + /// <summary> /// Updates playstate position for an item but does not save /// </summary> @@ -462,12 +530,12 @@ namespace MediaBrowser.Server.Implementations.Session } /// <summary> - /// Gets the session for remote control. + /// Gets the session. /// </summary> - /// <param name="sessionId">The session id.</param> + /// <param name="sessionId">The session identifier.</param> /// <returns>SessionInfo.</returns> /// <exception cref="ResourceNotFoundException"></exception> - private SessionInfo GetSessionForRemoteControl(Guid sessionId) + private SessionInfo GetSession(Guid sessionId) { var session = Sessions.First(i => i.Id.Equals(sessionId)); @@ -476,6 +544,19 @@ namespace MediaBrowser.Server.Implementations.Session throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId)); } + return session; + } + + /// <summary> + /// Gets the session for remote control. + /// </summary> + /// <param name="sessionId">The session id.</param> + /// <returns>SessionInfo.</returns> + /// <exception cref="ResourceNotFoundException"></exception> + private SessionInfo GetSessionForRemoteControl(Guid sessionId) + { + var session = GetSession(sessionId); + if (!session.SupportsRemoteControl) { throw new ArgumentException(string.Format("Session {0} does not support remote control.", session.Id)); @@ -595,7 +676,7 @@ namespace MediaBrowser.Server.Implementations.Session _logger.ErrorException("Error in SendRestartRequiredNotification.", ex); } - })); + }, cancellationToken)); return Task.WhenAll(tasks); } @@ -649,5 +730,68 @@ namespace MediaBrowser.Server.Implementations.Session return Task.WhenAll(tasks); } + + + /// <summary> + /// Adds the additional user. + /// </summary> + /// <param name="sessionId">The session identifier.</param> + /// <param name="userId">The user identifier.</param> + /// <exception cref="System.UnauthorizedAccessException">Cannot modify additional users without authenticating first.</exception> + /// <exception cref="System.ArgumentException">The requested user is already the primary user of the session.</exception> + public void AddAdditionalUser(Guid sessionId, Guid userId) + { + var session = GetSession(sessionId); + + if (!session.UserId.HasValue) + { + throw new UnauthorizedAccessException("Cannot modify additional users without authenticating first."); + } + + if (session.UserId.Value == userId) + { + throw new ArgumentException("The requested user is already the primary user of the session."); + } + + if (session.AdditionalUsersPresent.All(i => new Guid(i.UserId) != userId)) + { + var user = _userManager.GetUserById(userId); + + session.AdditionalUsersPresent.Add(new SessionUserInfo + { + UserId = userId.ToString("N"), + UserName = user.Name + }); + } + } + + /// <summary> + /// Removes the additional user. + /// </summary> + /// <param name="sessionId">The session identifier.</param> + /// <param name="userId">The user identifier.</param> + /// <exception cref="System.UnauthorizedAccessException">Cannot modify additional users without authenticating first.</exception> + /// <exception cref="System.ArgumentException">The requested user is already the primary user of the session.</exception> + public void RemoveAdditionalUser(Guid sessionId, Guid userId) + { + var session = GetSession(sessionId); + + if (!session.UserId.HasValue) + { + throw new UnauthorizedAccessException("Cannot modify additional users without authenticating first."); + } + + if (session.UserId.Value == userId) + { + throw new ArgumentException("The requested user is already the primary user of the session."); + } + + var user = session.AdditionalUsersPresent.FirstOrDefault(i => new Guid(i.UserId) == userId); + + if (user != null) + { + session.AdditionalUsersPresent.Remove(user); + } + } } }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs index 08481f09f..d693f90e2 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs @@ -191,7 +191,7 @@ namespace MediaBrowser.Server.Implementations.Session var session = GetSessionFromMessage(message); - if (session != null && session.User != null) + if (session != null && session.UserId.HasValue) { var vals = message.Data.Split('|'); @@ -229,7 +229,7 @@ namespace MediaBrowser.Server.Implementations.Session { var session = GetSessionFromMessage(message); - if (session != null && session.User != null) + if (session != null && session.UserId.HasValue) { var vals = message.Data.Split('|'); @@ -273,7 +273,7 @@ namespace MediaBrowser.Server.Implementations.Session var session = GetSessionFromMessage(message); - if (session != null && session.User != null) + if (session != null && session.UserId.HasValue) { var vals = message.Data.Split('|'); |
