aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectData.cs17
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectManager.cs359
-rw-r--r--MediaBrowser.Server.Implementations/Connect/Responses.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Devices/DeviceManager.cs41
-rw-r--r--MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs21
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserViewManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json10
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs24
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;