public void IPAddressDAO_Update_SuccessfulUpdate(string ip, long timestampLocked, int registrationFailures,
                                                         long lastRegFailTimestamp)
        {
            // Arrange

            UnitTestIPAddressDAO ipDAO = new UnitTestIPAddressDAO();
            // Create an IP.
            IPAddressRecord ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);

            ipDAO.Create(ipRecord);

            // Prepare a new data to update.
            IPAddressRecord updatedRecord = new IPAddressRecord(ip, 1, 1, 1);

            // Act

            // Update the data of the IP.
            ipDAO.Update(updatedRecord);
            // Read the IP.
            IPAddressObject ipObject = (IPAddressObject)ipDAO.ReadById(ip);
            // Check if the IP was updated correctly and set the result to true.
            bool result = DataEquals(ipRecord, ipObject);

            // Assert

            // The result should be true.
            Assert.IsTrue(result);
        }
예제 #2
0
        public async Task IPAddressDAO_ReadByIdAsync_SuccessfulRead(string ip, long timestampLocked, int registrationFailures,
                                                                    long lastRegFailTimestamp)
        {
            // Arrange

            // Create an IP.
            IPAddressRecord ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);
            await ipDAO.CreateAsync(ipRecord).ConfigureAwait(false);

            // Act

            // Read the IP.
            IPAddressObject ipObject = (IPAddressObject)await ipDAO.ReadByIdAsync(ip).ConfigureAwait(false);

            // Check if the read IP is correct and set the result accordingly.
            bool result = DataEquals(ipRecord, ipObject);

            // Assert

            // The result should be true.
            Assert.IsTrue(result);

            // Clean up

            // Delete the IP.
            await ipDAO.DeleteByIdsAsync(new List <string>() { ip }).ConfigureAwait(false);
        }
        public void IPAddressDAO_ReadById_UnsuccessfulRead(string ip, long timestampLocked, int registrationFailures,
                                                           long lastRegFailTimestamp)
        {
            // Arrange

            UnitTestIPAddressDAO ipDAO = new UnitTestIPAddressDAO();
            // Create an IP.
            IPAddressRecord ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);

            ipDAO.Create(ipRecord);
            bool result = false;

            // Act
            try
            {
                // Read a non-existing IP.
                IPAddressObject ipObject = (IPAddressObject)ipDAO.ReadById(NonExistingIP);
            }
            catch (ArgumentException)
            {
                // Catch the exception and set the result to true.
                result = true;
            }

            // Assert

            // The result should be true.
            Assert.IsTrue(result);
        }
예제 #4
0
        public async Task IPAddressDAO_CreateAsync_SuccessfulCreation(string ip, long timestampLocked, int registrationFailures,
                                                                      long lastRegFailTimestamp)
        {
            // Arrange
            IPAddressRecord ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);

            // Act

            // Create IP Address.
            await ipDAO.CreateAsync(ipRecord);

            IPAddressObject ipObject = (IPAddressObject)await ipDAO.ReadByIdAsync(ip).ConfigureAwait(false);

            // Check if the data created is correct.
            bool correctDataResult = DataEquals(ipRecord, ipObject);

            // Assert

            // The data should be correct.
            Assert.IsTrue(correctDataResult);

            // Clean up

            // Delete the IP.
            await ipDAO.DeleteByIdsAsync(new List <string>() { ip }).ConfigureAwait(false);
        }
