From b12215b3f94dd7f7d5cff6a703b037e215090a98 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 13:12:47 -0400 Subject: [PATCH 1/7] add connect error handling --- MediaBrowser.Api/ConnectService.cs | 2 +- .../Connect/ConnectManager.cs | 66 +++++++++++-------- .../Connect/Responses.cs | 5 ++ .../Localization/JavaScript/javascript.json | 4 +- .../Localization/Server/server.json | 3 +- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/MediaBrowser.Api/ConnectService.cs b/MediaBrowser.Api/ConnectService.cs index 80f6d4810e..4d3cad49d7 100644 --- a/MediaBrowser.Api/ConnectService.cs +++ b/MediaBrowser.Api/ConnectService.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Api } [Route("/Users/{Id}/Connect/Link", "DELETE", Summary = "Removes a Connect link for a user")] - public class DeleteConnectLink : IReturn + public class DeleteConnectLink : IReturnVoid { [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] public string Id { get; set; } diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 972f3adb6d..d0de64a6fd 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -295,7 +295,7 @@ namespace MediaBrowser.Server.Implementations.Connect if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) { - await RemoveLink(user, connectUser).ConfigureAwait(false); + await RemoveLink(user, connectUser.Id).ConfigureAwait(false); } var url = GetConnectUrl("ServerAuthorizations"); @@ -323,6 +323,7 @@ namespace MediaBrowser.Server.Implementations.Connect // No need to examine the response using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { + var response = _json.DeserializeFromStream(stream); } user.ConnectAccessKey = accessToken; @@ -332,44 +333,55 @@ namespace MediaBrowser.Server.Implementations.Connect await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } - public async Task RemoveLink(string userId) + public 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); + return RemoveLink(user, user.ConnectUserId); } - public async Task RemoveLink(User user, ConnectUser connectUser) + private async Task RemoveLink(User user, string connectUserId) { - var url = GetConnectUrl("ServerAuthorizations"); - - var options = new HttpRequestOptions + if (!string.IsNullOrWhiteSpace(connectUserId)) { - Url = url, - CancellationToken = CancellationToken.None - }; + var url = GetConnectUrl("ServerAuthorizations"); - var postData = new Dictionary - { - {"serverId", ConnectServerId}, - {"userId", connectUser.Id} - }; + var options = new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None + }; - options.SetPostData(postData); + var postData = new Dictionary + { + {"serverId", ConnectServerId}, + {"userId", connectUserId} + }; - SetServerAccessToken(options); + options.SetPostData(postData); - // No need to examine the response - using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) - { + 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."); + } } - + user.ConnectAccessKey = null; user.ConnectUserName = null; user.ConnectUserId = null; diff --git a/MediaBrowser.Server.Implementations/Connect/Responses.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs index 5d71c0f9b7..7a80015d50 100644 --- a/MediaBrowser.Server.Implementations/Connect/Responses.cs +++ b/MediaBrowser.Server.Implementations/Connect/Responses.cs @@ -25,4 +25,9 @@ namespace MediaBrowser.Server.Implementations.Connect public string IsActive { get; set; } public string ImageUrl { get; set; } } + + public class ServerUserAuthorizationResponse + { + + } } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 07ce3e4f00..6442c31780 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -453,5 +453,7 @@ "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 will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email." + "MessageMediaBrowserAccontAdded": "A Media Browser account has been added to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", + "HeaderMediaBrowserAccountRemoved": "Media Browser Account Removed", + "MessageMediaBrowserAccontRemoved": "The Media Browser account has been removed from this user." } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 7a3b08defb..86dc60c2ee 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1160,5 +1160,6 @@ "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.", "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." + "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.", + "ButtonLearnMoreAboutMediaBrowserConnect": "Learn more about Media Browser Connect" } From 14bb0aa30c4f13e4093b5a80fcb964c0402feda0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 13:25:46 -0400 Subject: [PATCH 2/7] check if connect user is active --- MediaBrowser.Controller/Connect/ConnectUser.cs | 1 + .../Connect/ConnectManager.cs | 8 +++++++- MediaBrowser.Server.Implementations/Connect/Responses.cs | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/Connect/ConnectUser.cs b/MediaBrowser.Controller/Connect/ConnectUser.cs index c640f90952..2cd14ec7cc 100644 --- a/MediaBrowser.Controller/Connect/ConnectUser.cs +++ b/MediaBrowser.Controller/Connect/ConnectUser.cs @@ -11,6 +11,7 @@ namespace MediaBrowser.Controller.Connect public string Id { get; set; } public string Name { get; set; } public string Email { get; set; } + public bool IsActive { get; set; } } public class ConnectUserQuery diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index d0de64a6fd..6a1c3f0746 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -291,6 +291,11 @@ namespace MediaBrowser.Server.Implementations.Connect }, CancellationToken.None).ConfigureAwait(false); + if (!connectUser.IsActive) + { + throw new ArgumentException("The Media Browser account has been disabled."); + } + var user = GetUser(userId); if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) @@ -422,7 +427,8 @@ namespace MediaBrowser.Server.Implementations.Connect { Email = response.Email, Id = response.Id, - Name = response.Name + Name = response.Name, + IsActive = response.IsActive }; } } diff --git a/MediaBrowser.Server.Implementations/Connect/Responses.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs index 7a80015d50..a3b0369ba1 100644 --- a/MediaBrowser.Server.Implementations/Connect/Responses.cs +++ b/MediaBrowser.Server.Implementations/Connect/Responses.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Server.Implementations.Connect public string Name { get; set; } public string DisplayName { get; set; } public string Email { get; set; } - public string IsActive { get; set; } + public bool IsActive { get; set; } public string ImageUrl { get; set; } } From 9991360d8a4cb3a692b3995dafdc43e7cde866de Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 13:42:23 -0400 Subject: [PATCH 3/7] set roles on connect endpoints --- MediaBrowser.Api/ConnectService.cs | 8 ++--- .../Net/AuthenticatedAttribute.cs | 9 +++++- MediaBrowser.Controller/Net/IAuthService.cs | 7 ++++- .../Configuration/ServerConfiguration.cs | 6 ++-- .../HttpServer/Security/AuthService.cs | 29 +++++++++++++------ 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/MediaBrowser.Api/ConnectService.cs b/MediaBrowser.Api/ConnectService.cs index 4d3cad49d7..e2a1b98e92 100644 --- a/MediaBrowser.Api/ConnectService.cs +++ b/MediaBrowser.Api/ConnectService.cs @@ -1,7 +1,7 @@ -using System.Threading.Tasks; -using MediaBrowser.Controller.Connect; +using MediaBrowser.Controller.Connect; using MediaBrowser.Controller.Net; using ServiceStack; +using System.Threading.Tasks; namespace MediaBrowser.Api { @@ -28,8 +28,8 @@ namespace MediaBrowser.Api [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] public string Id { get; set; } } - - [Authenticated] + + [Authenticated(Roles = "Admin")] public class ConnectService : BaseApiService { private readonly IConnectManager _connectManager; diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index 329dbaa463..31bb7c66be 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -1,5 +1,6 @@ using ServiceStack.Web; using System; +using System.Linq; namespace MediaBrowser.Controller.Net { @@ -13,6 +14,8 @@ namespace MediaBrowser.Controller.Net /// true if [allow local]; otherwise, false. public bool AllowLocal { get; set; } + public string Roles { get; set; } + /// /// The request filter is executed before the service. /// @@ -21,7 +24,11 @@ namespace MediaBrowser.Controller.Net /// The request DTO public void RequestFilter(IRequest request, IResponse response, object requestDto) { - AuthService.Authenticate(request, response, requestDto, AllowLocal); + var roles = (Roles ?? string.Empty).Split(',') + .Where(i => !string.IsNullOrWhiteSpace(i)) + .ToArray(); + + AuthService.Authenticate(request, response, requestDto, AllowLocal, roles); } /// diff --git a/MediaBrowser.Controller/Net/IAuthService.cs b/MediaBrowser.Controller/Net/IAuthService.cs index dca70f58fe..69014d0ff1 100644 --- a/MediaBrowser.Controller/Net/IAuthService.cs +++ b/MediaBrowser.Controller/Net/IAuthService.cs @@ -1,9 +1,14 @@ using ServiceStack.Web; +using System.Collections.Generic; namespace MediaBrowser.Controller.Net { public interface IAuthService { - void Authenticate(IRequest request, IResponse response, object requestDto, bool allowLocal); + void Authenticate(IRequest request, + IResponse response, + object requestDto, + bool allowLocal, + string[] roles); } } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 0fdb8f7cc3..4786194e27 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -175,7 +175,7 @@ namespace MediaBrowser.Model.Configuration public PeopleMetadataOptions PeopleMetadataOptions { get; set; } - public string[] SecureApps1 { get; set; } + public string[] SecureApps2 { get; set; } public bool SaveMetadataHidden { get; set; } @@ -223,7 +223,7 @@ namespace MediaBrowser.Model.Configuration PeopleMetadataOptions = new PeopleMetadataOptions(); - SecureApps1 = new[] + SecureApps2 = new[] { "Dashboard", "MBKinect", @@ -231,7 +231,7 @@ namespace MediaBrowser.Model.Configuration "Media Browser Theater", //"Chrome Companion", - //"MB-Classic" + "MB-Classic" }; MetadataOptions = new[] diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index ea09824911..4b699c0184 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; @@ -42,24 +41,29 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security /// public string HtmlRedirect { get; set; } - public void Authenticate(IRequest req, IResponse res, object requestDto, bool allowLocal) + public void Authenticate(IRequest request, + IResponse response, + object requestDto, + bool allowLocal, + string[] roles) { - if (HostContext.HasValidAuthSecret(req)) + if (HostContext.HasValidAuthSecret(request)) return; //ExecuteBasic(req, res, requestDto); //first check if session is authenticated //if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed) - ValidateUser(req, allowLocal); + ValidateUser(request, allowLocal, roles); } - private void ValidateUser(IRequest req, bool allowLocal) + private void ValidateUser(IRequest req, bool allowLocal, + string[] roles) { //This code is executed before the service var auth = AuthorizationContext.GetAuthorizationInfo(req); if (!string.IsNullOrWhiteSpace(auth.Token) - || _config.Configuration.SecureApps1.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + || _config.Configuration.SecureApps2.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { if (!allowLocal || !req.IsLocal) { @@ -73,8 +77,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security if (user == null & !string.IsNullOrWhiteSpace(auth.UserId)) { - // TODO: Re-enable - //throw new ArgumentException("User with Id " + auth.UserId + " not found"); + throw new ArgumentException("User with Id " + auth.UserId + " not found"); } if (user != null && user.Configuration.IsDisabled) @@ -82,6 +85,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security throw new AuthenticationException("User account has been disabled."); } + if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase)) + { + if (user == null || !user.Configuration.IsAdministrator) + { + throw new ArgumentException("Administrative access is required for this request."); + } + } + if (!string.IsNullOrWhiteSpace(auth.DeviceId) && !string.IsNullOrWhiteSpace(auth.Client) && !string.IsNullOrWhiteSpace(auth.Device)) From 9ad7d5d1a94239395b1a0717a8f5b220111ec886 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 14:47:48 -0400 Subject: [PATCH 4/7] consolidate connect calls --- MediaBrowser.Api/ConnectService.cs | 16 +--------------- .../Connect/ConnectUserLink.cs | 10 ---------- .../Connect/IConnectManager.cs | 7 ------- MediaBrowser.Controller/Entities/User.cs | 2 ++ .../MediaBrowser.Controller.csproj | 1 - .../MediaBrowser.Model.Portable.csproj | 3 +++ .../MediaBrowser.Model.net35.csproj | 3 +++ MediaBrowser.Model/Connect/UserLinkType.cs | 15 +++++++++++++++ MediaBrowser.Model/Dto/UserDto.cs | 19 ++++++++++++++++++- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + .../Connect/ConnectManager.cs | 12 ------------ .../Library/UserManager.cs | 9 ++++++--- 12 files changed, 49 insertions(+), 49 deletions(-) delete mode 100644 MediaBrowser.Controller/Connect/ConnectUserLink.cs create mode 100644 MediaBrowser.Model/Connect/UserLinkType.cs diff --git a/MediaBrowser.Api/ConnectService.cs b/MediaBrowser.Api/ConnectService.cs index e2a1b98e92..14b04a0bb8 100644 --- a/MediaBrowser.Api/ConnectService.cs +++ b/MediaBrowser.Api/ConnectService.cs @@ -5,15 +5,8 @@ using System.Threading.Tasks; 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 + public class CreateConnectLink : IReturnVoid { [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] public string Id { get; set; } @@ -39,13 +32,6 @@ namespace MediaBrowser.Api _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); diff --git a/MediaBrowser.Controller/Connect/ConnectUserLink.cs b/MediaBrowser.Controller/Connect/ConnectUserLink.cs deleted file mode 100644 index 93de6d8b4e..0000000000 --- a/MediaBrowser.Controller/Connect/ConnectUserLink.cs +++ /dev/null @@ -1,10 +0,0 @@ - -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 6c2128cd3f..8bdb76ea41 100644 --- a/MediaBrowser.Controller/Connect/IConnectManager.cs +++ b/MediaBrowser.Controller/Connect/IConnectManager.cs @@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.Connect /// The wan API address. string WanApiAddress { get; } - /// - /// Gets the user information. - /// - /// The user identifier. - /// ConnectUserInfo. - ConnectUserLink GetUserInfo(string userId); - /// /// Links the user. /// diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index c0c7a6c531..e0682c9ee9 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Connect; using MediaBrowser.Model.Serialization; using System; using System.IO; @@ -34,6 +35,7 @@ namespace MediaBrowser.Controller.Entities public string ConnectUserName { get; set; } public string ConnectUserId { get; set; } + public UserLinkType ConnectLinkType { get; set; } public string ConnectAccessKey { get; set; } /// diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 1d23a82a9e..fa10642324 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -101,7 +101,6 @@ - diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index c6e8adb166..32054beb37 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -188,6 +188,9 @@ Configuration\XbmcMetadataOptions.cs + + Connect\UserLinkType.cs + Dlna\AudioOptions.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 715331436c..e9153117be 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -151,6 +151,9 @@ Configuration\XbmcMetadataOptions.cs + + Connect\UserLinkType.cs + Dlna\AudioOptions.cs diff --git a/MediaBrowser.Model/Connect/UserLinkType.cs b/MediaBrowser.Model/Connect/UserLinkType.cs new file mode 100644 index 0000000000..e8ea15a4e7 --- /dev/null +++ b/MediaBrowser.Model/Connect/UserLinkType.cs @@ -0,0 +1,15 @@ + +namespace MediaBrowser.Model.Connect +{ + public enum UserLinkType + { + /// + /// The linked user + /// + LinkedUser = 1, + /// + /// The guest + /// + Guest = 2 + } +} diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs index 787f55ec09..b88e9d411a 100644 --- a/MediaBrowser.Model/Dto/UserDto.cs +++ b/MediaBrowser.Model/Dto/UserDto.cs @@ -1,9 +1,10 @@ using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Connect; +using MediaBrowser.Model.Extensions; using System; using System.ComponentModel; using System.Diagnostics; using System.Runtime.Serialization; -using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Dto { @@ -19,6 +20,22 @@ namespace MediaBrowser.Model.Dto /// The name. public string Name { get; set; } + /// + /// Gets or sets the name of the connect user. + /// + /// The name of the connect user. + public string ConnectUserName { get; set; } + /// + /// Gets or sets the connect user identifier. + /// + /// The connect user identifier. + public string ConnectUserId { get; set; } + /// + /// Gets or sets the type of the connect link. + /// + /// The type of the connect link. + public UserLinkType ConnectLinkType { get; set; } + /// /// Gets or sets the id. /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 9223db80a2..c4da280e23 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -81,6 +81,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 6a1c3f0746..3933b180e2 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -261,18 +261,6 @@ namespace MediaBrowser.Server.Implementations.Connect 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 "https://connect.mediabrowser.tv/service/" + handler; diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 47d6b17f0c..16a1dc516b 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -86,7 +86,7 @@ namespace MediaBrowser.Server.Implementations.Library /// public event EventHandler> UserUpdated; public event EventHandler> UserConfigurationUpdated; - + /// /// Called when [user updated]. /// @@ -137,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Library { return GetUserById(new Guid(id)); } - + public async Task Initialize() { Users = await LoadUsers().ConfigureAwait(false); @@ -260,7 +260,10 @@ namespace MediaBrowser.Server.Implementations.Library HasConfiguredPassword = hasConfiguredDefaultPassword, LastActivityDate = user.LastActivityDate, LastLoginDate = user.LastLoginDate, - Configuration = user.Configuration + Configuration = user.Configuration, + ConnectLinkType = user.ConnectLinkType, + ConnectUserId = user.ConnectUserId, + ConnectUserName = user.ConnectUserName }; var image = user.GetImageInfo(ImageType.Primary, 0); From 52aad5466a4700a8759d1f4c6e4f2673c12a8f9e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 15:27:29 -0400 Subject: [PATCH 5/7] add connect icon --- .../Localization/JavaScript/javascript.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 6442c31780..f8bb0f1d50 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -455,5 +455,6 @@ "HeaderMediaBrowserAccountAdded": "Media Browser Account Added", "MessageMediaBrowserAccontAdded": "A Media Browser account has been added to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", "HeaderMediaBrowserAccountRemoved": "Media Browser Account Removed", - "MessageMediaBrowserAccontRemoved": "The Media Browser account has been removed from this user." + "MessageMediaBrowserAccontRemoved": "The Media Browser account has been removed from this user.", + "TooltipLinkedToMediaBrowserConnect": "Linked to Media Browser Connect" } From 6dc9b169666bcfeb2edf3620c0646efa0c29606f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 19:39:06 -0400 Subject: [PATCH 6/7] update connect link text --- MediaBrowser.Api/ConnectService.cs | 8 +++----- .../Connect/ConnectInvitationRequest.cs | 20 ------------------- .../Connect/ConnectUser.cs | 7 +------ .../Connect/IConnectManager.cs | 2 +- .../Connect/UserLinkResult.cs | 8 ++++++++ .../MediaBrowser.Controller.csproj | 2 +- .../Connect/ConnectManager.cs | 11 +++++++++- .../Connect/Responses.cs | 9 ++++++++- .../Localization/JavaScript/javascript.json | 3 ++- .../Localization/Server/server.json | 1 + 10 files changed, 35 insertions(+), 36 deletions(-) delete mode 100644 MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs create mode 100644 MediaBrowser.Controller/Connect/UserLinkResult.cs diff --git a/MediaBrowser.Api/ConnectService.cs b/MediaBrowser.Api/ConnectService.cs index 14b04a0bb8..9ea75d4ace 100644 --- a/MediaBrowser.Api/ConnectService.cs +++ b/MediaBrowser.Api/ConnectService.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Api { [Route("/Users/{Id}/Connect/Link", "POST", Summary = "Creates a Connect link for a user")] - public class CreateConnectLink : IReturnVoid + public class CreateConnectLink : IReturn { [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] public string Id { get; set; } @@ -32,11 +32,9 @@ namespace MediaBrowser.Api _connectManager = connectManager; } - public void Post(CreateConnectLink request) + public object Post(CreateConnectLink request) { - var task = _connectManager.LinkUser(request.Id, request.ConnectUsername); - - Task.WaitAll(task); + return _connectManager.LinkUser(request.Id, request.ConnectUsername); } public void Delete(DeleteConnectLink request) diff --git a/MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs b/MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs deleted file mode 100644 index 91516723bf..0000000000 --- a/MediaBrowser.Controller/Connect/ConnectInvitationRequest.cs +++ /dev/null @@ -1,20 +0,0 @@ - -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 index 2cd14ec7cc..389330cecb 100644 --- a/MediaBrowser.Controller/Connect/ConnectUser.cs +++ b/MediaBrowser.Controller/Connect/ConnectUser.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - + namespace MediaBrowser.Controller.Connect { public class ConnectUser diff --git a/MediaBrowser.Controller/Connect/IConnectManager.cs b/MediaBrowser.Controller/Connect/IConnectManager.cs index 8bdb76ea41..7c1e14c302 100644 --- a/MediaBrowser.Controller/Connect/IConnectManager.cs +++ b/MediaBrowser.Controller/Connect/IConnectManager.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Connect /// The user identifier. /// The connect username. /// Task. - Task LinkUser(string userId, string connectUsername); + Task LinkUser(string userId, string connectUsername); /// /// Removes the link. diff --git a/MediaBrowser.Controller/Connect/UserLinkResult.cs b/MediaBrowser.Controller/Connect/UserLinkResult.cs new file mode 100644 index 0000000000..4ed57cfc2d --- /dev/null +++ b/MediaBrowser.Controller/Connect/UserLinkResult.cs @@ -0,0 +1,8 @@ + +namespace MediaBrowser.Controller.Connect +{ + public class UserLinkResult + { + public bool IsPending { get; set; } + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index fa10642324..6d881da4f8 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -99,9 +99,9 @@ - + diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 3933b180e2..d92ca8323f 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Connect; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Security; +using MediaBrowser.Model.Connect; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; @@ -266,7 +267,7 @@ namespace MediaBrowser.Server.Implementations.Connect return "https://connect.mediabrowser.tv/service/" + handler; } - public async Task LinkUser(string userId, string connectUsername) + public async Task LinkUser(string userId, string connectUsername) { if (string.IsNullOrWhiteSpace(connectUsername)) { @@ -313,17 +314,24 @@ namespace MediaBrowser.Server.Implementations.Connect 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(stream); + + result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); } user.ConnectAccessKey = accessToken; user.ConnectUserName = connectUser.Name; user.ConnectUserId = connectUser.Id; + user.ConnectLinkType = UserLinkType.LinkedUser; await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); + + return result; } public Task RemoveLink(string userId) @@ -378,6 +386,7 @@ namespace MediaBrowser.Server.Implementations.Connect user.ConnectAccessKey = null; user.ConnectUserName = null; user.ConnectUserId = null; + user.ConnectLinkType = UserLinkType.LinkedUser; await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); } diff --git a/MediaBrowser.Server.Implementations/Connect/Responses.cs b/MediaBrowser.Server.Implementations/Connect/Responses.cs index a3b0369ba1..eeb56d1c91 100644 --- a/MediaBrowser.Server.Implementations/Connect/Responses.cs +++ b/MediaBrowser.Server.Implementations/Connect/Responses.cs @@ -28,6 +28,13 @@ namespace MediaBrowser.Server.Implementations.Connect public class ServerUserAuthorizationResponse { - + public string Id { get; set; } + public string ServerId { get; set; } + public string UserId { get; set; } + public string AccessToken { get; set; } + public string DateCreated { get; set; } + public bool IsActive { get; set; } + public string AcceptStatus { get; set; } + public string UserType { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index f8bb0f1d50..543bcced26 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -453,7 +453,8 @@ "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 will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", + "MessageMediaBrowserAccountAdded": "The Media Browser account has been successfully linked to this user.", + "MessagePendingMediaBrowserAccountAdded": "A Media Browser account has been linked to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", "HeaderMediaBrowserAccountRemoved": "Media Browser Account Removed", "MessageMediaBrowserAccontRemoved": "The Media Browser account has been removed from this user.", "TooltipLinkedToMediaBrowserConnect": "Linked to Media Browser Connect" diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 86dc60c2ee..781b3e927a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -684,6 +684,7 @@ "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".", "LabelSupportedMediaTypes": "Supported Media Types:", "TabIdentification": "Identification", + "HeaderIdentification": "Identification", "TabDirectPlay": "Direct Play", "TabContainers": "Containers", "TabCodecs": "Codecs", From 6babe4f5103c83d75da1924027f6e13aea165085 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 14 Sep 2014 19:41:26 -0400 Subject: [PATCH 7/7] connect text change --- .../Localization/JavaScript/javascript.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 543bcced26..297e351ea6 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -453,8 +453,8 @@ "MessageYouHaveAnActiveRecurringMembership": "You have an active {0} membership. You can upgrade your plan using the options below.", "ButtonDelete": "Delete", "HeaderMediaBrowserAccountAdded": "Media Browser Account Added", - "MessageMediaBrowserAccountAdded": "The Media Browser account has been successfully linked to this user.", - "MessagePendingMediaBrowserAccountAdded": "A Media Browser account has been linked to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", + "MessageMediaBrowserAccountAdded": "The Media Browser account has been added to this user.", + "MessagePendingMediaBrowserAccountAdded": "The Media Browser account has been added to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.", "HeaderMediaBrowserAccountRemoved": "Media Browser Account Removed", "MessageMediaBrowserAccontRemoved": "The Media Browser account has been removed from this user.", "TooltipLinkedToMediaBrowserConnect": "Linked to Media Browser Connect"