diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations')
5 files changed, 102 insertions, 67 deletions
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs index e26fdc607..87d59f356 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs @@ -1,4 +1,5 @@ using MediaBrowser.Model.Connect; +using System; using System.Collections.Generic; namespace MediaBrowser.Server.Implementations.Connect @@ -22,6 +23,12 @@ namespace MediaBrowser.Server.Implementations.Connect /// <value>The authorizations.</value> public List<ConnectAuthorization> PendingAuthorizations { get; set; } + /// <summary> + /// Gets or sets the last authorizations refresh. + /// </summary> + /// <value>The last authorizations refresh.</value> + public DateTime LastAuthorizationsRefresh { get; set; } + public ConnectData() { PendingAuthorizations = new List<ConnectAuthorization>(); diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 92b769f3b..40d911979 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -168,9 +168,7 @@ namespace MediaBrowser.Server.Implementations.Connect await CreateServerRegistration(wanApiAddress).ConfigureAwait(false); } - await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); - - await RefreshUserInfosInternal(CancellationToken.None).ConfigureAwait(false); + await RefreshAuthorizationsInternal(true, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { @@ -335,7 +333,7 @@ namespace MediaBrowser.Server.Implementations.Connect if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) { - await RemoveLink(user, connectUser.Id).ConfigureAwait(false); + await RemoveConnect(user, connectUser.Id).ConfigureAwait(false); } var url = GetConnectUrl("ServerAuthorizations"); @@ -377,15 +375,15 @@ 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; + user.Configuration.SyncConnectImage = false; + user.Configuration.SyncConnectName = false; _userManager.UpdateConfiguration(user, user.Configuration); - await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); + await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); return result; } - + public async Task<UserLinkResult> InviteUser(string sendingUserId, string connectUsername) { await _operationLock.WaitAsync().ConfigureAwait(false); @@ -452,19 +450,19 @@ namespace MediaBrowser.Server.Implementations.Connect result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); } - await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); + await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); return result; } - - public Task RemoveLink(string userId) + + public Task RemoveConnect(string userId) { var user = GetUser(userId); - return RemoveLink(user, user.ConnectUserId); + return RemoveConnect(user, user.ConnectUserId); } - private async Task RemoveLink(User user, string connectUserId) + private async Task RemoveConnect(User user, string connectUserId) { if (!string.IsNullOrWhiteSpace(connectUserId)) { @@ -474,7 +472,7 @@ namespace MediaBrowser.Server.Implementations.Connect user.ConnectAccessKey = null; user.ConnectUserName = null; user.ConnectUserId = null; - user.ConnectLinkType = UserLinkType.LinkedUser; + user.ConnectLinkType = null; await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } @@ -513,7 +511,8 @@ namespace MediaBrowser.Server.Implementations.Connect Email = response.Email, Id = response.Id, Name = response.Name, - IsActive = response.IsActive + IsActive = response.IsActive, + ImageUrl = response.ImageUrl }; } } @@ -529,7 +528,7 @@ namespace MediaBrowser.Server.Implementations.Connect try { - await RefreshAuthorizationsInternal(cancellationToken).ConfigureAwait(false); + await RefreshAuthorizationsInternal(true, cancellationToken).ConfigureAwait(false); } finally { @@ -537,7 +536,7 @@ namespace MediaBrowser.Server.Implementations.Connect } } - private async Task RefreshAuthorizationsInternal(CancellationToken cancellationToken) + private async Task RefreshAuthorizationsInternal(bool refreshImages, CancellationToken cancellationToken) { var url = GetConnectUrl("ServerAuthorizations"); @@ -557,7 +556,7 @@ namespace MediaBrowser.Server.Implementations.Connect { var list = _json.DeserializeFromStream<List<ServerUserAuthorizationResponse>>(stream); - await RefreshAuthorizations(list).ConfigureAwait(false); + await RefreshAuthorizations(list, refreshImages).ConfigureAwait(false); } } catch (Exception ex) @@ -566,7 +565,8 @@ namespace MediaBrowser.Server.Implementations.Connect } } - private async Task RefreshAuthorizations(List<ServerUserAuthorizationResponse> list) + private readonly SemaphoreSlim _connectImageSemaphore = new SemaphoreSlim(5, 5); + private async Task RefreshAuthorizations(List<ServerUserAuthorizationResponse> list, bool refreshImages) { var users = _userManager.Users.ToList(); @@ -583,13 +583,14 @@ namespace MediaBrowser.Server.Implementations.Connect user.ConnectUserId = null; user.ConnectAccessKey = null; user.ConnectUserName = null; + user.ConnectLinkType = null; await _userManager.UpdateUser(user).ConfigureAwait(false); - if (user.ConnectLinkType == UserLinkType.Guest) + if (user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest) { _logger.Debug("Deleting guest user {0}", user.Name); - //await _userManager.DeleteUser(user).ConfigureAwait(false); + await _userManager.DeleteUser(user).ConfigureAwait(false); } } else @@ -611,7 +612,6 @@ namespace MediaBrowser.Server.Implementations.Connect 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)) @@ -623,18 +623,29 @@ namespace MediaBrowser.Server.Implementations.Connect if (user == null) { // Add user - //user.Configuration.SyncConnectImage = user.ConnectLinkType == UserLinkType.Guest; - //user.Configuration.SyncConnectName = user.ConnectLinkType == UserLinkType.Guest; + user = await _userManager.CreateUser(connectEntry.UserName).ConfigureAwait(false); + + user.ConnectUserName = connectEntry.UserName; + user.ConnectUserId = connectEntry.UserId; + user.ConnectLinkType = UserLinkType.Guest; + user.ConnectAccessKey = connectEntry.AccessToken; + + await _userManager.UpdateUser(user).ConfigureAwait(false); + + user.Configuration.SyncConnectImage = true; + user.Configuration.SyncConnectName = true; + + _userManager.UpdateConfiguration(user, user.Configuration); } } else if (string.Equals(connectEntry.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase)) { pending.Add(new ConnectAuthorization { - ConnectUserId = connectEntry.UserId, - ImageUrl = connectEntry.UserImageUrl, - UserName = connectEntry.UserName, - Id = connectEntry.Id + ConnectUserId = connectEntry.UserId, + ImageUrl = connectEntry.UserImageUrl, + UserName = connectEntry.UserName, + Id = connectEntry.Id }); } } @@ -642,54 +653,40 @@ namespace MediaBrowser.Server.Implementations.Connect _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(); - } + await RefreshGuestNames(list, refreshImages).ConfigureAwait(false); } - private readonly SemaphoreSlim _connectImageSemaphore = new SemaphoreSlim(5, 5); - - private async Task RefreshUserInfosInternal(CancellationToken cancellationToken) + private async Task RefreshGuestNames(List<ServerUserAuthorizationResponse> list, bool refreshImages) { var users = _userManager.Users .Where(i => !string.IsNullOrEmpty(i.ConnectUserId) && (i.Configuration.SyncConnectImage || i.Configuration.SyncConnectName)) - .ToList(); + .ToList(); foreach (var user in users) { - cancellationToken.ThrowIfCancellationRequested(); + var authorization = list.FirstOrDefault(i => string.Equals(i.UserId, user.ConnectUserId, StringComparison.Ordinal)); - var connectUser = await GetConnectUser(new ConnectUserQuery + if (authorization == null) { - Id = user.ConnectUserId - - }, cancellationToken).ConfigureAwait(false); + _logger.Warn("Unable to find connect authorization record for user {0}", user.Name); + continue; + } if (user.Configuration.SyncConnectName) { - var changed = !string.Equals(connectUser.Name, user.Name, StringComparison.OrdinalIgnoreCase); + var changed = !string.Equals(authorization.UserName, user.Name, StringComparison.OrdinalIgnoreCase); if (changed) { - await user.Rename(connectUser.Name).ConfigureAwait(false); + await user.Rename(authorization.UserName).ConfigureAwait(false); } } if (user.Configuration.SyncConnectImage) { - var imageUrl = connectUser.ImageUrl; + var imageUrl = authorization.UserImageUrl; if (!string.IsNullOrWhiteSpace(imageUrl)) { @@ -699,12 +696,11 @@ namespace MediaBrowser.Server.Implementations.Connect { changed = true; } - else + else if (refreshImages) { using (var response = await _httpClient.SendAsync(new HttpRequestOptions { Url = imageUrl, - CancellationToken = cancellationToken, BufferContent = false }, "HEAD").ConfigureAwait(false)) @@ -720,13 +716,13 @@ namespace MediaBrowser.Server.Implementations.Connect if (changed) { - await _providerManager.SaveImage(user, imageUrl, _connectImageSemaphore, ImageType.Primary, null, cancellationToken).ConfigureAwait(false); - + await _providerManager.SaveImage(user, imageUrl, _connectImageSemaphore, ImageType.Primary, null, CancellationToken.None).ConfigureAwait(false); + await user.RefreshMetadata(new MetadataRefreshOptions { ForceSave = true, - }, cancellationToken).ConfigureAwait(false); + }, CancellationToken.None).ConfigureAwait(false); } } } @@ -735,6 +731,25 @@ namespace MediaBrowser.Server.Implementations.Connect public async Task<List<ConnectAuthorization>> GetPendingGuests() { + var time = DateTime.UtcNow - _data.LastAuthorizationsRefresh; + + if (time.TotalMinutes >= 5) + { + await _operationLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); + + try + { + await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); + + _data.LastAuthorizationsRefresh = DateTime.UtcNow; + CacheData(); + } + finally + { + _operationLock.Release(); + } + } + return _data.PendingAuthorizations.ToList(); } @@ -760,7 +775,7 @@ namespace MediaBrowser.Server.Implementations.Connect await CancelAuthorizationByConnectUserId(connectUserId).ConfigureAwait(false); - await RefreshAuthorizationsInternal(CancellationToken.None).ConfigureAwait(false); + await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); } private async Task CancelAuthorizationByConnectUserId(string connectUserId) diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 16a1dc516..e76bc4f80 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -2,6 +2,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Connect; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -61,6 +62,7 @@ namespace MediaBrowser.Server.Implementations.Library private readonly Func<IImageProcessor> _imageProcessorFactory; private readonly Func<IDtoService> _dtoServiceFactory; + private readonly Func<IConnectManager> _connectFactory; /// <summary> /// Initializes a new instance of the <see cref="UserManager" /> class. @@ -68,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.Library /// <param name="logger">The logger.</param> /// <param name="configurationManager">The configuration manager.</param> /// <param name="userRepository">The user repository.</param> - public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory) + public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory) { _logger = logger; UserRepository = userRepository; @@ -76,6 +78,7 @@ namespace MediaBrowser.Server.Implementations.Library _networkManager = networkManager; _imageProcessorFactory = imageProcessorFactory; _dtoServiceFactory = dtoServiceFactory; + _connectFactory = connectFactory; ConfigurationManager = configurationManager; Users = new List<User>(); } @@ -143,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.Library Users = await LoadUsers().ConfigureAwait(false); } - public async Task<bool> AuthenticateUser(string username, string password, string remoteEndPoint) + public async Task<bool> AuthenticateUser(string username, string passwordSha1, string remoteEndPoint) { if (string.IsNullOrWhiteSpace(username)) { @@ -157,11 +160,11 @@ namespace MediaBrowser.Server.Implementations.Library throw new AuthenticationException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name)); } - var success = string.Equals(GetPasswordHash(user), password.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase); + var success = string.Equals(GetPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase); if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword) { - success = string.Equals(GetLocalPasswordHash(user), password.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase); + success = string.Equals(GetLocalPasswordHash(user), passwordSha1.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase); } // Update LastActivityDate and LastLoginDate, then save @@ -433,6 +436,11 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("user"); } + if (user.ConnectLinkType.HasValue) + { + await _connectFactory().RemoveConnect(user.Id.ToString("N")).ConfigureAwait(false); + } + var allUsers = Users.ToList(); if (allUsers.FirstOrDefault(u => u.Id == user.Id) == null) @@ -514,10 +522,12 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>User.</returns> private User InstantiateNewUser(string name) { + var idSalt = ("MBUser" + name); + return new User { Name = name, - Id = ("MBUser" + name).GetMD5(), + Id = idSalt.GetMD5(), DateCreated = DateTime.UtcNow, DateModified = DateTime.UtcNow, UsesIdForConfigurationPath = true diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index c1e9ff5cd..ec275c8dc 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -606,7 +606,7 @@ "TabDevices": "Devices", "DeviceLastUsedByUserName": "Last used by {0}", "HeaderDeleteDevice": "Delete Device", - "DeleteDeviceConfirmation": "Are you sure you with to delete this device? It will reappear the next time a user signs in with it.", + "DeleteDeviceConfirmation": "Are you sure you wish to delete this device? It will reappear the next time a user signs in with it.", "LabelEnableCameraUploadFor": "Enable camera upload for:", "HeaderSelectUploadPath": "Select Upload Path", "LabelEnableCameraUploadForHelp": "Uploads will occur automatically in the background when signed into Media Browser." diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index e576180c4..c104d2738 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1229,7 +1229,10 @@ "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.", + "LabelConnectInviteUserHelp": "This is the username or email that your friend uses 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" + "ButtonSendInvitation": "Send Invitation", + "HeaderGuests": "Guests", + "HeaderLocalUsers": "Local Users", + "HeaderPendingInvitations": "Pending Invitations" } |