예제 #5
0
        /// <summary>
        /// Deletes the entry in the data store pointed to by the <paramref name="ipAddress"/>.
        /// </summary>
        /// <param name="ipAddress">The ip address to delete from the data store.</param>
        /// <returns>Task (bool) whether the function completed without exception</returns>
        public async Task <bool> DeleteIPAsync(string ipAddress)
        {
            // Check for ip existence.
            if (!await CheckIPExistenceAsync(ipAddress).ConfigureAwait(false))
            {
                throw new ArgumentException(Constants.DeleteIPDNE);
            }

            // If the column is masked, mask the ip.
            string id = ipAddress;

            if (Constants.AnonymousUserDAOIsColumnMasked[Constants.AnonymousUserDAOIPColumn])
            {
                id = _maskingService.MaskString(ipAddress);
            }

            // Get the masked object from the ipDAO and decrement its mapping before deleteing.
            IPAddressObject maskedObj = await _anonymousUserDAO.ReadByIdAsync(id).ConfigureAwait(false) as IPAddressObject;

            await _maskingService.DecrementMappingForDeleteAsync(maskedObj).ConfigureAwait(false);

            await _anonymousUserDAO.DeleteByIdsAsync(new List <string>() { id }).ConfigureAwait(false);

            return(true);
        }
예제 #6
0
        public async Task IPAddressDAO_UpdateAsync_SuccessfulUpdate(string ip, long timestampLocked, int registrationFailures,
                                                                    long lastRegFailTimestamp)
        {
            // Arrange

            // Create an IP.
            IPAddressRecord ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);
            await ipDAO.CreateAsync(ipRecord).ConfigureAwait(false);

            // Prepare a new data to update.
            IPAddressRecord updatedRecord = new IPAddressRecord(ip, 1, 1, 1);

            // Act

            // Update the data of the IP.
            await ipDAO.UpdateAsync(updatedRecord);

            // Read the IP.
            IPAddressObject ipObject = (IPAddressObject)await ipDAO.ReadByIdAsync(ip);

            // Check if the IP was updated correctly and set the result to true.
            bool result = DataEquals(updatedRecord, ipObject);

            // Assert

            // The result should be true.
            Assert.IsTrue(result);

            // Clean up

            // Delete the IP.
            await ipDAO.DeleteByIdsAsync(new List <string>() { ip }).ConfigureAwait(false);
        }
예제 #7
0
        public async Task IPAddressDAO_ReadByIdAsync_UnsuccessfulRead(string ip, long timestampLocked, int registrationFailures,
                                                                      long lastRegFailTimestamp)
        {
            // Arrange

            // Create an IP.
            IPAddressRecord ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);
            await ipDAO.CreateAsync(ipRecord).ConfigureAwait(false);

            bool result = false;

            // Act
            try
            {
                // Read a non-existing IP.
                IPAddressObject ipObject = (IPAddressObject)await ipDAO.ReadByIdAsync(NonExistingIP).ConfigureAwait(false);
            }
            catch (ArgumentException)
            {
                // Catch the exception and set the result to true.
                result = true;
            }

            // Assert

            // The result should be true.
            Assert.IsTrue(result);

            // Clean up

            await ipDAO.DeleteByIdsAsync(new List <string>() { ip }).ConfigureAwait(false);
        }
예제 #8
0
        /// <summary>
        /// Updates an entry in the IP Address data store using the <paramref name="ipRecord"/>.
        /// </summary>
        /// <param name="ipRecord">The unmasked record conveying the data to update.</param>
        /// <returns>Task (bool) whether the function completed without exception</returns>
        public async Task <bool> UpdateIPAsync(IPAddressRecord ipRecord)
        {
            // Record must be unmasked.
            if (ipRecord.IsMasked())
            {
                throw new ArgumentException(Constants.UpdateIPRecordMasked);
            }

            // If the column is masked, mask the ip.
            string id = ipRecord.GetData()[Constants.AnonymousUserDAOIPColumn] as string;

            if (Constants.AnonymousUserDAOIsColumnMasked[Constants.AnonymousUserDAOIPColumn])
            {
                id = _maskingService.MaskString(id);
            }

            IPAddressRecord maskedRecord = await _maskingService.MaskAsync(ipRecord, false).ConfigureAwait(false) as IPAddressRecord;

            // Get the masked object from the ipDAO and decrement its mapping before updating.
            IPAddressObject maskedObj = await _anonymousUserDAO.ReadByIdAsync(id).ConfigureAwait(false) as IPAddressObject;

            await _maskingService.DecrementMappingForUpdateAsync(maskedRecord, maskedObj).ConfigureAwait(false);

            return(await _anonymousUserDAO.UpdateAsync(maskedRecord).ConfigureAwait(false));
        }
