diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations')
8 files changed, 386 insertions, 90 deletions
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs index dfbeccd4d..e26fdc607 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs @@ -1,4 +1,4 @@ -using System; +using MediaBrowser.Model.Connect; using System.Collections.Generic; namespace MediaBrowser.Server.Implementations.Connect @@ -20,22 +20,11 @@ namespace MediaBrowser.Server.Implementations.Connect /// Gets or sets the authorizations. /// </summary> /// <value>The authorizations.</value> - public List<ConnectAuthorization> Authorizations { get; set; } + public List<ConnectAuthorization> PendingAuthorizations { get; set; } public ConnectData() { - Authorizations = new List<ConnectAuthorization>(); - } - } - - public class ConnectAuthorization - { - public string LocalUserId { get; set; } - public string AccessToken { get; set; } - - public ConnectAuthorization() - { - AccessToken = new Guid().ToString("N"); + PendingAuthorizations = new List<ConnectAuthorization>(); } } } diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index a4535a57c..4e3bbbcb2 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -5,8 +5,10 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Connect; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Security; using MediaBrowser.Model.Connect; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; @@ -24,7 +26,7 @@ namespace MediaBrowser.Server.Implementations.Connect { public class ConnectManager : IConnectManager { - private SemaphoreSlim _operationLock = new SemaphoreSlim(1,1); + private readonly SemaphoreSlim _operationLock = new SemaphoreSlim(1, 1); private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; @@ -34,6 +36,7 @@ namespace MediaBrowser.Server.Implementations.Connect private readonly IServerApplicationHost _appHost; private readonly IServerConfigurationManager _config; private readonly IUserManager _userManager; + private readonly IProviderManager _providerManager; private ConnectData _data = new ConnectData(); @@ -90,7 +93,7 @@ namespace MediaBrowser.Server.Implementations.Connect IEncryptionManager encryption, IHttpClient httpClient, IServerApplicationHost appHost, - IServerConfigurationManager config, IUserManager userManager) + IServerConfigurationManager config, IUserManager userManager, IProviderManager providerManager) { _logger = logger; _appPaths = appPaths; @@ -100,6 +103,7 @@ namespace MediaBrowser.Server.Implementations.Connect _appHost = appHost; _config = config; _userManager = userManager; + _providerManager = providerManager; LoadCachedData(); } @@ -165,13 +169,15 @@ namespace MediaBrowser.Server.Implementations.Connect } await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); + + await RefreshUserInfosInternal(CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error registering with Connect", ex); } } - + private async Task CreateServerRegistration(string wanApiAddress) { var url = "Servers"; @@ -181,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.Connect { {"name", _appHost.FriendlyName}, {"url", wanApiAddress}, - {"systemid", _appHost.SystemId} + {"systemId", _appHost.SystemId} }; using (var stream = await _httpClient.Post(url, postData, CancellationToken.None).ConfigureAwait(false)) @@ -211,7 +217,7 @@ namespace MediaBrowser.Server.Implementations.Connect { {"name", _appHost.FriendlyName}, {"url", wanApiAddress}, - {"systemid", _appHost.SystemId} + {"systemId", _appHost.SystemId} }); SetServerAccessToken(options); @@ -222,6 +228,7 @@ namespace MediaBrowser.Server.Implementations.Connect } } + private readonly object _dataFileLock = new object(); private string CacheFilePath { get { return Path.Combine(_appPaths.DataPath, "connect.txt"); } @@ -239,7 +246,10 @@ namespace MediaBrowser.Server.Implementations.Connect var encrypted = _encryption.EncryptString(json); - File.WriteAllText(path, encrypted, Encoding.UTF8); + lock (_dataFileLock) + { + File.WriteAllText(path, encrypted, Encoding.UTF8); + } } catch (Exception ex) { @@ -253,11 +263,14 @@ namespace MediaBrowser.Server.Implementations.Connect try { - var encrypted = File.ReadAllText(path, Encoding.UTF8); + lock (_dataFileLock) + { + var encrypted = File.ReadAllText(path, Encoding.UTF8); - var json = _encryption.DecryptString(encrypted); + var json = _encryption.DecryptString(encrypted); - _data = _json.DeserializeFromString<ConnectData>(json); + _data = _json.DeserializeFromString<ConnectData>(json); + } } catch (IOException) { @@ -288,6 +301,20 @@ namespace MediaBrowser.Server.Implementations.Connect public async Task<UserLinkResult> LinkUser(string userId, string connectUsername) { + await _operationLock.WaitAsync().ConfigureAwait(false); + + try + { + return await LinkUserInternal(userId, connectUsername).ConfigureAwait(false); + } + finally + { + _operationLock.Release(); + } + } + + private async Task<UserLinkResult> LinkUserInternal(string userId, string connectUsername) + { if (string.IsNullOrWhiteSpace(connectUsername)) { throw new ArgumentNullException("connectUsername"); @@ -350,56 +377,98 @@ namespace MediaBrowser.Server.Implementations.Connect await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + user.Configuration.SyncConnectImage = user.ConnectLinkType == UserLinkType.Guest; + user.Configuration.SyncConnectName = user.ConnectLinkType == UserLinkType.Guest; + _userManager.UpdateConfiguration(user, user.Configuration); + + await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); + return result; } - - public Task RemoveLink(string userId) + + public async Task<UserLinkResult> InviteUser(string sendingUserId, string connectUsername) { - var user = GetUser(userId); + await _operationLock.WaitAsync().ConfigureAwait(false); - return RemoveLink(user, user.ConnectUserId); + try + { + return await InviteUserInternal(sendingUserId, connectUsername).ConfigureAwait(false); + } + finally + { + _operationLock.Release(); + } } - private async Task RemoveLink(User user, string connectUserId) + private async Task<UserLinkResult> InviteUserInternal(string sendingUserId, string connectUsername) { - if (!string.IsNullOrWhiteSpace(connectUserId)) + if (string.IsNullOrWhiteSpace(connectUsername)) { - var url = GetConnectUrl("ServerAuthorizations"); + throw new ArgumentNullException("connectUsername"); + } - var options = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None - }; + var connectUser = await GetConnectUser(new ConnectUserQuery + { + Name = connectUsername - var postData = new Dictionary<string, string> - { - {"serverId", ConnectServerId}, - {"userId", connectUserId} - }; + }, CancellationToken.None).ConfigureAwait(false); + + if (!connectUser.IsActive) + { + throw new ArgumentException("The Media Browser account has been disabled."); + } - options.SetPostData(postData); + var url = GetConnectUrl("ServerAuthorizations"); - SetServerAccessToken(options); + var options = new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None + }; - try - { - // No need to examine the response - using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) - { - } - } - catch (HttpException ex) - { - // If connect says the auth doesn't exist, we can handle that gracefully since this is a remove operation + var accessToken = Guid.NewGuid().ToString("N"); + var sendingUser = GetUser(sendingUserId); - if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) - { - throw; - } + var postData = new Dictionary<string, string> + { + {"serverId", ConnectServerId}, + {"userId", connectUser.Id}, + {"userType", "Guest"}, + {"accessToken", accessToken}, + {"requesterUserName", sendingUser.ConnectUserName} + }; - _logger.Debug("Connect returned a 404 when removing a user auth link. Handling it."); - } + options.SetPostData(postData); + + SetServerAccessToken(options); + + var result = new UserLinkResult(); + + // No need to examine the response + using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) + { + var response = _json.DeserializeFromStream<ServerUserAuthorizationResponse>(stream); + + result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); + } + + await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); + + return result; + } + + public Task RemoveLink(string userId) + { + var user = GetUser(userId); + + return RemoveLink(user, user.ConnectUserId); + } + + private async Task RemoveLink(User user, string connectUserId) + { + if (!string.IsNullOrWhiteSpace(connectUserId)) + { + await CancelAuthorizationByConnectUserId(connectUserId).ConfigureAwait(false); } user.ConnectAccessKey = null; @@ -472,24 +541,19 @@ namespace MediaBrowser.Server.Implementations.Connect { var url = GetConnectUrl("ServerAuthorizations"); + url += "?serverId=" + ConnectServerId; + var options = new HttpRequestOptions { Url = url, CancellationToken = cancellationToken }; - var postData = new Dictionary<string, string> - { - {"serverId", ConnectServerId} - }; - - options.SetPostData(postData); - SetServerAccessToken(options); try { - using (var stream = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content) + using (var stream = (await _httpClient.SendAsync(options, "GET").ConfigureAwait(false)).Content) { var list = _json.DeserializeFromStream<List<ServerUserAuthorizationResponse>>(stream); @@ -521,10 +585,11 @@ namespace MediaBrowser.Server.Implementations.Connect user.ConnectUserName = null; await _userManager.UpdateUser(user).ConfigureAwait(false); - + if (user.ConnectLinkType == UserLinkType.Guest) { - await _userManager.DeleteUser(user).ConfigureAwait(false); + _logger.Debug("Deleting guest user {0}", user.Name); + //await _userManager.DeleteUser(user).ConfigureAwait(false); } } else @@ -544,19 +609,195 @@ namespace MediaBrowser.Server.Implementations.Connect users = _userManager.Users.ToList(); + var pending = new List<ConnectAuthorization>(); + // TODO: Handle newly added guests that we don't know about foreach (var connectEntry in list) { - if (string.Equals(connectEntry.UserType, "guest", StringComparison.OrdinalIgnoreCase) && - string.Equals(connectEntry.AcceptStatus, "accepted", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(connectEntry.UserType, "guest", StringComparison.OrdinalIgnoreCase)) + { + if (string.Equals(connectEntry.AcceptStatus, "accepted", StringComparison.OrdinalIgnoreCase)) + { + var user = users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectEntry.UserId, StringComparison.OrdinalIgnoreCase)); + + if (user == null) + { + // Add user + } + } + else if (string.Equals(connectEntry.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase)) + { + pending.Add(new ConnectAuthorization + { + ConnectUserId = connectEntry.UserId, + ImageUrl = connectEntry.ImageUrl, + UserName = connectEntry.UserName, + Id = connectEntry.Id + }); + } + } + } + + _data.PendingAuthorizations = pending; + CacheData(); + } + + public async Task RefreshUserInfos(CancellationToken cancellationToken) + { + await _operationLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await RefreshUserInfosInternal(cancellationToken).ConfigureAwait(false); + } + finally + { + _operationLock.Release(); + } + } + + private readonly SemaphoreSlim _connectImageSemaphore = new SemaphoreSlim(5, 5); + + private async Task RefreshUserInfosInternal(CancellationToken cancellationToken) + { + var users = _userManager.Users + .Where(i => !string.IsNullOrEmpty(i.ConnectUserId) && + (i.Configuration.SyncConnectImage || i.Configuration.SyncConnectName)) + .ToList(); + + foreach (var user in users) + { + cancellationToken.ThrowIfCancellationRequested(); + + var connectUser = await GetConnectUser(new ConnectUserQuery { - var user = users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectEntry.UserId, StringComparison.OrdinalIgnoreCase)); + Id = user.ConnectUserId - if (user == null) + }, cancellationToken).ConfigureAwait(false); + + if (user.Configuration.SyncConnectName) + { + var changed = !string.Equals(connectUser.Name, user.Name, StringComparison.OrdinalIgnoreCase); + + if (changed) { - // Add user + await user.Rename(connectUser.Name).ConfigureAwait(false); } } + + if (user.Configuration.SyncConnectImage) + { + var imageUrl = connectUser.ImageUrl; + + if (!string.IsNullOrWhiteSpace(imageUrl)) + { + var changed = false; + + if (!user.HasImage(ImageType.Primary)) + { + changed = true; + } + else + { + using (var response = await _httpClient.SendAsync(new HttpRequestOptions + { + Url = imageUrl, + CancellationToken = cancellationToken, + BufferContent = false + + }, "HEAD").ConfigureAwait(false)) + { + var length = response.ContentLength; + + if (length != new FileInfo(user.GetImageInfo(ImageType.Primary, 0).Path).Length) + { + changed = true; + } + } + } + + if (changed) + { + await _providerManager.SaveImage(user, imageUrl, _connectImageSemaphore, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); + + await user.RefreshMetadata(new MetadataRefreshOptions + { + ForceSave = true, + + }, cancellationToken).ConfigureAwait(false); + } + } + } + } + } + + public async Task<List<ConnectAuthorization>> GetPendingGuests() + { + return _data.PendingAuthorizations.ToList(); + } + + public async Task CancelAuthorization(string id) + { + await _operationLock.WaitAsync().ConfigureAwait(false); + + try + { + await CancelAuthorizationInternal(id).ConfigureAwait(false); + } + finally + { + _operationLock.Release(); + } + } + + private async Task CancelAuthorizationInternal(string id) + { + var connectUserId = _data.PendingAuthorizations + .First(i => string.Equals(i.Id, id, StringComparison.Ordinal)) + .ConnectUserId; + + await CancelAuthorizationByConnectUserId(connectUserId).ConfigureAwait(false); + + await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); + } + + private async Task CancelAuthorizationByConnectUserId(string connectUserId) + { + var url = GetConnectUrl("ServerAuthorizations"); + + var options = new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None + }; + + var postData = new Dictionary<string, string> + { + {"serverId", ConnectServerId}, + {"userId", connectUserId} + }; + + options.SetPostData(postData); + + SetServerAccessToken(options); + + try + { + // No need to examine the response + using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) + { + } + } + catch (HttpException ex) + { + // If connect says the auth doesn't exist, we can handle that gracefully since this is a remove operation + + if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) + { + throw; + } + + _logger.Debug("Connect returned a 404 when removing a user auth link. Handling it."); } } } diff --git a/MediaBrowser.Server.Implementations/Connect/Responses.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs index eeb56d1c9..862e79559 100644 --- a/MediaBrowser.Server.Implementations/Connect/Responses.cs +++ b/MediaBrowser.Server.Implementations/Connect/Responses.cs @@ -36,5 +36,7 @@ namespace MediaBrowser.Server.Implementations.Connect public bool IsActive { get; set; } public string AcceptStatus { get; set; } public string UserType { get; set; } + public string ImageUrl { get; set; } + public string UserName { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs index 6d4238bdf..e2c729b2d 100644 --- a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs +++ b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs @@ -1,8 +1,11 @@ using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Events; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Devices; +using MediaBrowser.Model.Events; +using MediaBrowser.Model.Logging; using MediaBrowser.Model.Session; using System; using System.Collections.Generic; @@ -19,24 +22,31 @@ namespace MediaBrowser.Server.Implementations.Devices private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _libraryMonitor; private readonly IConfigurationManager _config; - - public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IConfigurationManager config) + private readonly ILogger _logger; + + /// <summary> + /// Occurs when [device options updated]. + /// </summary> + public event EventHandler<GenericEventArgs<DeviceInfo>> DeviceOptionsUpdated; + + public DeviceManager(IDeviceRepository repo, IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IConfigurationManager config, ILogger logger) { _repo = repo; _userManager = userManager; _fileSystem = fileSystem; _libraryMonitor = libraryMonitor; _config = config; + _logger = logger; } - public Task RegisterDevice(string reportedId, string name, string appName, string usedByUserId) + public async Task<DeviceInfo> RegisterDevice(string reportedId, string name, string appName, string usedByUserId) { var device = GetDevice(reportedId) ?? new DeviceInfo { Id = reportedId }; - device.Name = name; + device.ReportedName = name; device.AppName = appName; if (!string.IsNullOrWhiteSpace(usedByUserId)) @@ -49,7 +59,9 @@ namespace MediaBrowser.Server.Implementations.Devices device.DateLastModified = DateTime.UtcNow; - return _repo.SaveDevice(device); + await _repo.SaveDevice(device).ConfigureAwait(false); + + return device; } public Task SaveCapabilities(string reportedId, ClientCapabilities capabilities) @@ -114,10 +126,13 @@ namespace MediaBrowser.Server.Implementations.Devices private string GetUploadPath(string deviceId) { - var config = _config.GetUploadOptions(); - var device = GetDevice(deviceId); + if (!string.IsNullOrWhiteSpace(device.CameraUploadPath)) + { + return device.CameraUploadPath; + } + var config = _config.GetUploadOptions(); if (!string.IsNullOrWhiteSpace(config.CameraUploadPath)) { return config.CameraUploadPath; @@ -132,6 +147,18 @@ namespace MediaBrowser.Server.Implementations.Devices return path; } + + public async Task UpdateDeviceInfo(string id, DeviceOptions options) + { + var device = GetDevice(id); + + device.CustomName = options.CustomName; + device.CameraUploadPath = options.CameraUploadPath; + + await _repo.SaveDevice(device).ConfigureAwait(false); + + EventHelper.FireEventIfNotNull(DeviceOptionsUpdated, this, new GenericEventArgs<DeviceInfo>(device), _logger); + } } public class DevicesConfigStore : IConfigurationFactory diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 09e0e91f5..ce6224295 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -310,12 +310,23 @@ namespace MediaBrowser.Server.Implementations.IO /// <param name="watcher">The watcher.</param> private void DisposeWatcher(FileSystemWatcher watcher) { - Logger.Info("Stopping directory watching for path {0}", watcher.Path); - - watcher.EnableRaisingEvents = false; - watcher.Dispose(); + try + { + using (watcher) + { + Logger.Info("Stopping directory watching for path {0}", watcher.Path); - RemoveWatcherFromList(watcher); + watcher.EnableRaisingEvents = false; + } + } + catch + { + + } + finally + { + RemoveWatcherFromList(watcher); + } } /// <summary> diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index b12ae32a8..768c29ce0 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -2,9 +2,7 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Localization; diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index d7a99638e..e576180c4 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -75,7 +75,7 @@ "TabSecurity": "Security", "ButtonAddUser": "Add User", "ButtonAddLocalUser": "Add Local User", - "ButtonInviteMediaBrowserUser": "Invite Media Browser User", + "ButtonInviteUser": "Invite User", "ButtonSave": "Save", "ButtonResetPassword": "Reset Password", "LabelNewPassword": "New password:", @@ -1225,5 +1225,11 @@ "LabelCameraUploadPath": "Camera upload path:", "LabelCameraUploadPathHelp": "Select a custom upload path, if desired. If unspecified a default folder will be used.", "LabelCreateCameraUploadSubfolder": "Create a subfolder for each device", - "LabelCreateCameraUploadSubfolderHelp": "Specific folders can be assigned to a device by clicking on it from the Devices page." + "LabelCreateCameraUploadSubfolderHelp": "Specific folders can be assigned to a device by clicking on it from the Devices page.", + "LabelCustomDeviceDisplayName": "Display name:", + "LabelCustomDeviceDisplayNameHelp": "Supply a custom display name or leave empty to use the name reported by the device.", + "HeaderInviteUser": "Invite User", + "LabelConnectInviteHelp": "This is the username or email used to sign in to the Media Browser website.", + "HeaderInviteUserHelp": "Sharing your media with friends is easier than ever before with Media Browser Connect.", + "ButtonSendInvitation": "Send Invitation" } diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index c16044bd3..21467ccda 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -14,6 +14,7 @@ using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Devices; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; using MediaBrowser.Model.Library; @@ -129,6 +130,19 @@ namespace MediaBrowser.Server.Implementations.Session _httpClient = httpClient; _authRepo = authRepo; _deviceManager = deviceManager; + + _deviceManager.DeviceOptionsUpdated += _deviceManager_DeviceOptionsUpdated; + } + + void _deviceManager_DeviceOptionsUpdated(object sender, GenericEventArgs<DeviceInfo> e) + { + foreach (var session in Sessions) + { + if (string.Equals(session.DeviceId, e.Argument.Id)) + { + session.DeviceName = e.Argument.Name; + } + } } /// <summary> @@ -397,6 +411,7 @@ namespace MediaBrowser.Server.Implementations.Session try { SessionInfo connection; + DeviceInfo device = null; if (!_activeConnections.TryGetValue(key, out connection)) { @@ -421,10 +436,17 @@ namespace MediaBrowser.Server.Implementations.Session if (!string.IsNullOrEmpty(deviceId)) { var userIdString = userId.HasValue ? userId.Value.ToString("N") : null; - await _deviceManager.RegisterDevice(deviceId, deviceName, clientType, userIdString).ConfigureAwait(false); + device = await _deviceManager.RegisterDevice(deviceId, deviceName, clientType, userIdString).ConfigureAwait(false); } } + device = device ?? _deviceManager.GetDevice(deviceId); + + if (!string.IsNullOrEmpty(device.CustomName)) + { + deviceName = device.CustomName; + } + connection.DeviceName = deviceName; connection.UserId = userId; connection.UserName = username; |
