aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs6
-rw-r--r--MediaBrowser.Controller/Entities/User.cs15
-rw-r--r--MediaBrowser.Controller/Kernel.cs79
-rw-r--r--MediaBrowser.Controller/Library/DtoBuilder.cs18
-rw-r--r--MediaBrowser.Controller/Library/IUserManager.cs169
-rw-r--r--MediaBrowser.Controller/Library/LibraryManager.cs9
-rw-r--r--MediaBrowser.Controller/Library/UserDataManager.cs226
-rw-r--r--MediaBrowser.Controller/Library/UserManager.cs403
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj3
10 files changed, 206 insertions, 726 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 8535f85c2..e462ac9e2 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1205,7 +1205,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
- public virtual Task SetPlayedStatus(User user, bool wasPlayed)
+ public virtual Task SetPlayedStatus(User user, bool wasPlayed, IUserManager userManager)
{
if (user == null)
{
@@ -1235,7 +1235,7 @@ namespace MediaBrowser.Controller.Entities
data.Played = wasPlayed;
- return Kernel.Instance.UserDataManager.SaveUserDataForItem(user, this, data);
+ return userManager.SaveUserDataForItem(user, this, data);
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index b2be96b71..28075b9a1 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -962,12 +962,12 @@ namespace MediaBrowser.Controller.Entities
/// <param name="user">The user.</param>
/// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
/// <returns>Task.</returns>
- public override async Task SetPlayedStatus(User user, bool wasPlayed)
+ public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserManager userManager)
{
- await base.SetPlayedStatus(user, wasPlayed).ConfigureAwait(false);
+ await base.SetPlayedStatus(user, wasPlayed, userManager).ConfigureAwait(false);
// Now sweep through recursively and update status
- var tasks = GetChildren(user).Select(c => c.SetPlayedStatus(user, wasPlayed));
+ var tasks = GetChildren(user).Select(c => c.SetPlayedStatus(user, wasPlayed, userManager));
await Task.WhenAll(tasks).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index 5abd3e5a8..7196b68b8 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using System;
using System.IO;
@@ -16,6 +17,8 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class User : BaseItem
{
+ internal static IUserManager UserManager { get; set; }
+
/// <summary>
/// The _root folder path
/// </summary>
@@ -236,7 +239,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="newName">The new name.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
- internal Task Rename(string newName)
+ public Task Rename(string newName)
{
if (string.IsNullOrEmpty(newName))
{
@@ -364,7 +367,7 @@ namespace MediaBrowser.Controller.Entities
{
cancellationToken.ThrowIfCancellationRequested();
- await Kernel.Instance.UserManager.UpdateUser(this).ConfigureAwait(false);
+ await UserManager.UpdateUser(this).ConfigureAwait(false);
}
return changed;
@@ -425,9 +428,9 @@ namespace MediaBrowser.Controller.Entities
/// Resets the password by clearing it.
/// </summary>
/// <returns>Task.</returns>
- public Task ResetPassword()
+ public Task ResetPassword(IUserManager userManager)
{
- return ChangePassword(string.Empty);
+ return ChangePassword(string.Empty, userManager);
}
/// <summary>
@@ -435,11 +438,11 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <param name="newPassword">The new password.</param>
/// <returns>Task.</returns>
- public Task ChangePassword(string newPassword)
+ public Task ChangePassword(string newPassword, IUserManager userManager)
{
Password = string.IsNullOrEmpty(newPassword) ? string.Empty : newPassword.GetMD5().ToString();
- return Kernel.Instance.UserManager.UpdateUser(this);
+ return userManager.UpdateUser(this);
}
}
}
diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs
index 6703012be..e41b7c487 100644
--- a/MediaBrowser.Controller/Kernel.cs
+++ b/MediaBrowser.Controller/Kernel.cs
@@ -1,8 +1,5 @@
using MediaBrowser.Common.Kernel;
-using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.ScheduledTasks;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Common.Updates;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
@@ -52,12 +49,6 @@ namespace MediaBrowser.Controller
public ImageManager ImageManager { get; private set; }
/// <summary>
- /// Gets the user manager.
- /// </summary>
- /// <value>The user manager.</value>
- public UserManager UserManager { get; private set; }
-
- /// <summary>
/// Gets the FFMPEG controller.
/// </summary>
/// <value>The FFMPEG controller.</value>
@@ -82,47 +73,6 @@ namespace MediaBrowser.Controller
public ProviderManager ProviderManager { get; private set; }
/// <summary>
- /// Gets the user data manager.
- /// </summary>
- /// <value>The user data manager.</value>
- public UserDataManager UserDataManager { get; private set; }
-
- /// <summary>
- /// The _users
- /// </summary>
- private IEnumerable<User> _users;
- /// <summary>
- /// The _user lock
- /// </summary>
- private object _usersSyncLock = new object();
- /// <summary>
- /// The _users initialized
- /// </summary>
- private bool _usersInitialized;
- /// <summary>
- /// Gets the users.
- /// </summary>
- /// <value>The users.</value>
- public IEnumerable<User> Users
- {
- get
- {
- // Call ToList to exhaust the stream because we'll be iterating over this multiple times
- LazyInitializer.EnsureInitialized(ref _users, ref _usersInitialized, ref _usersSyncLock, UserManager.LoadUsers);
- return _users;
- }
- internal set
- {
- _users = value;
-
- if (value == null)
- {
- _usersInitialized = false;
- }
- }
- }
-
- /// <summary>
/// The _root folder
/// </summary>
private AggregateFolder _rootFolder;
@@ -304,13 +254,14 @@ namespace MediaBrowser.Controller
/// </summary>
protected override void FindParts()
{
+ // For now there's no real way to inject this properly
+ User.UserManager = ApplicationHost.Resolve<IUserManager>();
+
InstallationManager = (InstallationManager)ApplicationHost.CreateInstance(typeof(InstallationManager));
FFMpegManager = (FFMpegManager)ApplicationHost.CreateInstance(typeof(FFMpegManager));
LibraryManager = (LibraryManager)ApplicationHost.CreateInstance(typeof(LibraryManager));
- UserManager = (UserManager)ApplicationHost.CreateInstance(typeof(UserManager));
ImageManager = (ImageManager)ApplicationHost.CreateInstance(typeof(ImageManager));
ProviderManager = (ProviderManager)ApplicationHost.CreateInstance(typeof(ProviderManager));
- UserDataManager = (UserDataManager)ApplicationHost.CreateInstance(typeof(UserDataManager));
SecurityManager = (PluginSecurityManager)ApplicationHost.CreateInstance(typeof(PluginSecurityManager));
base.FindParts();
@@ -337,7 +288,6 @@ namespace MediaBrowser.Controller
protected override async Task ReloadInternal()
{
// Reset these so that they can be lazy loaded again
- Users = null;
RootFolder = null;
await base.ReloadInternal().ConfigureAwait(false);
@@ -346,7 +296,7 @@ namespace MediaBrowser.Controller
ReloadFileSystemManager();
- await UserManager.RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false);
+ await ApplicationHost.Resolve<IUserManager>().RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false);
}
/// <summary>
@@ -454,29 +404,14 @@ namespace MediaBrowser.Controller
}
/// <summary>
- /// Gets a User by Id
- /// </summary>
- /// <param name="id">The id.</param>
- /// <returns>User.</returns>
- /// <exception cref="System.ArgumentNullException"></exception>
- public User GetUserById(Guid id)
- {
- if (id == Guid.Empty)
- {
- throw new ArgumentNullException();
- }
-
- return Users.FirstOrDefault(u => u.Id == id);
- }
-
- /// <summary>
/// Finds a library item by Id and UserId.
/// </summary>
/// <param name="id">The id.</param>
/// <param name="userId">The user id.</param>
+ /// <param name="userManager">The user manager.</param>
/// <returns>BaseItem.</returns>
/// <exception cref="System.ArgumentNullException">id</exception>
- public BaseItem GetItemById(Guid id, Guid userId)
+ public BaseItem GetItemById(Guid id, Guid userId, IUserManager userManager)
{
if (id == Guid.Empty)
{
@@ -488,7 +423,7 @@ namespace MediaBrowser.Controller
throw new ArgumentNullException("userId");
}
- var user = GetUserById(userId);
+ var user = userManager.GetUserById(userId);
var userRoot = user.RootFolder;
return userRoot.FindItemById(id, user);
diff --git a/MediaBrowser.Controller/Library/DtoBuilder.cs b/MediaBrowser.Controller/Library/DtoBuilder.cs
index 8cf9d5b57..30a14bf97 100644
--- a/MediaBrowser.Controller/Library/DtoBuilder.cs
+++ b/MediaBrowser.Controller/Library/DtoBuilder.cs
@@ -823,7 +823,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="id">The id.</param>
/// <param name="userId">The user id.</param>
/// <returns>BaseItem.</returns>
- public static BaseItem GetItemByClientId(string id, Guid? userId = null)
+ public static BaseItem GetItemByClientId(string id, IUserManager userManager, Guid? userId = null)
{
var isIdEmpty = string.IsNullOrEmpty(id);
@@ -835,7 +835,7 @@ namespace MediaBrowser.Controller.Library
{
if (userId.HasValue)
{
- return GetIndexFolder(id, userId.Value);
+ return GetIndexFolder(id, userId.Value, userManager);
}
}
@@ -844,8 +844,8 @@ namespace MediaBrowser.Controller.Library
if (userId.HasValue)
{
item = isIdEmpty
- ? Kernel.Instance.GetUserById(userId.Value).RootFolder
- : Kernel.Instance.GetItemById(new Guid(id), userId.Value);
+ ? userManager.GetUserById(userId.Value).RootFolder
+ : Kernel.Instance.GetItemById(new Guid(id), userId.Value, userManager);
}
else if (!isIndexFolder)
{
@@ -855,9 +855,9 @@ namespace MediaBrowser.Controller.Library
// If we still don't find it, look within individual user views
if (item == null && !userId.HasValue)
{
- foreach (var user in Kernel.Instance.Users)
+ foreach (var user in userManager.Users)
{
- item = GetItemByClientId(id, user.Id);
+ item = GetItemByClientId(id, userManager, user.Id);
if (item != null)
{
@@ -875,9 +875,9 @@ namespace MediaBrowser.Controller.Library
/// <param name="id">The id.</param>
/// <param name="userId">The user id.</param>
/// <returns>BaseItem.</returns>
- private static BaseItem GetIndexFolder(string id, Guid userId)
+ private static BaseItem GetIndexFolder(string id, Guid userId, IUserManager userManager)
{
- var user = Kernel.Instance.GetUserById(userId);
+ var user = userManager.GetUserById(userId);
var stringSeparators = new[] { IndexFolderDelimeter };
@@ -885,7 +885,7 @@ namespace MediaBrowser.Controller.Library
var values = id.Split(stringSeparators, StringSplitOptions.None).ToList();
// Get the top folder normally using the first id
- var folder = GetItemByClientId(values[0], userId) as Folder;
+ var folder = GetItemByClientId(values[0], userManager, userId) as Folder;
values.RemoveAt(0);
diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs
new file mode 100644
index 000000000..ea4f03330
--- /dev/null
+++ b/MediaBrowser.Controller/Library/IUserManager.cs
@@ -0,0 +1,169 @@
+using MediaBrowser.Common.Events;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Connectivity;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Library
+{
+ public interface IUserManager
+ {
+ /// <summary>
+ /// Gets the users.
+ /// </summary>
+ /// <value>The users.</value>
+ IEnumerable<User> Users { get; }
+
+ /// <summary>
+ /// Gets the active connections.
+ /// </summary>
+ /// <value>The active connections.</value>
+ IEnumerable<ClientConnectionInfo> ConnectedUsers { get; }
+
+ /// <summary>
+ /// Occurs when [playback start].
+ /// </summary>
+ event EventHandler<PlaybackProgressEventArgs> PlaybackStart;
+
+ /// <summary>
+ /// Occurs when [playback progress].
+ /// </summary>
+ event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
+
+ /// <summary>
+ /// Occurs when [playback stopped].
+ /// </summary>
+ event EventHandler<PlaybackProgressEventArgs> PlaybackStopped;
+
+ /// <summary>
+ /// Occurs when [user updated].
+ /// </summary>
+ event EventHandler<GenericEventArgs<User>> UserUpdated;
+
+ /// <summary>
+ /// Occurs when [user deleted].
+ /// </summary>
+ event EventHandler<GenericEventArgs<User>> UserDeleted;
+
+ /// <summary>
+ /// Gets a User by Id
+ /// </summary>
+ /// <param name="id">The id.</param>
+ /// <returns>User.</returns>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ User GetUserById(Guid id);
+
+ /// <summary>
+ /// Authenticates a User and returns a result indicating whether or not it succeeded
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="password">The password.</param>
+ /// <returns>Task{System.Boolean}.</returns>
+ /// <exception cref="System.ArgumentNullException">user</exception>
+ Task<bool> AuthenticateUser(User user, string password);
+
+ /// <summary>
+ /// Logs the user activity.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="clientType">Type of the client.</param>
+ /// <param name="deviceName">Name of the device.</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="System.ArgumentNullException">user</exception>
+ Task LogUserActivity(User user, ClientType clientType, string deviceName);
+
+ /// <summary>
+ /// Loads the users from the repository
+ /// </summary>
+ /// <returns>IEnumerable{User}.</returns>
+ IEnumerable<User> LoadUsers();
+
+ /// <summary>
+ /// Refreshes metadata for each user
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <param name="force">if set to <c>true</c> [force].</param>
+ /// <returns>Task.</returns>
+ Task RefreshUsersMetadata(CancellationToken cancellationToken, bool force = false);
+
+ /// <summary>
+ /// Renames the user.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="newName">The new name.</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="System.ArgumentNullException">user</exception>
+ /// <exception cref="System.ArgumentException"></exception>
+ Task RenameUser(User user, string newName);
+
+ /// <summary>
+ /// Updates the user.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <exception cref="System.ArgumentNullException">user</exception>
+ /// <exception cref="System.ArgumentException"></exception>
+ Task UpdateUser(User user);
+
+ /// <summary>
+ /// Creates the user.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <returns>User.</returns>
+ /// <exception cref="System.ArgumentNullException">name</exception>
+ /// <exception cref="System.ArgumentException"></exception>
+ Task<User> CreateUser(string name);
+
+ /// <summary>
+ /// Deletes the user.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="System.ArgumentNullException">user</exception>
+ /// <exception cref="System.ArgumentException"></exception>
+ Task DeleteUser(User user);
+
+ /// <summary>
+ /// Used to report that playback has started for an item
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="item">The item.</param>
+ /// <param name="clientType">Type of the client.</param>
+ /// <param name="deviceName">Name of the device.</param>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ void OnPlaybackStart(User user, BaseItem item, ClientType clientType, string deviceName);
+
+ /// <summary>
+ /// Used to report playback progress for an item
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="item">The item.</param>
+ /// <param name="positionTicks">The position ticks.</param>
+ /// <param name="clientType">Type of the client.</param>
+ /// <param name="deviceName">Name of the device.</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, ClientType clientType, string deviceName);
+
+ /// <summary>
+ /// Used to report that playback has ended for an item
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="item">The item.</param>
+ /// <param name="positionTicks">The position ticks.</param>
+ /// <param name="clientType">Type of the client.</param>
+ /// <param name="deviceName">Name of the device.</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, ClientType clientType, string deviceName);
+
+ /// <summary>
+ /// Saves user data for an item
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="item">The item.</param>
+ /// <param name="data">The data.</param>
+ Task SaveUserDataForItem(User user, BaseItem item, UserItemData data);
+ }
+}
diff --git a/MediaBrowser.Controller/Library/LibraryManager.cs b/MediaBrowser.Controller/Library/LibraryManager.cs
index 53f4af4b2..5dbf5c72d 100644
--- a/MediaBrowser.Controller/Library/LibraryManager.cs
+++ b/MediaBrowser.Controller/Library/LibraryManager.cs
@@ -64,6 +64,8 @@ namespace MediaBrowser.Controller.Library
/// </summary>
private readonly ITaskManager _taskManager;
+ private readonly IUserManager _userManager;
+
/// <summary>
/// Gets or sets the kernel.
/// </summary>
@@ -76,11 +78,12 @@ namespace MediaBrowser.Controller.Library
/// <param name="kernel">The kernel.</param>
/// <param name="logger">The logger.</param>
/// <param name="taskManager">The task manager.</param>
- public LibraryManager(Kernel kernel, ILogger logger, ITaskManager taskManager)
+ public LibraryManager(Kernel kernel, ILogger logger, ITaskManager taskManager, IUserManager userManager)
{
Kernel = kernel;
_logger = logger;
_taskManager = taskManager;
+ _userManager = userManager;
kernel.ConfigurationUpdated += kernel_ConfigurationUpdated;
}
@@ -490,13 +493,13 @@ namespace MediaBrowser.Controller.Library
await Kernel.RootFolder.ValidateChildren(new Progress<double> { }, cancellationToken, recursive: false);
// Validate only the collection folders for each user, just to make them available as quickly as possible
- var userCollectionFolderTasks = Kernel.Users.AsParallel().Select(user => user.ValidateCollectionFolders(new Progress<double> { }, cancellationToken));
+ var userCollectionFolderTasks = _userManager.Users.AsParallel().Select(user => user.ValidateCollectionFolders(new Progress<double> { }, cancellationToken));
await Task.WhenAll(userCollectionFolderTasks).ConfigureAwait(false);
// Now validate the entire media library
await Kernel.RootFolder.ValidateChildren(progress, cancellationToken, recursive: true).ConfigureAwait(false);
- foreach (var user in Kernel.Users)
+ foreach (var user in _userManager.Users)
{
await user.ValidateMediaLibrary(new Progress<double> { }, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Controller/Library/UserDataManager.cs b/MediaBrowser.Controller/Library/UserDataManager.cs
deleted file mode 100644
index bda5d0383..000000000
--- a/MediaBrowser.Controller/Library/UserDataManager.cs
+++ /dev/null
@@ -1,226 +0,0 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Connectivity;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.Library
-{
- /// <summary>
- /// Class UserDataManager
- /// </summary>
- public class UserDataManager : BaseManager<Kernel>
- {
- #region Events
- /// <summary>
- /// Occurs when [playback start].
- /// </summary>
- public event EventHandler<PlaybackProgressEventArgs> PlaybackStart;
- /// <summary>
- /// Occurs when [playback progress].
- /// </summary>
- public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
- /// <summary>
- /// Occurs when [playback stopped].
- /// </summary>
- public event EventHandler<PlaybackProgressEventArgs> PlaybackStopped;
- #endregion
-
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UserDataManager" /> class.
- /// </summary>
- /// <param name="kernel">The kernel.</param>
- /// <param name="logger">The logger.</param>
- public UserDataManager(Kernel kernel, ILogger logger)
- : base(kernel)
- {
- _logger = logger;
- }
-
- /// <summary>
- /// Used to report that playback has started for an item
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="item">The item.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <exception cref="System.ArgumentNullException"></exception>
- public void OnPlaybackStart(User user, BaseItem item, ClientType clientType, string deviceName)
- {
- if (user == null)
- {
- throw new ArgumentNullException();
- }
- if (item == null)
- {
- throw new ArgumentNullException();
- }
-
- Kernel.UserManager.UpdateNowPlayingItemId(user, clientType, deviceName, item);
-
- // Nothing to save here
- // Fire events to inform plugins
- EventHelper.QueueEventIfNotNull(PlaybackStart, this, new PlaybackProgressEventArgs
- {
- Argument = item,
- User = user
- }, _logger);
- }
-
- /// <summary>
- /// Used to report playback progress for an item
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="item">The item.</param>
- /// <param name="positionTicks">The position ticks.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException"></exception>
- public async Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, ClientType clientType, string deviceName)
- {
- if (user == null)
- {
- throw new ArgumentNullException();
- }
- if (item == null)
- {
- throw new ArgumentNullException();
- }
-
- Kernel.UserManager.UpdateNowPlayingItemId(user, clientType, deviceName, item, positionTicks);
-
- if (positionTicks.HasValue)
- {
- var data = item.GetUserData(user, true);
-
- UpdatePlayState(item, data, positionTicks.Value, false);
- await SaveUserDataForItem(user, item, data).ConfigureAwait(false);
- }
-
- EventHelper.QueueEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs
- {
- Argument = item,
- User = user,
- PlaybackPositionTicks = positionTicks
- }, _logger);
- }
-
- /// <summary>
- /// Used to report that playback has ended for an item
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="item">The item.</param>
- /// <param name="positionTicks">The position ticks.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException"></exception>
- public async Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, ClientType clientType, string deviceName)
- {
- if (user == null)
- {
- throw new ArgumentNullException();
- }
- if (item == null)
- {
- throw new ArgumentNullException();
- }
-
- Kernel.UserManager.RemoveNowPlayingItemId(user, clientType, deviceName, item);
-
- var data = item.GetUserData(user, true);
-
- if (positionTicks.HasValue)
- {
- UpdatePlayState(item, data, positionTicks.Value, true);
- }
- else
- {
- // If the client isn't able to report this, then we'll just have to make an assumption
- data.PlayCount++;
- data.Played = true;
- }
-
- await SaveUserDataForItem(user, item, data).ConfigureAwait(false);
-
- EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackProgressEventArgs
- {
- Argument = item,
- User = user,
- PlaybackPositionTicks = positionTicks
- }, _logger);
- }
-
- /// <summary>
- /// Updates playstate position for an item but does not save
- /// </summary>
- /// <param name="item">The item</param>
- /// <param name="data">User data for the item</param>
- /// <param name="positionTicks">The current playback position</param>
- /// <param name="incrementPlayCount">Whether or not to increment playcount</param>
- private void UpdatePlayState(BaseItem item, UserItemData data, long positionTicks, bool incrementPlayCount)
- {
- // If a position has been reported, and if we know the duration
- if (positionTicks > 0 && item.RunTimeTicks.HasValue && item.RunTimeTicks > 0)
- {
- var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100;
-
- // Don't track in very beginning
- if (pctIn < Kernel.Configuration.MinResumePct)
- {
- positionTicks = 0;
- incrementPlayCount = false;
- }
-
- // If we're at the end, assume completed
- else if (pctIn > Kernel.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value)
- {
- positionTicks = 0;
- data.Played = true;
- }
-
- else
- {
- // Enforce MinResumeDuration
- var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds;
-
- if (durationSeconds < Kernel.Configuration.MinResumeDurationSeconds)
- {
- positionTicks = 0;
- data.Played = true;
- }
- }
- }
-
- data.PlaybackPositionTicks = positionTicks;
-
- if (incrementPlayCount)
- {
- data.PlayCount++;
- data.LastPlayedDate = DateTime.UtcNow;
- }
- }
-
- /// <summary>
- /// Saves user data for an item
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="item">The item.</param>
- /// <param name="data">The data.</param>
- public Task SaveUserDataForItem(User user, BaseItem item, UserItemData data)
- {
- item.AddOrUpdateUserData(user, data);
-
- return Kernel.UserDataRepository.SaveUserData(item, CancellationToken.None);
- }
- }
-}
diff --git a/MediaBrowser.Controller/Library/UserManager.cs b/MediaBrowser.Controller/Library/UserManager.cs
deleted file mode 100644
index 5340e70be..000000000
--- a/MediaBrowser.Controller/Library/UserManager.cs
+++ /dev/null
@@ -1,403 +0,0 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Connectivity;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Logging;
-
-namespace MediaBrowser.Controller.Library
-{
- /// <summary>
- /// Class UserManager
- /// </summary>
- public class UserManager : BaseManager<Kernel>
- {
- /// <summary>
- /// The _active connections
- /// </summary>
- private readonly ConcurrentBag<ClientConnectionInfo> _activeConnections =
- new ConcurrentBag<ClientConnectionInfo>();
-
- /// <summary>
- /// Gets all connections.
- /// </summary>
- /// <value>All connections.</value>
- public IEnumerable<ClientConnectionInfo> AllConnections
- {
- get { return _activeConnections.Where(c => Kernel.GetUserById(c.UserId) != null).OrderByDescending(c => c.LastActivityDate); }
- }
-
- /// <summary>
- /// Gets the active connections.
- /// </summary>
- /// <value>The active connections.</value>
- public IEnumerable<ClientConnectionInfo> ActiveConnections
- {
- get { return AllConnections.Where(c => (DateTime.UtcNow - c.LastActivityDate).TotalMinutes <= 10); }
- }
-
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="UserManager" /> class.
- /// </summary>
- /// <param name="kernel">The kernel.</param>
- /// <param name="logger">The logger.</param>
- public UserManager(Kernel kernel, ILogger logger)
- : base(kernel)
- {
- _logger = logger;
- }
-
- #region UserUpdated Event
- /// <summary>
- /// Occurs when [user updated].
- /// </summary>
- public event EventHandler<GenericEventArgs<User>> UserUpdated;
-
- /// <summary>
- /// Called when [user updated].
- /// </summary>
- /// <param name="user">The user.</param>
- internal void OnUserUpdated(User user)
- {
- EventHelper.QueueEventIfNotNull(UserUpdated, this, new GenericEventArgs<User> { Argument = user }, _logger);
-
- // Notify connected ui's
- Kernel.ServerManager.SendWebSocketMessage("UserUpdated", new DtoBuilder(_logger).GetDtoUser(user));
- }
- #endregion
-
- #region UserDeleted Event
- /// <summary>
- /// Occurs when [user deleted].
- /// </summary>
- public event EventHandler<GenericEventArgs<User>> UserDeleted;
- /// <summary>
- /// Called when [user deleted].
- /// </summary>
- /// <param name="user">The user.</param>
- internal void OnUserDeleted(User user)
- {
- EventHelper.QueueEventIfNotNull(UserDeleted, this, new GenericEventArgs<User> { Argument = user }, _logger);
-
- // Notify connected ui's
- Kernel.ServerManager.SendWebSocketMessage("UserDeleted", user.Id.ToString());
- }
- #endregion
-
- /// <summary>
- /// Authenticates a User and returns a result indicating whether or not it succeeded
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="password">The password.</param>
- /// <returns>Task{System.Boolean}.</returns>
- /// <exception cref="System.ArgumentNullException">user</exception>
- public async Task<bool> AuthenticateUser(User user, string password)
- {
- if (user == null)
- {
- throw new ArgumentNullException("user");
- }
-
- password = password ?? string.Empty;
- var existingPassword = string.IsNullOrEmpty(user.Password) ? string.Empty.GetMD5().ToString() : user.Password;
-
- var success = password.GetMD5().ToString().Equals(existingPassword);
-
- // Update LastActivityDate and LastLoginDate, then save
- if (success)
- {
- user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
- await UpdateUser(user).ConfigureAwait(false);
- }
-
- _logger.Info("Authentication request for {0} {1}.", user.Name, (success ? "has succeeded" : "has been denied"));
-
- return success;
- }
-
- /// <summary>
- /// Logs the user activity.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">user</exception>
- public Task LogUserActivity(User user, ClientType clientType, string deviceName)
- {
- if (user == null)
- {
- throw new ArgumentNullException("user");
- }
-
- var activityDate = DateTime.UtcNow;
-
- user.LastActivityDate = activityDate;
-
- LogConnection(user.Id, clientType, deviceName, activityDate);
-
- // Save this directly. No need to fire off all the events for this.
- return Kernel.UserRepository.SaveUser(user, CancellationToken.None);
- }
-
- /// <summary>
- /// Updates the now playing item id.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <param name="item">The item.</param>
- /// <param name="currentPositionTicks">The current position ticks.</param>
- public void UpdateNowPlayingItemId(User user, ClientType clientType, string deviceName, BaseItem item, long? currentPositionTicks = null)
- {
- var conn = GetConnection(user.Id, clientType, deviceName);
-
- conn.NowPlayingPositionTicks = currentPositionTicks;
- conn.NowPlayingItem = DtoBuilder.GetBaseItemInfo(item);
- }
-
- /// <summary>
- /// Removes the now playing item id.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <param name="item">The item.</param>
- public void RemoveNowPlayingItemId(User user, ClientType clientType, string deviceName, BaseItem item)
- {
- var conn = GetConnection(user.Id, clientType, deviceName);
-
- if (conn.NowPlayingItem != null && conn.NowPlayingItem.Id.Equals(item.Id.ToString()))
- {
- conn.NowPlayingItem = null;
- conn.NowPlayingPositionTicks = null;
- }
- }
-
- /// <summary>
- /// Logs the connection.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <param name="lastActivityDate">The last activity date.</param>
- private void LogConnection(Guid userId, ClientType clientType, string deviceName, DateTime lastActivityDate)
- {
- GetConnection(userId, clientType, deviceName).LastActivityDate = lastActivityDate;
- }
-
- /// <summary>
- /// Gets the connection.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <returns>ClientConnectionInfo.</returns>
- private ClientConnectionInfo GetConnection(Guid userId, ClientType clientType, string deviceName)
- {
- var conn = _activeConnections.FirstOrDefault(c => c.UserId == userId && c.ClientType == clientType && string.Equals(deviceName, c.DeviceName, StringComparison.OrdinalIgnoreCase));
-
- if (conn == null)
- {
- conn = new ClientConnectionInfo
- {
- UserId = userId,
- ClientType = clientType,
- DeviceName = deviceName
- };
-
- _activeConnections.Add(conn);
- }
-
- return conn;
- }
-
- /// <summary>
- /// Loads the users from the repository
- /// </summary>
- /// <returns>IEnumerable{User}.</returns>
- internal IEnumerable<User> LoadUsers()
- {
- var users = Kernel.UserRepository.RetrieveAllUsers().ToList();
-
- // There always has to be at least one user.
- if (users.Count == 0)
- {
- var name = Environment.UserName;
-
- var user = InstantiateNewUser(name);
-
- var task = Kernel.UserRepository.SaveUser(user, CancellationToken.None);
-
- // Hate having to block threads
- Task.WaitAll(task);
-
- users.Add(user);
- }
-
- return users;
- }
-
- /// <summary>
- /// Refreshes metadata for each user
- /// </summary>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="force">if set to <c>true</c> [force].</param>
- /// <returns>Task.</returns>
- public Task RefreshUsersMetadata(CancellationToken cancellationToken, bool force = false)
- {
- var tasks = Kernel.Users.Select(user => user.RefreshMetadata(cancellationToken, forceRefresh: force)).ToList();
-
- return Task.WhenAll(tasks);
- }
-
- /// <summary>
- /// Renames the user.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="newName">The new name.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">user</exception>
- /// <exception cref="System.ArgumentException"></exception>
- public async Task RenameUser(User user, string newName)
- {
- if (user == null)
- {
- throw new ArgumentNullException("user");
- }
-
- if (string.IsNullOrEmpty(newName))
- {
- throw new ArgumentNullException("newName");
- }
-
- if (Kernel.Users.Any(u => u.Id != user.Id && u.Name.Equals(newName, StringComparison.OrdinalIgnoreCase)))
- {
- throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", newName));
- }
-
- if (user.Name.Equals(newName, StringComparison.Ordinal))
- {
- throw new ArgumentException("The new and old names must be different.");
- }
-
- await user.Rename(newName);
-
- OnUserUpdated(user);
- }
-
- /// <summary>
- /// Updates the user.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <exception cref="System.ArgumentNullException">user</exception>
- /// <exception cref="System.ArgumentException"></exception>
- public async Task UpdateUser(User user)
- {
- if (user == null)
- {
- throw new ArgumentNullException("user");
- }
-
- if (user.Id == Guid.Empty || !Kernel.Users.Any(u => u.Id.Equals(user.Id)))
- {
- throw new ArgumentException(string.Format("User with name '{0}' and Id {1} does not exist.", user.Name, user.Id));
- }
-
- user.DateModified = DateTime.UtcNow;
-
- await Kernel.UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false);
-
- OnUserUpdated(user);
- }
-
- /// <summary>
- /// Creates the user.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <returns>User.</returns>
- /// <exception cref="System.ArgumentNullException">name</exception>
- /// <exception cref="System.ArgumentException"></exception>
- public async Task<User> CreateUser(string name)
- {
- if (string.IsNullOrEmpty(name))
- {
- throw new ArgumentNullException("name");
- }
-
- if (Kernel.Users.Any(u => u.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
- {
- throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", name));
- }
-
- var user = InstantiateNewUser(name);
-
- var list = Kernel.Users.ToList();
- list.Add(user);
- Kernel.Users = list;
-
- await Kernel.UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false);
-
- return user;
- }
-
- /// <summary>
- /// Deletes the user.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">user</exception>
- /// <exception cref="System.ArgumentException"></exception>
- public async Task DeleteUser(User user)
- {
- if (user == null)
- {
- throw new ArgumentNullException("user");
- }
-
- if (Kernel.Users.FirstOrDefault(u => u.Id == user.Id) == null)
- {
- throw new ArgumentException(string.Format("The user cannot be deleted because there is no user with the Name {0} and Id {1}.", user.Name, user.Id));
- }
-
- if (Kernel.Users.Count() == 1)
- {
- throw new ArgumentException(string.Format("The user '{0}' be deleted because there must be at least one user in the system.", user.Name));
- }
-
- await Kernel.UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false);
-
- OnUserDeleted(user);
-
- // Force this to be lazy loaded again
- Kernel.Users = null;
- }
-
- /// <summary>
- /// Instantiates the new user.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <returns>User.</returns>
- private User InstantiateNewUser(string name)
- {
- return new User
- {
- Name = name,
- Id = ("MBUser" + name).GetMD5(),
- DateCreated = DateTime.UtcNow,
- DateModified = DateTime.UtcNow
- };
- }
- }
-}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 6ab70f47c..6648c6458 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -113,9 +113,8 @@
<Compile Include="IServerApplicationPaths.cs" />
<Compile Include="Library\ChildrenChangedEventArgs.cs" />
<Compile Include="Library\DtoBuilder.cs" />
+ <Compile Include="Library\IUserManager.cs" />
<Compile Include="Library\Profiler.cs" />
- <Compile Include="Library\UserDataManager.cs" />
- <Compile Include="Library\UserManager.cs" />
<Compile Include="Localization\AURatingsDictionary.cs" />
<Compile Include="Localization\BaseStrings.cs" />
<Compile Include="Localization\GBRatingsDictionary.cs" />