From 5c615fa02448813499ed87f2a1c2b937c7a7dcd5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 11:10:51 -0400 Subject: [PATCH] add connect linking --- MediaBrowser.Api/ConnectService.cs | 63 ++++++ .../Library/LibraryStructureService.cs | 2 +- MediaBrowser.Api/LiveTv/LiveTvService.cs | 6 +- MediaBrowser.Api/MediaBrowser.Api.csproj | 1 + .../Playback/BaseStreamingService.cs | 2 +- MediaBrowser.Api/PlaylistService.cs | 2 +- MediaBrowser.Api/TvShowsService.cs | 2 +- .../UserLibrary/PlaystateService.cs | 4 +- .../UserLibrary/UserLibraryService.cs | 2 +- .../BaseApplicationHost.cs | 2 +- .../Devices/DeviceId.cs | 24 +- .../Connect/ConnectInvitationRequest.cs | 20 ++ .../Connect/ConnectUser.cs | 22 ++ .../Connect/ConnectUserLink.cs | 10 + .../Connect/IConnectManager.cs | 29 ++- MediaBrowser.Controller/Entities/User.cs | 33 ++- .../Library/IUserManager.cs | 7 + .../MediaBrowser.Controller.csproj | 3 + .../Net/LoggedAttribute.cs | 2 +- .../ContentDirectory/ContentDirectory.cs | 4 +- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 2 +- .../Configuration/UserConfiguration.cs | 10 +- .../Channels/ChannelManager.cs | 14 +- .../Connect/ConnectData.cs | 26 ++- .../Connect/ConnectManager.cs | 209 ++++++++++++++++-- ...erRegistrationResponse.cs => Responses.cs} | 10 + .../HttpServer/Security/AuthService.cs | 2 +- .../Library/SearchEngine.cs | 2 +- .../Library/UserManager.cs | 16 +- .../Library/UserViewManager.cs | 2 +- .../LiveTv/LiveTvManager.cs | 16 +- .../Localization/JavaScript/javascript.json | 7 +- .../Localization/Server/server.json | 6 +- ...MediaBrowser.Server.Implementations.csproj | 2 +- .../Notifications/NotificationManager.cs | 2 +- .../Playlists/PlaylistManager.cs | 6 +- .../Session/SessionManager.cs | 4 +- .../TV/TVSeriesManager.cs | 4 +- .../ApplicationHost.cs | 2 +- .../FFMpeg/FFMpegDownloader.cs | 33 ++- .../MediaBrowser.WebDashboard.csproj | 3 + .../Savers/BaseNfoSaver.cs | 2 +- 42 files changed, 542 insertions(+), 78 deletions(-) create mode 100644 MediaBrowser.Api/ConnectService.cs create mode 100644 MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs create mode 100644 MediaBrowser.Controller/Connect/ConnectUser.cs create mode 100644 MediaBrowser.Controller/Connect/ConnectUserLink.cs rename MediaBrowser.Server.Implementations/Connect/{ServerRegistrationResponse.cs => Responses.cs} (59%) diff --git a/MediaBrowser.Api/ConnectService.cs b/MediaBrowser.Api/ConnectService.cs new file mode 100644 index 0000000000..80f6d4810e --- /dev/null +++ b/MediaBrowser.Api/ConnectService.cs @@ -0,0 +1,63 @@ +using System.Threading.Tasks; +using MediaBrowser.Controller.Connect; +using MediaBrowser.Controller.Net; +using ServiceStack; + +namespace MediaBrowser.Api +{ + [Route("/Users/{Id}/Connect/Info", "GET", Summary = "Gets connect info for a user")] + public class GetConnectUserInfo : IReturn + { + [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Users/{Id}/Connect/Link", "POST", Summary = "Creates a Connect link for a user")] + public class CreateConnectLink : IReturn + { + [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string Id { get; set; } + + [ApiMember(Name = "ConnectUsername", Description = "Connect username", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] + public string ConnectUsername { get; set; } + } + + [Route("/Users/{Id}/Connect/Link", "DELETE", Summary = "Removes a Connect link for a user")] + public class DeleteConnectLink : IReturn + { + [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] + public string Id { get; set; } + } + + [Authenticated] + public class ConnectService : BaseApiService + { + private readonly IConnectManager _connectManager; + + public ConnectService(IConnectManager connectManager) + { + _connectManager = connectManager; + } + + public object Get(GetConnectUserInfo request) + { + var result = _connectManager.GetUserInfo(request.Id); + + return ToOptimizedResult(result); + } + + public void Post(CreateConnectLink request) + { + var task = _connectManager.LinkUser(request.Id, request.ConnectUsername); + + Task.WaitAll(task); + } + + public void Delete(DeleteConnectLink request) + { + var task = _connectManager.RemoveLink(request.Id); + + Task.WaitAll(task); + } + } +} diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs index c3ef587685..f56daca1e7 100644 --- a/MediaBrowser.Api/Library/LibraryStructureService.cs +++ b/MediaBrowser.Api/Library/LibraryStructureService.cs @@ -195,7 +195,7 @@ namespace MediaBrowser.Api.Library } else { - var user = _userManager.GetUserById(new Guid(request.UserId)); + var user = _userManager.GetUserById(request.UserId); var result = _libraryManager.GetVirtualFolders(user).OrderBy(i => i.Name).ToList(); diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 35420c9360..cd21265778 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -321,7 +321,7 @@ namespace MediaBrowser.Api.LiveTv public async Task Get(GetChannel request) { - var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(new Guid(request.UserId)); + var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId); var result = await _liveTvManager.GetChannel(request.Id, CancellationToken.None, user).ConfigureAwait(false); @@ -406,7 +406,7 @@ namespace MediaBrowser.Api.LiveTv public async Task Get(GetRecording request) { - var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(new Guid(request.UserId)); + var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId); var result = await _liveTvManager.GetRecording(request.Id, CancellationToken.None, user).ConfigureAwait(false); @@ -514,7 +514,7 @@ namespace MediaBrowser.Api.LiveTv public async Task Get(GetProgram request) { - var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(new Guid(request.UserId)); + var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId); var result = await _liveTvManager.GetProgram(request.Id, CancellationToken.None, user).ConfigureAwait(false); diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 5cb9ebb1b0..db939366ad 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -70,6 +70,7 @@ + diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9a4b500d8f..f1b84875d1 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -784,7 +784,7 @@ namespace MediaBrowser.Api.Playback get { #if __MonoCS__ - return false; + return true; #endif try diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs index 5f4ced12e6..1318b322ac 100644 --- a/MediaBrowser.Api/PlaylistService.cs +++ b/MediaBrowser.Api/PlaylistService.cs @@ -137,7 +137,7 @@ namespace MediaBrowser.Api public object Get(GetPlaylistItems request) { var playlist = (Playlist)_libraryManager.GetItemById(request.Id); - var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(new Guid(request.UserId)) : null; + var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; var items = playlist.GetManageableItems().ToArray(); diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 20a3d38375..f3df6c7b02 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -282,7 +282,7 @@ namespace MediaBrowser.Api UserId = request.UserId }); - var user = _userManager.GetUserById(new Guid(request.UserId)); + var user = _userManager.GetUserById(request.UserId); var fields = request.GetItemFields().ToList(); diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index 2abb76dc82..874d2bfa18 100644 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs @@ -245,7 +245,7 @@ namespace MediaBrowser.Api.UserLibrary foreach (var additionalUserInfo in session.AdditionalUsers) { - var additionalUser = _userManager.GetUserById(new Guid(additionalUserInfo.UserId)); + var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId); await UpdatePlayedStatus(additionalUser, request.Id, true, datePlayed).ConfigureAwait(false); } @@ -353,7 +353,7 @@ namespace MediaBrowser.Api.UserLibrary foreach (var additionalUserInfo in session.AdditionalUsers) { - var additionalUser = _userManager.GetUserById(new Guid(additionalUserInfo.UserId)); + var additionalUser = _userManager.GetUserById(additionalUserInfo.UserId); await UpdatePlayedStatus(additionalUser, request.Id, false, null).ConfigureAwait(false); } diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index 44b5b0e9b8..8414241d5e 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -402,7 +402,7 @@ namespace MediaBrowser.Api.UserLibrary public async Task Get(GetUserViews request) { - var user = _userManager.GetUserById(new Guid(request.UserId)); + var user = _userManager.GetUserById(request.UserId); // Get everything var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList(); diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index 011dd76ee6..c59d1a3b00 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -186,7 +186,7 @@ namespace MediaBrowser.Common.Implementations { if (_deviceId == null) { - _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId")); + _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), NetworkManager); } return _deviceId.Value; diff --git a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs index ce69843fb9..5af236026e 100644 --- a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs +++ b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs @@ -1,4 +1,6 @@ using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; using MediaBrowser.Model.Logging; using System; using System.IO; @@ -9,6 +11,7 @@ namespace MediaBrowser.Common.Implementations.Devices public class DeviceId { private readonly IApplicationPaths _appPaths; + private readonly INetworkManager _networkManager; private readonly ILogger _logger; private readonly object _syncLock = new object(); @@ -67,7 +70,23 @@ namespace MediaBrowser.Common.Implementations.Devices private string GetNewId() { - return Guid.NewGuid().ToString("N"); + // When generating an Id, base it off of the app path + mac address + // But we can't fail here, so if we can't get the mac address then just use a random guid + + string mac; + + try + { + mac = _networkManager.GetMacAddress(); + } + catch + { + mac = Guid.NewGuid().ToString("N"); + } + + mac += "-" + _appPaths.ApplicationPath; + + return mac.GetMD5().ToString("N"); } private string GetDeviceId() @@ -85,10 +104,11 @@ namespace MediaBrowser.Common.Implementations.Devices private string _id; - public DeviceId(IApplicationPaths appPaths, ILogger logger) + public DeviceId(IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager) { _appPaths = appPaths; _logger = logger; + _networkManager = networkManager; } public string Value diff --git a/MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs b/MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs new file mode 100644 index 0000000000..91516723bf --- /dev/null +++ b/MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs @@ -0,0 +1,20 @@ + +namespace MediaBrowser.Controller.Connect +{ + public class ConnectInvitationRequest + { + public string LocalUserId { get; set; } + + public string Username { get; set; } + + public string RequesterUserId { get; set; } + + public ConnectUserType Type { get; set; } + } + + public enum ConnectUserType + { + LinkedUser = 1, + Guest = 2 + } +} diff --git a/MediaBrowser.Controller/Connect/ConnectUser.cs b/MediaBrowser.Controller/Connect/ConnectUser.cs new file mode 100644 index 0000000000..c640f90952 --- /dev/null +++ b/MediaBrowser.Controller/Connect/ConnectUser.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Connect +{ + public class ConnectUser + { + public string Id { get; set; } + public string Name { get; set; } + public string Email { get; set; } + } + + public class ConnectUserQuery + { + public string Id { get; set; } + public string Name { get; set; } + public string Email { get; set; } + } +} diff --git a/MediaBrowser.Controller/Connect/ConnectUserLink.cs b/MediaBrowser.Controller/Connect/ConnectUserLink.cs new file mode 100644 index 0000000000..93de6d8b4e --- /dev/null +++ b/MediaBrowser.Controller/Connect/ConnectUserLink.cs @@ -0,0 +1,10 @@ + +namespace MediaBrowser.Controller.Connect +{ + public class ConnectUserLink + { + public string Username { get; set; } + public string UserId { get; set; } + public string LocalUserId { get; set; } + } +} diff --git a/MediaBrowser.Controller/Connect/IConnectManager.cs b/MediaBrowser.Controller/Connect/IConnectManager.cs index 2e52591f5c..6c2128cd3f 100644 --- a/MediaBrowser.Controller/Connect/IConnectManager.cs +++ b/MediaBrowser.Controller/Connect/IConnectManager.cs @@ -1,8 +1,35 @@ - +using System.Threading.Tasks; + namespace MediaBrowser.Controller.Connect { public interface IConnectManager { + /// + /// Gets the wan API address. + /// + /// The wan API address. string WanApiAddress { get; } + + /// + /// Gets the user information. + /// + /// The user identifier. + /// ConnectUserInfo. + ConnectUserLink GetUserInfo(string userId); + + /// + /// Links the user. + /// + /// The user identifier. + /// The connect username. + /// Task. + Task LinkUser(string userId, string connectUsername); + + /// + /// Removes the link. + /// + /// The user identifier. + /// Task. + Task RemoveLink(string userId); } } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index e4fd929ffd..c0c7a6c531 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -19,6 +19,12 @@ namespace MediaBrowser.Controller.Entities public static IUserManager UserManager { get; set; } public static IXmlSerializer XmlSerializer { get; set; } + /// + /// From now on all user paths will be Id-based. + /// This is for backwards compatibility. + /// + public bool UsesIdForConfigurationPath { get; set; } + /// /// Gets or sets the password. /// @@ -26,6 +32,10 @@ namespace MediaBrowser.Controller.Entities public string Password { get; set; } public string LocalPassword { get; set; } + public string ConnectUserName { get; set; } + public string ConnectUserId { get; set; } + public string ConnectAccessKey { get; set; } + /// /// Gets or sets the path. /// @@ -136,12 +146,14 @@ namespace MediaBrowser.Controller.Entities { if (string.IsNullOrEmpty(newName)) { - throw new ArgumentNullException(); + throw new ArgumentNullException("newName"); } // If only the casing is changing, leave the file system alone - if (!newName.Equals(Name, StringComparison.OrdinalIgnoreCase)) + if (!UsesIdForConfigurationPath && !newName.Equals(Name, StringComparison.OrdinalIgnoreCase)) { + UsesIdForConfigurationPath = true; + // Move configuration var newConfigDirectory = GetConfigurationDirectoryPath(newName); var oldConfigurationDirectory = ConfigurationDirectoryPath; @@ -168,7 +180,8 @@ namespace MediaBrowser.Controller.Entities { ReplaceAllMetadata = true, ImageRefreshMode = ImageRefreshMode.FullRefresh, - MetadataRefreshMode = MetadataRefreshMode.FullRefresh + MetadataRefreshMode = MetadataRefreshMode.FullRefresh, + ForceSave = true }, CancellationToken.None); } @@ -183,7 +196,7 @@ namespace MediaBrowser.Controller.Entities /// /// The configuration directory path. [IgnoreDataMember] - public string ConfigurationDirectoryPath + private string ConfigurationDirectoryPath { get { @@ -203,9 +216,17 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("username"); } - var safeFolderName = FileSystem.GetValidFilename(username); + var parentPath = ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath; - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName); + // Legacy + if (!UsesIdForConfigurationPath) + { + var safeFolderName = FileSystem.GetValidFilename(username); + + return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName); + } + + return System.IO.Path.Combine(parentPath, Id.ToString("N")); } /// diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs index a5d949c8a2..3efdbea768 100644 --- a/MediaBrowser.Controller/Library/IUserManager.cs +++ b/MediaBrowser.Controller/Library/IUserManager.cs @@ -49,6 +49,13 @@ namespace MediaBrowser.Controller.Library /// User GetUserById(Guid id); + /// + /// Gets the user by identifier. + /// + /// The identifier. + /// User. + User GetUserById(string id); + /// /// Authenticates a User and returns a result indicating whether or not it succeeded /// diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 1813d9f08b..1d23a82a9e 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -99,6 +99,9 @@ + + + diff --git a/MediaBrowser.Controller/Net/LoggedAttribute.cs b/MediaBrowser.Controller/Net/LoggedAttribute.cs index 6df72f7a7e..ea07b1c7f5 100644 --- a/MediaBrowser.Controller/Net/LoggedAttribute.cs +++ b/MediaBrowser.Controller/Net/LoggedAttribute.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Net { var userId = auth.UserId; - user = UserManager.GetUserById(new Guid(userId)); + user = UserManager.GetUserById(userId); } string deviceId = auth.DeviceId; diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs index f594b4471d..dce93ae4e9 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.Dlna.ContentDirectory { if (!string.IsNullOrEmpty(profile.UserId)) { - var user = _userManager.GetUserById(new Guid(profile.UserId)); + var user = _userManager.GetUserById(profile.UserId); if (user != null) { @@ -93,7 +93,7 @@ namespace MediaBrowser.Dlna.ContentDirectory if (!string.IsNullOrEmpty(userId)) { - var user = _userManager.GetUserById(new Guid(userId)); + var user = _userManager.GetUserById(userId); if (user != null) { diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 961b501460..bef3f6d0e8 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -281,7 +281,7 @@ namespace MediaBrowser.Dlna.PlayTo { _logger.Debug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand); - var user = String.IsNullOrEmpty(command.ControllingUserId) ? null : _userManager.GetUserById(new Guid(command.ControllingUserId)); + var user = String.IsNullOrEmpty(command.ControllingUserId) ? null : _userManager.GetUserById(command.ControllingUserId); var items = new List(); foreach (string id in command.ItemIds) diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index b48018c9a2..3f25ba656b 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -78,14 +78,15 @@ namespace MediaBrowser.Model.Configuration public bool EnableLocalPassword { get; set; } public string[] OrderedViews { get; set; } - + + public bool SyncConnectName { get; set; } + public bool SyncConnectImage { get; set; } + /// /// Initializes a new instance of the class. /// public UserConfiguration() { - IsAdministrator = true; - PlayDefaultAudioTrack = true; EnableRemoteControlOfOtherUsers = true; EnableLiveTvManagement = true; @@ -101,6 +102,9 @@ namespace MediaBrowser.Model.Configuration ExcludeFoldersFromGrouping = new string[] { }; DisplayCollectionsView = true; DisplayFoldersView = true; + + SyncConnectName = true; + SyncConnectImage = true; } } } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index c7ca6bb30c..dfd24a248c 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -110,7 +110,7 @@ namespace MediaBrowser.Server.Implementations.Channels { var user = string.IsNullOrWhiteSpace(query.UserId) ? null - : _userManager.GetUserById(new Guid(query.UserId)); + : _userManager.GetUserById(query.UserId); var channels = GetAllChannels() .Select(GetChannelEntity) @@ -163,7 +163,7 @@ namespace MediaBrowser.Server.Implementations.Channels { var user = string.IsNullOrWhiteSpace(query.UserId) ? null - : _userManager.GetUserById(new Guid(query.UserId)); + : _userManager.GetUserById(query.UserId); var internalResult = await GetChannelsInternal(query, cancellationToken).ConfigureAwait(false); @@ -565,7 +565,7 @@ namespace MediaBrowser.Server.Implementations.Channels { var user = string.IsNullOrWhiteSpace(query.UserId) ? null - : _userManager.GetUserById(new Guid(query.UserId)); + : _userManager.GetUserById(query.UserId); if (!string.IsNullOrWhiteSpace(query.UserId) && user == null) { @@ -724,7 +724,7 @@ namespace MediaBrowser.Server.Implementations.Channels { var user = string.IsNullOrWhiteSpace(query.UserId) ? null - : _userManager.GetUserById(new Guid(query.UserId)); + : _userManager.GetUserById(query.UserId); var channels = GetAllChannels(); @@ -897,7 +897,7 @@ namespace MediaBrowser.Server.Implementations.Channels var user = string.IsNullOrWhiteSpace(query.UserId) ? null - : _userManager.GetUserById(new Guid(query.UserId)); + : _userManager.GetUserById(query.UserId); ChannelItemSortField? sortField = null; ChannelItemSortField parsedField; @@ -942,7 +942,7 @@ namespace MediaBrowser.Server.Implementations.Channels { var user = string.IsNullOrWhiteSpace(query.UserId) ? null - : _userManager.GetUserById(new Guid(query.UserId)); + : _userManager.GetUserById(query.UserId); var internalResult = await GetChannelItemsInternal(query, cancellationToken).ConfigureAwait(false); @@ -1356,7 +1356,7 @@ namespace MediaBrowser.Server.Implementations.Channels public async Task GetChannelFolder(string userId, CancellationToken cancellationToken) { - var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(new Guid(userId)); + var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId); // Get everything var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList(); diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs index 1816b103ee..dfbeccd4d3 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs @@ -1,4 +1,6 @@ - +using System; +using System.Collections.Generic; + namespace MediaBrowser.Server.Implementations.Connect { public class ConnectData @@ -13,5 +15,27 @@ namespace MediaBrowser.Server.Implementations.Connect /// /// The access key. public string AccessKey { get; set; } + + /// + /// Gets or sets the authorizations. + /// + /// The authorizations. + public List Authorizations { get; set; } + + public ConnectData() + { + Authorizations = new List(); + } + } + + public class ConnectAuthorization + { + public string LocalUserId { get; set; } + public string AccessToken { get; set; } + + public ConnectAuthorization() + { + AccessToken = new Guid().ToString("N"); + } } } diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 3ea54835d2..e3e1b39cc6 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -3,6 +3,8 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Connect; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Security; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; @@ -27,9 +29,18 @@ namespace MediaBrowser.Server.Implementations.Connect private readonly IHttpClient _httpClient; private readonly IServerApplicationHost _appHost; private readonly IServerConfigurationManager _config; + private readonly IUserManager _userManager; - public string ConnectServerId { get; set; } - public string ConnectAccessKey { get; set; } + private ConnectData _data = new ConnectData(); + + public string ConnectServerId + { + get { return _data.ServerId; } + } + public string ConnectAccessKey + { + get { return _data.AccessKey; } + } public string DiscoveredWanIpAddress { get; private set; } @@ -47,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.Connect return address; } } - + public string WanApiAddress { get @@ -75,7 +86,7 @@ namespace MediaBrowser.Server.Implementations.Connect IEncryptionManager encryption, IHttpClient httpClient, IServerApplicationHost appHost, - IServerConfigurationManager config) + IServerConfigurationManager config, IUserManager userManager) { _logger = logger; _appPaths = appPaths; @@ -84,6 +95,7 @@ namespace MediaBrowser.Server.Implementations.Connect _httpClient = httpClient; _appHost = appHost; _config = config; + _userManager = userManager; LoadCachedData(); } @@ -156,8 +168,8 @@ namespace MediaBrowser.Server.Implementations.Connect { var data = _json.DeserializeFromStream(stream); - ConnectServerId = data.Id; - ConnectAccessKey = data.AccessKey; + _data.ServerId = data.Id; + _data.AccessKey = data.AccessKey; CacheData(); } @@ -182,7 +194,7 @@ namespace MediaBrowser.Server.Implementations.Connect {"systemid", _appHost.SystemId} }); - options.RequestHeaders.Add("X-Connect-Token", ConnectAccessKey); + SetServerAccessToken(options); // No need to examine the response using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) @@ -203,11 +215,7 @@ namespace MediaBrowser.Server.Implementations.Connect { Directory.CreateDirectory(Path.GetDirectoryName(path)); - var json = _json.SerializeToString(new ConnectData - { - AccessKey = ConnectAccessKey, - ServerId = ConnectServerId - }); + var json = _json.SerializeToString(_data); var encrypted = _encryption.EncryptString(json); @@ -229,10 +237,7 @@ namespace MediaBrowser.Server.Implementations.Connect var json = _encryption.DecryptString(encrypted); - var data = _json.DeserializeFromString(json); - - ConnectAccessKey = data.AccessKey; - ConnectServerId = data.ServerId; + _data = _json.DeserializeFromString(json); } catch (IOException) { @@ -244,9 +249,181 @@ namespace MediaBrowser.Server.Implementations.Connect } } + private User GetUser(string id) + { + var user = _userManager.GetUserById(id); + + if (user == null) + { + throw new ArgumentException("User not found."); + } + + return user; + } + + public ConnectUserLink GetUserInfo(string userId) + { + var user = GetUser(userId); + + return new ConnectUserLink + { + LocalUserId = user.Id.ToString("N"), + Username = user.ConnectUserName, + UserId = user.ConnectUserId + }; + } + private string GetConnectUrl(string handler) { return "http://mb3admin.com/test/connect/" + handler; } + + public async Task LinkUser(string userId, string connectUsername) + { + if (string.IsNullOrWhiteSpace(connectUsername)) + { + throw new ArgumentNullException("connectUsername"); + } + + var connectUser = await GetConnectUser(new ConnectUserQuery + { + Name = connectUsername + + }, CancellationToken.None).ConfigureAwait(false); + + var user = GetUser(userId); + + // See if it's already been set. + if (string.Equals(connectUser.Id, user.ConnectUserId, StringComparison.OrdinalIgnoreCase)) + { + return; + } + + if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) + { + await RemoveLink(user, connectUser).ConfigureAwait(false); + } + + var url = GetConnectUrl("ServerAuthorizations"); + + var options = new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None + }; + + var accessToken = Guid.NewGuid().ToString("N"); + + var postData = new Dictionary + { + {"serverId", ConnectServerId}, + {"userId", connectUser.Id}, + {"userType", "Linked"}, + {"accessToken", accessToken} + }; + + options.SetPostData(postData); + + SetServerAccessToken(options); + + // No need to examine the response + using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) + { + } + + user.ConnectAccessKey = accessToken; + user.ConnectUserName = connectUser.Name; + user.ConnectUserId = connectUser.Id; + + await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + } + + public async Task RemoveLink(string userId) + { + var user = GetUser(userId); + + var connectUser = await GetConnectUser(new ConnectUserQuery + { + Name = user.ConnectUserId + + }, CancellationToken.None).ConfigureAwait(false); + + await RemoveLink(user, connectUser).ConfigureAwait(false); + } + + public async Task RemoveLink(User user, ConnectUser connectUser) + { + var url = GetConnectUrl("ServerAuthorizations"); + + var options = new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None + }; + + var postData = new Dictionary + { + {"serverId", ConnectServerId}, + {"userId", connectUser.Id} + }; + + options.SetPostData(postData); + + SetServerAccessToken(options); + + // No need to examine the response + using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) + { + } + + user.ConnectAccessKey = null; + user.ConnectUserName = null; + user.ConnectUserId = null; + + await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + } + + private async Task GetConnectUser(ConnectUserQuery query, CancellationToken cancellationToken) + { + var url = GetConnectUrl("user"); + + if (!string.IsNullOrWhiteSpace(query.Id)) + { + url = url + "?id=" + WebUtility.UrlEncode(query.Id); + } + else if (!string.IsNullOrWhiteSpace(query.Name)) + { + url = url + "?name=" + WebUtility.UrlEncode(query.Name); + } + else if (!string.IsNullOrWhiteSpace(query.Email)) + { + url = url + "?email=" + WebUtility.UrlEncode(query.Email); + } + + var options = new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url + }; + + SetServerAccessToken(options); + + using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) + { + var response = _json.DeserializeFromStream(stream); + + return new ConnectUser + { + Email = response.Email, + Id = response.Id, + Name = response.Name + }; + } + } + + private void SetServerAccessToken(HttpRequestOptions options) + { + options.RequestHeaders.Add("X-Connect-Token", ConnectAccessKey); + } } } diff --git a/MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs similarity index 59% rename from MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs rename to MediaBrowser.Server.Implementations/Connect/Responses.cs index 75c55e26ec..5d71c0f9b7 100644 --- a/MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs +++ b/MediaBrowser.Server.Implementations/Connect/Responses.cs @@ -15,4 +15,14 @@ namespace MediaBrowser.Server.Implementations.Connect public string Url { get; set; } public string Name { get; set; } } + + public class GetConnectUserResponse + { + public string Id { get; set; } + public string Name { get; set; } + public string DisplayName { get; set; } + public string Email { get; set; } + public string IsActive { get; set; } + public string ImageUrl { get; set; } + } } diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index 1294368f1b..ea09824911 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security var user = string.IsNullOrWhiteSpace(auth.UserId) ? null - : UserManager.GetUserById(new Guid(auth.UserId)); + : UserManager.GetUserById(auth.UserId); if (user == null & !string.IsNullOrWhiteSpace(auth.UserId)) { diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 6faa72b818..738222540c 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Library } else { - var user = _userManager.GetUserById(new Guid(query.UserId)); + var user = _userManager.GetUserById(query.UserId); inputItems = user.RootFolder.GetRecursiveChildren(user, true); } diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 94cc612408..47d6b17f0c 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -128,6 +128,16 @@ namespace MediaBrowser.Server.Implementations.Library return Users.FirstOrDefault(u => u.Id == id); } + /// + /// Gets the user by identifier. + /// + /// The identifier. + /// User. + public User GetUserById(string id) + { + return GetUserById(new Guid(id)); + } + public async Task Initialize() { Users = await LoadUsers().ConfigureAwait(false); @@ -219,6 +229,9 @@ namespace MediaBrowser.Server.Implementations.Library await UserRepository.SaveUser(user, CancellationToken.None).ConfigureAwait(false); users.Add(user); + + user.Configuration.IsAdministrator = true; + UpdateConfiguration(user, user.Configuration); } return users; @@ -503,7 +516,8 @@ namespace MediaBrowser.Server.Implementations.Library Name = name, Id = ("MBUser" + name).GetMD5(), DateCreated = DateTime.UtcNow, - DateModified = DateTime.UtcNow + DateModified = DateTime.UtcNow, + UsesIdForConfigurationPath = true }; } diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 61283505ba..4beb34e4f9 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Library public async Task> GetUserViews(UserViewQuery query, CancellationToken cancellationToken) { - var user = _userManager.GetUserById(new Guid(query.UserId)); + var user = _userManager.GetUserById(query.UserId); var folders = user.RootFolder .GetChildren(user, true) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index d2a89e947c..562b97a481 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task> GetInternalChannels(LiveTvChannelQuery query, CancellationToken cancellationToken) { - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); var channels = _channelIdList.Select(_libraryManager.GetItemById) .Where(i => i != null) @@ -231,7 +231,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task> GetChannels(LiveTvChannelQuery query, CancellationToken cancellationToken) { - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); var internalResult = await GetInternalChannels(query, cancellationToken).ConfigureAwait(false); @@ -693,7 +693,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv }); } - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); if (user != null) { @@ -730,7 +730,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { IEnumerable programs = _programs.Values; - var user = _userManager.GetUserById(new Guid(query.UserId)); + var user = _userManager.GetUserById(query.UserId); // Avoid implicitly captured closure var currentUser = user; @@ -786,7 +786,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { var internalResult = await GetRecommendedProgramsInternal(query, cancellationToken).ConfigureAwait(false); - var user = _userManager.GetUserById(new Guid(query.UserId)); + var user = _userManager.GetUserById(query.UserId); var returnArray = internalResult.Items .Select(i => @@ -1099,7 +1099,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv }; } - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false); @@ -1199,7 +1199,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv }; } - var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId)); + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); var internalResult = await GetInternalRecordings(query, cancellationToken).ConfigureAwait(false); @@ -1869,7 +1869,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task GetLiveTvFolder(string userId, CancellationToken cancellationToken) { - var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(new Guid(userId)); + var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId); // Get everything var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList(); diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index c1d4a42c92..f95fd85b73 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -11,7 +11,7 @@ "FileNotFound": "File not found.", "FileReadError": "An error occurred while reading the file.", "DeleteUser": "Delete User", - "DeleteUserConfirmation": "Are you sure you wish to delete {0}?", + "DeleteUserConfirmation": "Are you sure you wish to delete this user?", "PasswordResetHeader": "Password Reset", "PasswordResetComplete": "The password has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", @@ -450,5 +450,8 @@ "MessageChangeRecurringPlanConfirm": "After completing this transaction you will need to cancel your previous recurring donation from within your PayPal account. Thank you for supporting Media Browser.", "MessageSupporterMembershipExpiredOn": "Your supporter membership expired on {0}.", "MessageYouHaveALifetimeMembership": "You have a lifetime supporter membership. You can provide additional donations on a one-time or recurring basis using the options below. Thank you for supporting Media Browser.", - "MessageYouHaveAnActiveRecurringMembership": "You have an active {0} membership. You can upgrade your plan using the options below." + "MessageYouHaveAnActiveRecurringMembership": "You have an active {0} membership. You can upgrade your plan using the options below.", + "ButtonDelete": "Delete", + "HeaderMediaBrowserAccountAdded": "Media Browser Account Added", + "MessageMediaBrowserAccontAdded": "A Media Browser account has been added to this user. An email has been sent to the owner of the account. They will need to confirm the invitation by clicking a link within the email." } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index f5e54e3f99..7a3b08defb 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -74,6 +74,8 @@ "TabProfiles": "Profiles", "TabSecurity": "Security", "ButtonAddUser": "Add User", + "ButtonAddLocalUser": "Add Local User", + "ButtonInviteMediaBrowserUser": "Invite Media Browser User", "ButtonSave": "Save", "ButtonResetPassword": "Reset Password", "LabelNewPassword": "New password:", @@ -1156,5 +1158,7 @@ "XmlDocumentAttributeListHelp": "These attributes are applied to the root element of every xml response.", "OptionSaveMetadataAsHidden": "Save metadata and images as hidden files", "LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan", - "LabelExtractChaptersDuringLibraryScanHelp": "If enabled, chapter images will be extracted when videos are imported during the library scan. If disabled they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster." + "LabelExtractChaptersDuringLibraryScanHelp": "If enabled, chapter images will be extracted when videos are imported during the library scan. If disabled they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.", + "LabelConnectUserName": "Media Browser username/email:", + "LabelConnectUserNameHelp": "Connect this user to a Media Browser account to enable easy sign-in access from any app without having to know the server ip address." } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index b44adc4d86..d7c06e2f4e 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -118,7 +118,7 @@ - + diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs index 3558922d8b..3f8b61a458 100644 --- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs +++ b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.Notifications GetConfiguration().GetOptions(notificationType); var users = GetUserIds(request, options) - .Select(i => _userManager.GetUserById(new Guid(i))); + .Select(i => _userManager.GetUserById(i)); var title = GetTitle(request, options); var description = GetDescription(request, options); diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs index ee2114aa4d..852959312a 100644 --- a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs +++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Playlists public IEnumerable GetPlaylists(string userId) { - var user = _userManager.GetUserById(new Guid(userId)); + var user = _userManager.GetUserById(userId); return GetPlaylistsFolder(userId).GetChildren(user, true).OfType(); } @@ -100,7 +100,7 @@ namespace MediaBrowser.Server.Implementations.Playlists throw new ArgumentException("A playlist media type is required."); } - var user = _userManager.GetUserById(new Guid(options.UserId)); + var user = _userManager.GetUserById(options.UserId); var path = Path.Combine(parentFolder.Path, folderName); path = GetTargetPath(path); @@ -162,7 +162,7 @@ namespace MediaBrowser.Server.Implementations.Playlists public Task AddToPlaylist(string playlistId, IEnumerable itemIds, string userId) { - var user = string.IsNullOrWhiteSpace(userId) ? null : _userManager.GetUserById(new Guid(userId)); + var user = string.IsNullOrWhiteSpace(userId) ? null : _userManager.GetUserById(userId); return AddToPlaylistInternal(playlistId, itemIds, user); } diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 912174c1e3..ceda8f47d9 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -455,7 +455,7 @@ namespace MediaBrowser.Server.Implementations.Session users.Add(user); var additionalUsers = session.AdditionalUsers - .Select(i => _userManager.GetUserById(new Guid(i.UserId))) + .Select(i => _userManager.GetUserById(i.UserId)) .Where(i => i != null); users.AddRange(additionalUsers); @@ -1189,7 +1189,7 @@ namespace MediaBrowser.Server.Implementations.Session if (!string.IsNullOrWhiteSpace(info.UserId)) { - var user = _userManager.GetUserById(new Guid(info.UserId)); + var user = _userManager.GetUserById(info.UserId); if (user == null || user.Configuration.IsDisabled) { diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index e71a5d5142..66e771aa37 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Server.Implementations.TV public QueryResult GetNextUp(NextUpQuery request) { - var user = _userManager.GetUserById(new Guid(request.UserId)); + var user = _userManager.GetUserById(request.UserId); if (user == null) { @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.TV public QueryResult GetNextUp(NextUpQuery request, IEnumerable parentsFolders) { - var user = _userManager.GetUserById(new Guid(request.UserId)); + var user = _userManager.GetUserById(request.UserId); if (user == null) { diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index b5db94776a..0d76e95b9b 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -447,7 +447,7 @@ namespace MediaBrowser.ServerApplication var encryptionManager = new EncryptionManager(); RegisterSingleInstance(encryptionManager); - ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager); + ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager, UserManager); RegisterSingleInstance(ConnectManager); SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository); diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs index 4f94ebd67c..ae11712a5d 100644 --- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Configuration; +using System.Collections.Generic; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Model.IO; @@ -52,6 +53,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg Directory.CreateDirectory(versionedDirectoryPath); + var excludeFromDeletions = new List { versionedDirectoryPath }; + if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath)) { // ffmpeg not present. See if there's an older version we can start with @@ -71,14 +74,42 @@ namespace MediaBrowser.ServerApplication.FFMpeg info = existingVersion; versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath); + + excludeFromDeletions.Add(versionedDirectoryPath); } } await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + DeleteOlderFolders(Path.GetDirectoryName(versionedDirectoryPath), excludeFromDeletions); + return info; } + private void DeleteOlderFolders(string path, IEnumerable excludeFolders ) + { + var folders = Directory.GetDirectories(path) + .Where(i => !excludeFolders.Contains(i, StringComparer.OrdinalIgnoreCase)) + .ToList(); + + foreach (var folder in folders) + { + DeleteFolder(folder); + } + } + + private void DeleteFolder(string path) + { + try + { + Directory.Delete(path, true); + } + catch (Exception ex) + { + _logger.ErrorException("Error deleting {0}", ex, path); + } + } + private FFMpegInfo GetExistingVersion(FFMpegInfo info, string rootEncoderPath) { var encoderFilename = Path.GetFileName(info.EncoderPath); diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 0fa99d3492..4fb5cea568 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -2101,6 +2101,9 @@ + + PreserveNewest + PreserveNewest diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index d67404794c..a0562c8357 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -858,7 +858,7 @@ namespace MediaBrowser.XbmcMetadata.Savers return; } - var user = userManager.GetUserById(new Guid(userId)); + var user = userManager.GetUserById(userId); if (user == null) {