public LoginInfo(string userName, string userPasswordHash, ISecretProvider secretProvider, ISecretPersistor secretPersistor)
 {
     UserName         = userName;
     UserPasswordHash = userPasswordHash;
     SecretProvider   = secretProvider;
     SecretPersistor  = secretPersistor;
 }
        public async Task <bool> Login(string userName, ISecretProvider secretProvider, ISecretPersistor secretPersistor = null)
        {
            if (string.IsNullOrWhiteSpace(userName))
            {
                throw new ArgumentException($"{nameof(userName)} not specified.", nameof(userName));
            }
            if (secretProvider == null)
            {
                throw new ArgumentNullException(nameof(secretProvider));
            }
            if (IsLoggedIn)
            {
                throw new InvalidOperationException("The client is already logged in.");
            }

            if (secretProvider.TryGetUserPasswordHash(out string userPasswordHash) == false)
            {
                string userPassword = await secretProvider.GetPassword();

                FormUrlEncodedContent formContent = CreateFormContent(new[]
                {
                    new KeyValuePair <string, string>("username_or_email", userName)
                });
                SaltResult saltResult = await _httpClient.PostFormData <SaltResult>(API_SALT_URI, formContent);

                if (CheckResultStatus(saltResult))
                {
                    userPasswordHash = BCrypt.HashPassword(userPassword, saltResult.Salt);
                }
                else
                {
                    return(false);
                }
            }

            LoginInfo loginInfo = new LoginInfo(userName, userPasswordHash, secretProvider, secretPersistor);

            if (await TryLogin(loginInfo))
            {
                _loginInfo         = loginInfo;
                _privateRootFolder = WsFolder.CreateRootFolder(this, true);
                _publicRootFolder  = WsFolder.CreateRootFolder(this, false);
                secretPersistor?.SaveUserPasswordHash(userPasswordHash);
                return(true);
            }
            return(false);
        }