aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Devices/DeviceManager.cs
diff options
context:
space:
mode:
authorstefan <stefan@hegedues.at>2018-09-12 19:26:21 +0200
committerstefan <stefan@hegedues.at>2018-09-12 19:26:21 +0200
commit48facb797ed912e4ea6b04b17d1ff190ac2daac4 (patch)
tree8dae77a31670a888d733484cb17dd4077d5444e8 /Emby.Server.Implementations/Devices/DeviceManager.cs
parentc32d8656382a0eacb301692e0084377fc433ae9b (diff)
Update to 3.5.2 and .net core 2.1
Diffstat (limited to 'Emby.Server.Implementations/Devices/DeviceManager.cs')
-rw-r--r--Emby.Server.Implementations/Devices/DeviceManager.cs380
1 files changed, 292 insertions, 88 deletions
diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs
index ee4c4bb26..0fac886ef 100644
--- a/Emby.Server.Implementations/Devices/DeviceManager.cs
+++ b/Emby.Server.Implementations/Devices/DeviceManager.cs
@@ -18,114 +18,150 @@ using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Model.Globalization;
+using MediaBrowser.Controller.Security;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Common.Extensions;
namespace Emby.Server.Implementations.Devices
{
public class DeviceManager : IDeviceManager
{
- private readonly IDeviceRepository _repo;
+ private readonly IJsonSerializer _json;
private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _libraryMonitor;
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly INetworkManager _network;
+ private readonly ILibraryManager _libraryManager;
+ private readonly ILocalizationManager _localizationManager;
+ private readonly IAuthenticationRepository _authRepo;
+
+ public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
public event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded;
- /// <summary>
- /// Occurs when [device options updated].
- /// </summary>
- public event EventHandler<GenericEventArgs<DeviceInfo>> DeviceOptionsUpdated;
+ private readonly object _cameraUploadSyncLock = new object();
+ private readonly object _capabilitiesSyncLock = new object();
- public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network)
+ public DeviceManager(IAuthenticationRepository authRepo, IJsonSerializer json, ILibraryManager libraryManager, ILocalizationManager localizationManager, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IServerConfigurationManager config, ILogger logger, INetworkManager network)
{
- _repo = repo;
+ _json = json;
_userManager = userManager;
_fileSystem = fileSystem;
_libraryMonitor = libraryMonitor;
_config = config;
_logger = logger;
_network = network;
+ _libraryManager = libraryManager;
+ _localizationManager = localizationManager;
+ _authRepo = authRepo;
}
- public DeviceInfo RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId)
+
+ private Dictionary<string, ClientCapabilities> _capabilitiesCache = new Dictionary<string, ClientCapabilities>(StringComparer.OrdinalIgnoreCase);
+ public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
{
- if (string.IsNullOrWhiteSpace(reportedId))
- {
- throw new ArgumentNullException("reportedId");
- }
+ var path = Path.Combine(GetDevicePath(deviceId), "capabilities.json");
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
- var device = GetDevice(reportedId) ?? new DeviceInfo
+ lock (_capabilitiesSyncLock)
{
- Id = reportedId
- };
+ _capabilitiesCache[deviceId] = capabilities;
- device.ReportedName = name;
- device.AppName = appName;
- device.AppVersion = appVersion;
+ _json.SerializeToFile(capabilities, path);
+ }
+ }
- if (!string.IsNullOrWhiteSpace(usedByUserId))
- {
- var user = _userManager.GetUserById(usedByUserId);
+ public void UpdateDeviceOptions(string deviceId, DeviceOptions options)
+ {
+ _authRepo.UpdateDeviceOptions(deviceId, options);
- device.LastUserId = user.Id.ToString("N");
- device.LastUserName = user.Name;
+ if (DeviceOptionsUpdated != null)
+ {
+ DeviceOptionsUpdated(this, new GenericEventArgs<Tuple<string, DeviceOptions>>()
+ {
+ Argument = new Tuple<string, DeviceOptions>(deviceId, options)
+ });
}
+ }
- device.DateLastModified = DateTime.UtcNow;
+ public DeviceOptions GetDeviceOptions(string deviceId)
+ {
+ return _authRepo.GetDeviceOptions(deviceId);
+ }
- device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
+ public ClientCapabilities GetCapabilities(string id)
+ {
+ lock (_capabilitiesSyncLock)
+ {
+ ClientCapabilities result;
+ if (_capabilitiesCache.TryGetValue(id, out result))
+ {
+ return result;
+ }
- _repo.SaveDevice(device);
+ var path = Path.Combine(GetDevicePath(id), "capabilities.json");
+ try
+ {
+ return _json.DeserializeFromFile<ClientCapabilities>(path) ?? new ClientCapabilities();
+ }
+ catch
+ {
+ }
+ }
- return device;
+ return new ClientCapabilities();
}
- public void SaveCapabilities(string reportedId, ClientCapabilities capabilities)
+ public DeviceInfo GetDevice(string id)
{
- _repo.SaveCapabilities(reportedId, capabilities);
+ return GetDevice(id, true);
}
- public ClientCapabilities GetCapabilities(string reportedId)
+ private DeviceInfo GetDevice(string id, bool includeCapabilities)
{
- return _repo.GetCapabilities(reportedId);
- }
+ var session = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ DeviceId = id
- public DeviceInfo GetDevice(string id)
- {
- return _repo.GetDevice(id);
+ }).Items.FirstOrDefault();
+
+ var device = session == null ? null : ToDeviceInfo(session);
+
+ return device;
}
public QueryResult<DeviceInfo> GetDevices(DeviceQuery query)
{
- IEnumerable<DeviceInfo> devices = _repo.GetDevices();
+ var sessions = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ //UserId = query.UserId
+ HasUser = true
+
+ }).Items;
if (query.SupportsSync.HasValue)
{
var val = query.SupportsSync.Value;
- devices = devices.Where(i => i.Capabilities.SupportsSync == val);
+ sessions = sessions.Where(i => GetCapabilities(i.DeviceId).SupportsSync == val).ToArray();
}
- if (query.SupportsPersistentIdentifier.HasValue)
+ if (!query.UserId.Equals(Guid.Empty))
{
- var val = query.SupportsPersistentIdentifier.Value;
+ var user = _userManager.GetUserById(query.UserId);
- devices = devices.Where(i =>
- {
- var deviceVal = i.Capabilities.SupportsPersistentIdentifier;
- return deviceVal == val;
- });
+ sessions = sessions.Where(i => CanAccessDevice(user, i.DeviceId)).ToArray();
}
- if (!string.IsNullOrWhiteSpace(query.UserId))
- {
- devices = devices.Where(i => CanAccessDevice(query.UserId, i.Id));
- }
+ var array = sessions.Select(ToDeviceInfo).ToArray();
- var array = devices.ToArray();
return new QueryResult<DeviceInfo>
{
Items = array,
@@ -133,20 +169,59 @@ namespace Emby.Server.Implementations.Devices
};
}
- public void DeleteDevice(string id)
+ private DeviceInfo ToDeviceInfo(AuthenticationInfo authInfo)
+ {
+ var caps = GetCapabilities(authInfo.DeviceId);
+
+ return new DeviceInfo
+ {
+ AppName = authInfo.AppName,
+ AppVersion = authInfo.AppVersion,
+ Id = authInfo.DeviceId,
+ LastUserId = authInfo.UserId,
+ LastUserName = authInfo.UserName,
+ Name = authInfo.DeviceName,
+ DateLastActivity = authInfo.DateLastActivity,
+ IconUrl = caps == null ? null : caps.IconUrl
+ };
+ }
+
+ private string GetDevicesPath()
+ {
+ return Path.Combine(_config.ApplicationPaths.DataPath, "devices");
+ }
+
+ private string GetDevicePath(string id)
{
- _repo.DeleteDevice(id);
+ return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N"));
}
public ContentUploadHistory GetCameraUploadHistory(string deviceId)
{
- return _repo.GetCameraUploadHistory(deviceId);
+ var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
+
+ lock (_cameraUploadSyncLock)
+ {
+ try
+ {
+ return _json.DeserializeFromFile<ContentUploadHistory>(path);
+ }
+ catch (IOException)
+ {
+ return new ContentUploadHistory
+ {
+ DeviceId = deviceId
+ };
+ }
+ }
}
public async Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file)
{
- var device = GetDevice(deviceId);
- var path = GetUploadPath(device);
+ var device = GetDevice(deviceId, false);
+ var uploadPathInfo = GetUploadPath(device);
+
+ var path = uploadPathInfo.Item1;
if (!string.IsNullOrWhiteSpace(file.Album))
{
@@ -156,10 +231,12 @@ namespace Emby.Server.Implementations.Devices
path = Path.Combine(path, file.Name);
path = Path.ChangeExtension(path, MimeTypes.ToExtension(file.MimeType) ?? "jpg");
- _libraryMonitor.ReportFileSystemChangeBeginning(path);
-
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
+ await EnsureLibraryFolder(uploadPathInfo.Item2, uploadPathInfo.Item3).ConfigureAwait(false);
+
+ _libraryMonitor.ReportFileSystemChangeBeginning(path);
+
try
{
using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
@@ -167,7 +244,7 @@ namespace Emby.Server.Implementations.Devices
await stream.CopyToAsync(fs).ConfigureAwait(false);
}
- _repo.AddCameraUpload(deviceId, file);
+ AddCameraUpload(deviceId, file);
}
finally
{
@@ -187,65 +264,118 @@ namespace Emby.Server.Implementations.Devices
}
}
- private string GetUploadPath(DeviceInfo device)
+ private void AddCameraUpload(string deviceId, LocalFileInfo file)
{
- if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
+ var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
+
+ lock (_cameraUploadSyncLock)
{
- return device.CameraUploadPath;
+ ContentUploadHistory history;
+
+ try
+ {
+ history = _json.DeserializeFromFile<ContentUploadHistory>(path);
+ }
+ catch (IOException)
+ {
+ history = new ContentUploadHistory
+ {
+ DeviceId = deviceId
+ };
+ }
+
+ history.DeviceId = deviceId;
+
+ var list = history.FilesUploaded.ToList();
+ list.Add(file);
+ history.FilesUploaded = list.ToArray(list.Count);
+
+ _json.SerializeToFile(history, path);
}
+ }
+ internal Task EnsureLibraryFolder(string path, string name)
+ {
+ var existingFolders = _libraryManager
+ .RootFolder
+ .Children
+ .OfType<Folder>()
+ .Where(i => _fileSystem.AreEqual(path, i.Path) || _fileSystem.ContainsSubPath(i.Path, path))
+ .ToList();
+
+ if (existingFolders.Count > 0)
+ {
+ return Task.CompletedTask;
+ }
+
+ _fileSystem.CreateDirectory(path);
+
+ var libraryOptions = new LibraryOptions
+ {
+ PathInfos = new[] { new MediaPathInfo { Path = path } },
+ EnablePhotos = true,
+ EnableRealtimeMonitor = false,
+ SaveLocalMetadata = true
+ };
+
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ name = _localizationManager.GetLocalizedString("HeaderCameraUploads");
+ }
+
+ return _libraryManager.AddVirtualFolder(name, CollectionType.HomeVideos, libraryOptions, true);
+ }
+
+ private Tuple<string, string, string> GetUploadPath(DeviceInfo device)
+ {
var config = _config.GetUploadOptions();
var path = config.CameraUploadPath;
+
if (string.IsNullOrWhiteSpace(path))
{
path = DefaultCameraUploadsPath;
}
+ var topLibraryPath = path;
+
if (config.EnableCameraUploadSubfolders)
{
path = Path.Combine(path, _fileSystem.GetValidFilename(device.Name));
}
- return path;
- }
-
- private string DefaultCameraUploadsPath
- {
- get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
+ return new Tuple<string, string, string>(path, topLibraryPath, null);
}
- public void UpdateDeviceInfo(string id, DeviceOptions options)
+ internal string GetUploadsPath()
{
- var device = GetDevice(id);
-
- device.CustomName = options.CustomName;
- device.CameraUploadPath = options.CameraUploadPath;
+ var config = _config.GetUploadOptions();
+ var path = config.CameraUploadPath;
- device.Name = string.IsNullOrWhiteSpace(device.CustomName) ? device.ReportedName : device.CustomName;
+ if (string.IsNullOrWhiteSpace(path))
+ {
+ path = DefaultCameraUploadsPath;
+ }
- _repo.SaveDevice(device);
+ return path;
+ }
- EventHelper.FireEventIfNotNull(DeviceOptionsUpdated, this, new GenericEventArgs<DeviceInfo>(device), _logger);
+ private string DefaultCameraUploadsPath
+ {
+ get { return Path.Combine(_config.CommonApplicationPaths.DataPath, "camerauploads"); }
}
- public bool CanAccessDevice(string userId, string deviceId)
+ public bool CanAccessDevice(User user, string deviceId)
{
- if (string.IsNullOrWhiteSpace(userId))
+ if (user == null)
{
- throw new ArgumentNullException("userId");
+ throw new ArgumentException("user not found");
}
- if (string.IsNullOrWhiteSpace(deviceId))
+ if (string.IsNullOrEmpty(deviceId))
{
throw new ArgumentNullException("deviceId");
}
- var user = _userManager.GetUserById(userId);
-
- if (user == null)
- {
- throw new ArgumentException("user not found");
- }
-
if (!CanAccessDevice(user.Policy, deviceId))
{
var capabilities = GetCapabilities(deviceId);
@@ -271,15 +401,89 @@ namespace Emby.Server.Implementations.Devices
return true;
}
- return ListHelper.ContainsIgnoreCase(policy.EnabledDevices, id);
+ return policy.EnabledDevices.Contains(id, StringComparer.OrdinalIgnoreCase);
+ }
+ }
+
+ public class DeviceManagerEntryPoint : IServerEntryPoint
+ {
+ private readonly DeviceManager _deviceManager;
+ private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
+ private ILogger _logger;
+
+ public DeviceManagerEntryPoint(IDeviceManager deviceManager, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger)
+ {
+ _deviceManager = (DeviceManager)deviceManager;
+ _config = config;
+ _fileSystem = fileSystem;
+ _logger = logger;
+ }
+
+ public async void Run()
+ {
+ if (!_config.Configuration.CameraUploadUpgraded && _config.Configuration.IsStartupWizardCompleted)
+ {
+ var path = _deviceManager.GetUploadsPath();
+
+ if (_fileSystem.DirectoryExists(path))
+ {
+ try
+ {
+ await _deviceManager.EnsureLibraryFolder(path, null).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error creating camera uploads library", ex);
+ }
+
+ _config.Configuration.CameraUploadUpgraded = true;
+ _config.SaveConfiguration();
+ }
+ }
+ }
+
+ #region IDisposable Support
+ private bool disposedValue = false; // To detect redundant calls
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: dispose managed state (managed objects).
+ }
+
+ // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
+ // TODO: set large fields to null.
+
+ disposedValue = true;
+ }
+ }
+
+ // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
+ // ~DeviceManagerEntryPoint() {
+ // // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ // Dispose(false);
+ // }
+
+ // This code added to correctly implement the disposable pattern.
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ // TODO: uncomment the following line if the finalizer is overridden above.
+ // GC.SuppressFinalize(this);
}
+ #endregion
}
public class DevicesConfigStore : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
- return new List<ConfigurationStore>
+ return new ConfigurationStore[]
{
new ConfigurationStore
{