예제 #9
0
        private bool DataEquals(IPAddressRecord ipRecord, IPAddressObject ipObject)
        {
            IDictionary <string, object> recordData = ipRecord.GetData();

            Console.WriteLine(recordData[Constants.AnonymousUserDAOIPColumn]);
            Console.WriteLine(recordData[Constants.AnonymousUserDAOtimestampLockedColumn]);
            Console.WriteLine(recordData[Constants.AnonymousUserDAOregistrationFailuresColumn]);
            Console.WriteLine(recordData[Constants.AnonymousUserDAOlastRegFailTimestampColumn]);
            Console.WriteLine(ipObject.IP);
            Console.WriteLine(ipObject.TimestampLocked);
            Console.WriteLine(ipObject.RegistrationFailures);
            Console.WriteLine(ipObject.LastRegFailTimestamp);

            if (((string)recordData[Constants.AnonymousUserDAOIPColumn]).Equals(ipObject.IP) &&
                ((long)recordData[Constants.AnonymousUserDAOtimestampLockedColumn]).Equals(ipObject.TimestampLocked) &&
                ((int)recordData[Constants.AnonymousUserDAOregistrationFailuresColumn]).Equals(ipObject.RegistrationFailures) &&
                ((long)recordData[Constants.AnonymousUserDAOlastRegFailTimestampColumn]).Equals(ipObject.LastRegFailTimestamp))
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #10
0
        /// <summary>
        /// Asynchronously check if the <paramref name="ipAddress"/> is locked in the data store.
        /// </summary>
        /// <param name="ipAddress">The ip address to check (string)</param>
        /// <returns>Task (bool) whether the ip is locked</returns>
        public async Task <bool> CheckIfIPLockedAsync(string ipAddress)
        {
            // Asynchronously gets the info of the ipAddress.
            IPAddressObject ip = await GetIPAddressInfoAsync(ipAddress).ConfigureAwait(false);

            // The ip is locked if the timetamp locked has a value.
            return(ip.TimestampLocked != Constants.NoValueLong);
        }
        /// <summary>
        /// Check if the <paramref name="ipAddress"/> is locked in the data store.
        /// </summary>
        /// <param name="ipAddress">The ip address to check (string)</param>
        /// <returns>Task (bool) whether the ip is locked</returns>
        public static bool CheckIfIPLocked(string ipAddress)
        {
            // Gets the info of the ipAddress.
            IPAddressObject ip = GetIPAddressInfo(ipAddress);

            // The ip is locked if the timetamp locked has a value.
            return(ip.TimestampLocked != Constants.NoValueLong);
        }
예제 #12
0
        /// <summary>
        /// Asynchronously gets the <paramref name="ipAddress"/> info and return as an object.
        /// </summary>
        /// <param name="ipAddress">The ip address of the record in the data store (string)</param>
        /// <returns>Task (IPAddressObject) the object representing the ip info</returns>
        public async Task <IPAddressObject> GetIPAddressInfoAsync(string ipAddress)
        {
            string id = ipAddress;

            if (Constants.AnonymousUserDAOIsColumnMasked[Constants.AnonymousUserDAOIPColumn])
            {
                id = _maskingService.MaskString(ipAddress);
            }

            // Cast the return result of asynchronously reading by the ip address into the IP object.
            IPAddressObject ip = await _anonymousUserDAO.ReadByIdAsync(id).ConfigureAwait(false) as IPAddressObject;

            return(await _maskingService.UnMaskAsync(ip).ConfigureAwait(false) as IPAddressObject);
        }
예제 #13
0
        /// <summary>
        /// Increment the registration failures of the anonymous user defined by the <paramref name="ipAddress"/>.
        /// </summary>
        /// <param name="ipAddress">The ip address to increment the registration failures of (string)</param>
        /// <param name="maxTimeBeforeFailureReset">The time before their failures reset (TimeSpan)</param>
        /// <param name="maxNumberOfTries">The max number of registration tries before they get locked (int)</param>
        /// <returns>Task (bool) whether the funciton executed without exception</returns>
        public async Task <bool> IncrementRegistrationFailuresAsync(string ipAddress, TimeSpan maxTimeBeforeFailureReset, int maxNumberOfTries)
        {
            IPAddressObject ip = await GetIPAddressInfoAsync(ipAddress).ConfigureAwait(false);

            IPAddressRecord record;

            // Need to check if the maxtime + lastTime is less than now.
            // if it is then reset the failure
            long lastRegFailTimestamp = ip.LastRegFailTimestamp;
            long maxSeconds           = TimeUtilityService.TimespanToSeconds(maxTimeBeforeFailureReset);
            long currentUnix          = TimeUtilityService.CurrentUnixTime();

            bool reset = false;

            // If the time has passed their max time before reset, reset their failures. Don't reset
            // if they have no last registration fail timestamp.
            if (lastRegFailTimestamp + maxSeconds < currentUnix && lastRegFailTimestamp != Constants.NoValueLong)
            {
                reset  = true;
                record = new IPAddressRecord(ipAddress, registrationFailures: 0);

                await UpdateIPAsync(record).ConfigureAwait(false);
            }

            // Increment the user's login Failure count.
            int updatedRegistrationFailures = reset ? 1 : ip.RegistrationFailures + 1;

            // Lock the ip if they have reached the max number of tries.
            // Update the last reg fail time.
            if (updatedRegistrationFailures >= maxNumberOfTries)
            {
                record = new IPAddressRecord(ipAddress, timestampLocked: currentUnix, registrationFailures: updatedRegistrationFailures, lastRegFailTimestamp: currentUnix);

                // Asynchronously notify the system admin if an ip address was locked during registration.
                await SystemUtilityService.NotifySystemAdminAsync($"{ipAddress} was locked at {currentUnix}", Constants.SystemAdminEmailAddress).ConfigureAwait(false);
            }
            else
            {
                record = new IPAddressRecord(ipAddress, registrationFailures: updatedRegistrationFailures, lastRegFailTimestamp: currentUnix);
            }

            return(await UpdateIPAsync(record).ConfigureAwait(false));
        }
예제 #14
0
        /// <summary>
        /// Read the information in the data store pointed to by the <paramref name="id"/>.
        /// </summary>
        /// <param name="id">The id of the row to read (string)</param>
        /// <returns>Task (IDataObject) the information represented as an object</returns>
        public async Task <IDataObject> ReadByIdAsync(string id)
        {
            // Check if the id exists in the table, and throw an argument exception if it doesn't.
            if (!await CheckIPExistenceAsync(id).ConfigureAwait(false))
            {
                throw new ArgumentException(Constants.IPReadDNE);
            }

            // Object to return -- IPAddressObject.
            IPAddressObject result;

            // Get the connection inside of a using statement to properly dispose/close.
            using (MySqlConnection connection = new MySqlConnection(SQLConnection))
            {
                // Open the connection.
                connection.Open();

                // Construct the sql string to get the record where the id column equals the id parameter.
                string sqlString = $"SELECT * FROM {Constants.AnonymousUserDAOTableName} WHERE {Constants.AnonymousUserDAOIPColumn} = @ID;";

                // Get the command and data table objects inside using statements to properly dispose/close.
                using (MySqlCommand command = new MySqlCommand(sqlString, connection))
                    using (DataTable dataTable = new DataTable())
                    {
                        // Add the value to the id parameter, execute the reader asynchronously, load the reader into
                        // the data table, and get the first row (the result).
                        command.Parameters.AddWithValue("@ID", id);
                        var reader = await command.ExecuteReaderAsync().ConfigureAwait(false);

                        dataTable.Load(reader);
                        DataRow row = dataTable.Rows[0];

                        // Construct the IPAddressObject by casting the values of the columns to their proper data types.
                        result = new IPAddressObject((string)row[Constants.AnonymousUserDAOIPColumn],
                                                     (long)row[Constants.AnonymousUserDAOtimestampLockedColumn],
                                                     (int)row[Constants.AnonymousUserDAOregistrationFailuresColumn],
                                                     (long)row[Constants.AnonymousUserDAOlastRegFailTimestampColumn]);
                    }
            }

            return(result);
        }
        public void IPAddressDAO_Create_SuccessfulCreation(string ip, long timestampLocked, int registrationFailures,
                                                           long lastRegFailTimestamp)
        {
            // Arrange
            UnitTestIPAddressDAO ipDAO    = new UnitTestIPAddressDAO();
            IPAddressRecord      ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);

            // Act

            // Create IP Address.
            ipDAO.Create(ipRecord);
            IPAddressObject ipObject = (IPAddressObject)ipDAO.ReadById(ip);
            // Check if the data created is correct.
            bool correctDataResult = DataEquals(ipRecord, ipObject);

            // Assert

            // The data should be correct.
            Assert.IsTrue(correctDataResult);
        }
