aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Session
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-01-03 21:35:41 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-01-03 21:35:41 -0500
commit135168b0e0640211aee5cda9285cffb184385e83 (patch)
treeccbdd9a8a5299aa557b888919b1884e5705ed05e /MediaBrowser.Server.Implementations/Session
parent6da42312441dcdad2fbbd831a219398371340b43 (diff)
support adding additional users to sessions
Diffstat (limited to 'MediaBrowser.Server.Implementations/Session')
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs236
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs6
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('|');