public async Task ReportServerUsage(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var data = new Dictionary<string, string> { { "feature", _applicationHost.Name }, { "mac", _applicationHost.SystemId }, { "serverid", _applicationHost.SystemId }, { "deviceid", _applicationHost.SystemId }, { "ver", _applicationHost.ApplicationVersion.ToString() }, { "platform", _applicationHost.OperatingSystemDisplayName }, { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower()} }; var users = _userManager.Users.ToList(); data["localusers"] = users.Count(i => !i.ConnectLinkType.HasValue).ToString(CultureInfo.InvariantCulture); data["guests"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest).ToString(CultureInfo.InvariantCulture); data["linkedusers"] = users.Count(i => i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.LinkedUser).ToString(CultureInfo.InvariantCulture); data["plugins"] = string.Join(",", _applicationHost.Plugins.Select(i => i.Id).ToArray()); var logErrors = false; #if DEBUG logErrors = true; #endif var options = new HttpRequestOptions { Url = MbAdminUrl + "service/registration/ping", CancellationToken = cancellationToken, // Seeing block length errors EnableHttpCompression = false, LogRequest = false, LogErrors = logErrors, BufferContent = false }; options.SetPostData(data); using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) { } }
/// <summary> /// Performs a POST request /// </summary> /// <param name="options">The options.</param> /// <param name="postData">Params to add to the POST data.</param> /// <returns>stream on success, null on failure</returns> public async Task<Stream> Post(HttpRequestOptions options, Dictionary<string, string> postData) { options.SetPostData(postData); var response = await Post(options).ConfigureAwait(false); return response.Content; }
public async Task ReportAppUsage(ClientInfo app, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(app.DeviceId)) { throw new ArgumentException("Client info must have a device Id"); } _logger.Info("App Activity: app: {0}, version: {1}, deviceId: {2}, deviceName: {3}", app.AppName ?? "Unknown App", app.AppVersion ?? "Unknown", app.DeviceId, app.DeviceName ?? "Unknown"); cancellationToken.ThrowIfCancellationRequested(); var data = new Dictionary<string, string> { { "feature", app.AppName ?? "Unknown App" }, { "serverid", _applicationHost.SystemId }, { "deviceid", app.DeviceId }, { "mac", app.DeviceId }, { "ver", app.AppVersion ?? "Unknown" }, { "platform", app.DeviceName }, }; var logErrors = false; #if DEBUG logErrors = true; #endif var options = new HttpRequestOptions { Url = MbAdminUrl + "service/registration/ping", CancellationToken = cancellationToken, // Seeing block length errors EnableHttpCompression = false, LogRequest = false, LogErrors = logErrors, BufferContent = false }; options.SetPostData(data); using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) { } }
private async Task<UserLinkResult> SendNewUserInvitation(string fromName, string email) { var url = GetConnectUrl("users/invite"); var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; var postData = new Dictionary<string, string> { {"email", email}, {"requesterUserName", fromName} }; options.SetPostData(postData); SetApplicationHeader(options); // No need to examine the response using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { } return new UserLinkResult { IsNewUserInvitation = true, GuestDisplayName = email }; }
private async Task<MBRegistrationRecord> GetRegistrationStatusInternal(string feature, string mb2Equivalent = null, string version = null) { var lastChecked = LicenseFile.LastChecked(feature); //check the reg file first to alleviate strain on the MB admin server - must actually check in every 30 days tho var reg = new RegRecord { // Cache the result for up to a week registered = lastChecked > DateTime.UtcNow.AddDays(-7) }; var success = reg.registered; if (!(lastChecked > DateTime.UtcNow.AddDays(-1))) { var data = new Dictionary<string, string> { { "feature", feature }, { "key", SupporterKey }, { "mac", _appHost.SystemId }, { "systemid", _appHost.SystemId }, { "mb2equiv", mb2Equivalent }, { "ver", version }, { "platform", _appHost.OperatingSystemDisplayName }, { "isservice", _appHost.IsRunningAsService.ToString().ToLower() } }; try { var options = new HttpRequestOptions { Url = MBValidateUrl, // Seeing block length errors EnableHttpCompression = false, BufferContent = false }; options.SetPostData(data); using (var json = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { reg = _jsonSerializer.DeserializeFromStream<RegRecord>(json); success = true; } if (reg.registered) { LicenseFile.AddRegCheck(feature); } else { LicenseFile.RemoveRegCheck(feature); } } catch (Exception e) { _logger.ErrorException("Error checking registration status of {0}", e, feature); } } var record = new MBRegistrationRecord { IsRegistered = reg.registered, ExpirationDate = reg.expDate, RegChecked = true, RegError = !success }; record.TrialVersion = IsInTrial(reg.expDate, record.RegChecked, record.IsRegistered); record.IsValid = !record.RegChecked || record.IsRegistered || record.TrialVersion; return record; }
private async Task<UserLinkResult> LinkUserInternal(string userId, string connectUsername) { if (string.IsNullOrWhiteSpace(userId)) { throw new ArgumentNullException("userId"); } if (string.IsNullOrWhiteSpace(connectUsername)) { throw new ArgumentNullException("connectUsername"); } if (string.IsNullOrWhiteSpace(ConnectServerId)) { throw new ArgumentNullException("ConnectServerId"); } var connectUser = await GetConnectUser(new ConnectUserQuery { NameOrEmail = connectUsername }, CancellationToken.None).ConfigureAwait(false); if (!connectUser.IsActive) { throw new ArgumentException("The Emby account has been disabled."); } var user = GetUser(userId); if (!string.IsNullOrWhiteSpace(user.ConnectUserId)) { await RemoveConnect(user, connectUser.Id).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<string, string> { {"serverId", ConnectServerId}, {"userId", connectUser.Id}, {"userType", "Linked"}, {"accessToken", accessToken} }; options.SetPostData(postData); SetServerAccessToken(options); SetApplicationHeader(options); var result = new UserLinkResult(); // No need to examine the response using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { var response = _json.DeserializeFromStream<ServerUserAuthorizationResponse>(stream); result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); } user.ConnectAccessKey = accessToken; user.ConnectUserName = connectUser.Name; user.ConnectUserId = connectUser.Id; user.ConnectLinkType = UserLinkType.LinkedUser; await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration); await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); return result; }
private async Task<UserLinkResult> InviteUserInternal(ConnectAuthorizationRequest request) { var connectUsername = request.ConnectUserName; var sendingUserId = request.SendingUserId; if (string.IsNullOrWhiteSpace(connectUsername)) { throw new ArgumentNullException("connectUsername"); } if (string.IsNullOrWhiteSpace(ConnectServerId)) { throw new ArgumentNullException("ConnectServerId"); } var sendingUser = GetUser(sendingUserId); var requesterUserName = sendingUser.ConnectUserName; if (string.IsNullOrWhiteSpace(requesterUserName)) { throw new ArgumentException("A Connect account is required in order to send invitations."); } string connectUserId = null; var result = new UserLinkResult(); try { var connectUser = await GetConnectUser(new ConnectUserQuery { NameOrEmail = connectUsername }, CancellationToken.None).ConfigureAwait(false); if (!connectUser.IsActive) { throw new ArgumentException("The Emby account is not active. Please ensure the account has been activated by following the instructions within the email confirmation."); } connectUserId = connectUser.Id; result.GuestDisplayName = connectUser.Name; } catch (HttpException ex) { if (!ex.StatusCode.HasValue) { throw; } // If they entered a username, then whatever the error is just throw it, for example, user not found if (!Validator.EmailIsValid(connectUsername)) { if (ex.StatusCode.Value == HttpStatusCode.NotFound) { throw new ResourceNotFoundException(); } throw; } if (ex.StatusCode.Value != HttpStatusCode.NotFound) { throw; } } if (string.IsNullOrWhiteSpace(connectUserId)) { return await SendNewUserInvitation(requesterUserName, connectUsername).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<string, string> { {"serverId", ConnectServerId}, {"userId", connectUserId}, {"userType", "Guest"}, {"accessToken", accessToken}, {"requesterUserName", requesterUserName} }; options.SetPostData(postData); SetServerAccessToken(options); SetApplicationHeader(options); // No need to examine the response using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { var response = _json.DeserializeFromStream<ServerUserAuthorizationResponse>(stream); result.IsPending = string.Equals(response.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase); _data.PendingAuthorizations.Add(new ConnectAuthorizationInternal { ConnectUserId = response.UserId, Id = response.Id, ImageUrl = response.UserImageUrl, UserName = response.UserName, EnabledLibraries = request.EnabledLibraries, EnabledChannels = request.EnabledChannels, EnableLiveTv = request.EnableLiveTv, AccessToken = accessToken }); CacheData(); } await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false); return result; }
private async Task CreateServerRegistration(string wanApiAddress, string localAddress) { if (string.IsNullOrWhiteSpace(wanApiAddress)) { throw new ArgumentNullException("wanApiAddress"); } var url = "Servers"; url = GetConnectUrl(url); var postData = new Dictionary<string, string> { {"name", _appHost.FriendlyName}, {"url", wanApiAddress}, {"systemId", _appHost.SystemId} }; if (!string.IsNullOrWhiteSpace(localAddress)) { postData["localAddress"] = localAddress; } var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; options.SetPostData(postData); SetApplicationHeader(options); using (var response = await _httpClient.Post(options).ConfigureAwait(false)) { var data = _json.DeserializeFromStream<ServerRegistrationResponse>(response.Content); _data.ServerId = data.Id; _data.AccessKey = data.AccessKey; CacheData(); } }
private async Task UpdateServerRegistration(string wanApiAddress, string localAddress) { if (string.IsNullOrWhiteSpace(wanApiAddress)) { throw new ArgumentNullException("wanApiAddress"); } if (string.IsNullOrWhiteSpace(ConnectServerId)) { throw new ArgumentNullException("ConnectServerId"); } var url = "Servers"; url = GetConnectUrl(url); url += "?id=" + ConnectServerId; var postData = new Dictionary<string, string> { {"name", _appHost.FriendlyName}, {"url", wanApiAddress}, {"systemId", _appHost.SystemId} }; if (!string.IsNullOrWhiteSpace(localAddress)) { postData["localAddress"] = localAddress; } var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; options.SetPostData(postData); SetServerAccessToken(options); SetApplicationHeader(options); // No need to examine the response using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { } }
private async Task CancelAuthorizationByConnectUserId(string connectUserId) { if (string.IsNullOrWhiteSpace(connectUserId)) { throw new ArgumentNullException("connectUserId"); } if (string.IsNullOrWhiteSpace(ConnectServerId)) { throw new ArgumentNullException("ConnectServerId"); } var url = GetConnectUrl("ServerAuthorizations"); var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; var postData = new Dictionary<string, string> { {"serverId", ConnectServerId}, {"userId", connectUserId} }; options.SetPostData(postData); SetServerAccessToken(options); SetApplicationHeader(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."); } }
public async Task Authenticate(string username, string passwordMd5) { if (string.IsNullOrWhiteSpace(username)) { throw new ArgumentNullException("username"); } if (string.IsNullOrWhiteSpace(passwordMd5)) { throw new ArgumentNullException("passwordMd5"); } var options = new HttpRequestOptions { Url = GetConnectUrl("user/authenticate") }; options.SetPostData(new Dictionary<string, string> { {"userName",username}, {"password",passwordMd5} }); SetApplicationHeader(options); // No need to examine the response using (var response = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content) { } }
private async Task UpdateServerRegistration(string wanApiAddress) { var url = "Servers"; url = GetConnectUrl(url); url += "?id=" + ConnectServerId; var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; options.SetPostData(new Dictionary<string, string> { {"name", _appHost.FriendlyName}, {"url", wanApiAddress}, {"systemid", _appHost.SystemId} }); options.RequestHeaders.Add("X-Connect-Token", ConnectAccessKey); // No need to examine the response using (var stream = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { } }
private async Task TryUploadUserPreferences(User user, CancellationToken cancellationToken) { if (user == null) { throw new ArgumentNullException("user"); } if (string.IsNullOrEmpty(user.ConnectUserId)) { return; } if (string.IsNullOrEmpty(ConnectAccessKey)) { return; } var url = GetConnectUrl("user/preferences"); url += "?userId=" + user.ConnectUserId; url += "&key=userpreferences"; var options = new HttpRequestOptions { Url = url, CancellationToken = cancellationToken }; var postData = new Dictionary<string, string>(); postData["data"] = _json.SerializeToString(ConnectUserPreferences.FromUserConfiguration(user.Configuration)); options.SetPostData(postData); SetServerAccessToken(options); SetApplicationHeader(options); try { // No need to examine the response using (var stream = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content) { } } catch (Exception ex) { _logger.ErrorException("Error uploading user preferences", ex); } }
private async Task RemoveLink(User user, string connectUserId) { if (!string.IsNullOrWhiteSpace(connectUserId)) { var url = GetConnectUrl("ServerAuthorizations"); var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; var postData = new Dictionary<string, string> { {"serverId", ConnectServerId}, {"userId", connectUserId} }; options.SetPostData(postData); SetServerAccessToken(options); try { // No need to examine the response using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) { } } catch (HttpException ex) { // If connect says the auth doesn't exist, we can handle that gracefully since this is a remove operation if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) { throw; } _logger.Debug("Connect returned a 404 when removing a user auth link. Handling it."); } } user.ConnectAccessKey = null; user.ConnectUserName = null; user.ConnectUserId = null; user.ConnectLinkType = UserLinkType.LinkedUser; await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); }
public async Task RemoveConnectSupporter(string id) { if (!_securityManager.IsMBSupporter) { throw new InvalidOperationException(); } var url = GetConnectUrl("keyAssociation"); var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; var postData = new Dictionary<string, string> { {"serverId", ConnectServerId}, {"supporterKey", _securityManager.SupporterKey}, {"userId", id} }; options.SetPostData(postData); SetServerAccessToken(options); SetApplicationHeader(options); // No need to examine the response using (var stream = (await _httpClient.SendAsync(options, "DELETE").ConfigureAwait(false)).Content) { } }
public async Task<ConnectSupporterSummary> GetConnectSupporterSummary() { if (!_securityManager.IsMBSupporter) { return new ConnectSupporterSummary(); } var url = GetConnectUrl("keyAssociation"); var options = new HttpRequestOptions { Url = url, CancellationToken = CancellationToken.None }; var postData = new Dictionary<string, string> { {"serverId", ConnectServerId}, {"supporterKey", _securityManager.SupporterKey} }; options.SetPostData(postData); SetServerAccessToken(options); SetApplicationHeader(options); // No need to examine the response using (var stream = (await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)).Content) { return _json.DeserializeFromStream<ConnectSupporterSummary>(stream); } }