Example #1
0
        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))
            {
                
            }
        }
Example #2
0
        /// <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;
        }
Example #3
0
        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))
            {

            }
        }
Example #4
0
        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
            };
        }
Example #5
0
        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;
        }
Example #6
0
        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;
        }
Example #7
0
        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;
        }
Example #8
0
        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();
            }
        }
Example #9
0
        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)
            {
            }
        }
Example #10
0
        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.");
            }
        }
Example #11
0
        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)
            {
            }
        }
Example #12
0
        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)
            {
            }
        }
Example #13
0
        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);
            }
        }
Example #14
0
        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);
        }
Example #15
0
        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)
            {
            }
        }
Example #16
0
        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);
            }
        }