예제 #16
0
        public async Task MaskingService_UnMaskAsync_WorksWithDifferentObjects(bool isTemp, string username, string name, string email,
                                                                               string phoneNumber, string password, string userType, string salt, string ipAddress)
        {
            await _userManagementService.CreateIPAsync(ipAddress).ConfigureAwait(false);

            UserRecord userRecord = new UserRecord(username, name, email, phoneNumber, password, Constants.EnabledStatus, userType,
                                                   salt, Constants.NoValueLong, Constants.NoValueString, Constants.NoValueLong, Constants.NoValueInt, Constants.NoValueLong, Constants.NoValueInt, Constants.NoValueInt);

            await _userManagementService.CreateUserAsync(isTemp, userRecord).ConfigureAwait(false);

            string id = username;

            if (Constants.UserDAOIsColumnMasked[Constants.UserDAOusernameColumn])
            {
                id = _maskingService.MaskString(username);
            }

            UserObject rawUser = (UserObject)await _userDAO.ReadByIdAsync(id).ConfigureAwait(false);

            id = ipAddress;

            if (Constants.AnonymousUserDAOIsColumnMasked[Constants.AnonymousUserDAOIPColumn])
            {
                id = _maskingService.MaskString(ipAddress);
            }

            // Cast the return result of asynchronously reading by the ip address into the IP object.
            IPAddressObject rawIP = (IPAddressObject)await _ipDAO.ReadByIdAsync(id).ConfigureAwait(false);

            IPAddressObject ip = (IPAddressObject)await _maskingService.UnMaskAsync(rawIP).ConfigureAwait(false);

            UserObject user = (UserObject)await _maskingService.UnMaskAsync(rawUser).ConfigureAwait(false);

            Assert.IsTrue(ip.IsUnMasked());
            Assert.IsTrue(user.IsUnMasked());

            await _userManagementService.DeleteIPAsync(ipAddress).ConfigureAwait(false);

            await _userManagementService.DeleteUserAsync(username).ConfigureAwait(false);
        }
        public void IPAddressDAO_ReadById_SuccessfulRead(string ip, long timestampLocked, int registrationFailures,
                                                         long lastRegFailTimestamp)
        {
            // Arrange

            UnitTestIPAddressDAO ipDAO = new UnitTestIPAddressDAO();
            // Create an IP.
            IPAddressRecord ipRecord =
                new IPAddressRecord(ip, timestampLocked, registrationFailures, lastRegFailTimestamp);

            ipDAO.Create(ipRecord);

            // Act

            // Read the IP.
            IPAddressObject ipObject = (IPAddressObject)ipDAO.ReadById(ip);
            // Check if the read IP is correct and set the result accordingly.
            bool result = DataEquals(ipRecord, ipObject);

            // Assert

            // The result should be true.
            Assert.IsTrue(result);
        }
