From 5c615fa02448813499ed87f2a1c2b937c7a7dcd5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 11:10:51 -0400 Subject: add connect linking --- .../Connect/ConnectData.cs | 26 ++- .../Connect/ConnectManager.cs | 209 +++++++++++++++++++-- .../Connect/Responses.cs | 28 +++ .../Connect/ServerRegistrationResponse.cs | 18 -- 4 files changed, 246 insertions(+), 35 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/Connect/Responses.cs delete mode 100644 MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs (limited to 'MediaBrowser.Server.Implementations/Connect') diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs index 1816b103e..dfbeccd4d 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 3ea54835d..e3e1b39cc 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/Responses.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs new file mode 100644 index 000000000..5d71c0f9b --- /dev/null +++ b/MediaBrowser.Server.Implementations/Connect/Responses.cs @@ -0,0 +1,28 @@ + +namespace MediaBrowser.Server.Implementations.Connect +{ + public class ServerRegistrationResponse + { + public string Id { get; set; } + public string Url { get; set; } + public string Name { get; set; } + public string AccessKey { get; set; } + } + + public class UpdateServerRegistrationResponse + { + public string Id { get; set; } + 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/Connect/ServerRegistrationResponse.cs b/MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs deleted file mode 100644 index 75c55e26e..000000000 --- a/MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs +++ /dev/null @@ -1,18 +0,0 @@ - -namespace MediaBrowser.Server.Implementations.Connect -{ - public class ServerRegistrationResponse - { - public string Id { get; set; } - public string Url { get; set; } - public string Name { get; set; } - public string AccessKey { get; set; } - } - - public class UpdateServerRegistrationResponse - { - public string Id { get; set; } - public string Url { get; set; } - public string Name { get; set; } - } -} -- cgit v1.2.3