예제 #18
0
        // Time out after X seconds will be conducted in Controllers with Task.Wait

        // Re-trying after exceptions occur will be conducted in Controllers, who will check if an exception occurred and how
        // many exceptions have currently occured after a manager has returned.

        // Encrypted password, encrypted AES key, and AES IV are all in hex string format.
        public async Task <Result <bool> > RegisterAsync(string firstName, string lastName,
                                                         string email, string username, string phoneNumber,
                                                         string ipAddress, string hashedPassword, string salt,
                                                         string proxyPassword, int currentNumExceptions)
        {
            try
            {
                bool registrationSuccess = false;

                // If the ip address is not in our system. Insert into datastore
                if (!await _userManagementService.CheckIPExistenceAsync(ipAddress).ConfigureAwait(false))
                {
                    await _userManagementService.CreateIPAsync(ipAddress).ConfigureAwait(false);
                }

                // Grab the user ip object.
                IPAddressObject ip = await _userManagementService.GetIPAddressInfoAsync(ipAddress).ConfigureAwait(false);

                // Set fields for repeated fails to lock them out.
                long timeLocked  = ip.TimestampLocked;
                long maxSeconds  = TimeUtilityService.TimespanToSeconds(Constants.MaxIPLockTime);
                long currentUnix = TimeUtilityService.CurrentUnixTime();

                // If the time has passed their max time before unlock, unlock them
                if (timeLocked + maxSeconds < currentUnix && timeLocked != Constants.NoValueLong)
                {
                    await _userManagementService.UnlockIPAsync(ipAddress).ConfigureAwait(false);
                }

                if (await _userManagementService.CheckIfIPLockedAsync(ipAddress).ConfigureAwait(false))
                {
                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.IPLockedLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.IPLockedUserMessage, registrationSuccess, false));
                }

                // Check the length of their first name.
                if (!StringUtilityService.CheckLength(firstName, Constants.MaximumFirstNameCharacters,
                                                      Constants.MinimumFirstNameCharacters))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidFirstNameLengthLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidFirstNameLengthUserMessage, registrationSuccess, false));
                }

                // Check the character requirements of their first name.
                if (!StringUtilityService.CheckCharacters(firstName, Constants.CharSetsData[Constants.FirstNameCharacterType]))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidFirstNameCharactersLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidFirstNameCharactersUserMessage, registrationSuccess, false));
                }

                // Check the length of their last name.
                if (!StringUtilityService.CheckLength(lastName, Constants.MaximumLastNameCharacters,
                                                      Constants.MinimumLastNameCharacters))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidLastNameLengthLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidLastNameLengthUserMessage, registrationSuccess, false));
                }

                // Check the character requirements of their last name.
                if (!StringUtilityService.CheckCharacters(lastName, Constants.CharSetsData[Constants.LastNameCharacterType]))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidLastNameCharactersLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidLastNameCharactersUserMessage, registrationSuccess, false));
                }

                // Check the length of their email.
                if (!StringUtilityService.CheckLength(email, Constants.MaximumEmailCharacters,
                                                      Constants.MinimumEmailCharacters))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidEmailLengthLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidEmailLengthUserMessage, registrationSuccess, false));
                }

                // Check the character requirements of their email.
                if (!StringUtilityService.CheckCharacters(email, Constants.CharSetsData[Constants.EmailCharacterType]))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidEmailCharactersLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidEmailCharactersUserMessage, registrationSuccess, false));
                }

                // Check the format of their email.
                if (!StringUtilityService.CheckEmailFormatValidity(email))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidEmailFormatMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidEmailFormatMessage, registrationSuccess, false));
                }

                // Email must be unique after canonicalization.
                string canonicalizedEmail = StringUtilityService.CanonicalizeEmail(email);

                if (await _userManagementService.CheckEmailExistenceAsync(canonicalizedEmail).ConfigureAwait(false))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.EmailExistsLogMessage).ConfigureAwait(false);

                    Console.WriteLine("Email");
                    return(SystemUtilityService.CreateResult(Constants.UniqueIdExistsRegistrationUserMessage, registrationSuccess, false));
                }

                // Check the length of their username.
                if (!StringUtilityService.CheckLength(username, Constants.MaximumUsernameCharacters,
                                                      Constants.MinimumUsernameCharacters))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidUsernameLengthLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidUsernameLengthUserMessage, registrationSuccess, false));
                }

                // Check the character requirements of their username.
                if (!StringUtilityService.CheckCharacters(email, Constants.CharSetsData[Constants.UsernameCharacterType]))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidUsernameCharactersLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidUsernameCharactersUserMessage, registrationSuccess, false));
                }

                // Check username uniqueness.
                if (await _userManagementService.CheckUserExistenceAsync(username).ConfigureAwait(false))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.UsernameExistsLogMessage).ConfigureAwait(false);

                    Console.WriteLine("username");
                    return(SystemUtilityService.CreateResult(Constants.UniqueIdExistsRegistrationUserMessage, registrationSuccess, false));
                }

                // Check the length of their phone number.
                if (!StringUtilityService.CheckLength(phoneNumber, Constants.PhoneNumberCharacterLength))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidPhoneNumberLengthLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidPhoneNumberLengthUserMessage, registrationSuccess, false));
                }

                // Check the character requirements of their phone number.
                if (!StringUtilityService.CheckCharacters(phoneNumber, Constants.CharSetsData[Constants.PhoneNumberCharacterType]))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidPhoneNumberCharactersLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidPhoneNumberCharactersUserMessage, registrationSuccess, false));
                }

                // Check phone number uniqueness.
                if (await _userManagementService.CheckPhoneNumberExistenceAsync(phoneNumber).ConfigureAwait(false))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.PhoneNumberExistsLogMessage).ConfigureAwait(false);

                    Console.WriteLine("phone");
                    return(SystemUtilityService.CreateResult(Constants.UniqueIdExistsRegistrationUserMessage, registrationSuccess, false));
                }

                // Check the length of their password.
                if (!StringUtilityService.CheckLength(proxyPassword, Constants.MaximumPasswordCharacters,
                                                      Constants.MinimumPasswordCharacters))
                {
                    await _userManagementService.IncrementRegistrationFailuresAsync(ipAddress,
                                                                                    Constants.RegistrationTriesResetTime,
                                                                                    Constants.MaxRegistrationAttempts).ConfigureAwait(false);

                    _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                                 Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress,
                                                 Constants.InvalidPasswordLengthLogMessage).ConfigureAwait(false);

                    return(SystemUtilityService.CreateResult(Constants.InvalidPasswordLengthUserMessage,
                                                             registrationSuccess, false));
                }

                // Successful registration!
                registrationSuccess = true;

                // Create user record object to represent a user.

                // Email code, email code timestamp, login failures, last login failure timestamp, email code failures, and phone code failures initialized to have no value.
                UserRecord user = new UserRecord(username, firstName + " " + lastName, canonicalizedEmail, phoneNumber, hashedPassword, Constants.EnabledStatus, Constants.CustomerUserType,
                                                 salt, Constants.NoValueLong, Constants.NoValueString, Constants.NoValueLong, Constants.NoValueInt, Constants.NoValueLong, Constants.NoValueInt, Constants.NoValueInt);

                // Create that user.
                await _userManagementService.CreateUserAsync(true, user).ConfigureAwait(false);

                _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                             Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress).ConfigureAwait(false);

                return(SystemUtilityService.CreateResult(Constants.RegistrationSuccessUserMessage, registrationSuccess, false));
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                _ = _loggingManager.LogAsync(DateTime.UtcNow.ToString(Constants.LoggingFormatString),
                                             Constants.RegistrationOperation, Constants.AnonymousUserIdentifier, ipAddress, e.Message).ConfigureAwait(false);

                if (currentNumExceptions + 1 >= Constants.MaximumOperationRetries)
                {
                    await SystemUtilityService.NotifySystemAdminAsync($"{Constants.RegistrationOperation} failed a maximum number of times for {ipAddress}.", Constants.SystemAdminEmailAddress).ConfigureAwait(false);
                }

                return(SystemUtilityService.CreateResult(Constants.SystemErrorUserMessage, false, true));
            }
        }