/// <summary> /// Asynchronously logs to the data store and flat file. /// </summary> /// <param name="timestamp">The timestamp of the operation.</param> /// <param name="operation">The type of the operation.</param> /// <param name="identifier">The identifier of the operation's performer.</param> /// <param name="ipAddress">The ip address of the operation's performer.</param> /// <param name="errorType">The type of error that occurred during the operation (default = no error)</param> /// <returns>Task (bool) whether the logging operation was successful.</returns> private async Task <bool> LogAsync(string timestamp, string operation, string identifier, string ipAddress, string errorType = Constants.NoError) { // Attempt logging to both the data store and the flat file and track the results. bool ffLoggingResult = await _ffLoggingService.LogToFlatFileAsync(timestamp, operation, identifier, ipAddress, errorType, Constants.LogFolder, Constants.LogFileType).ConfigureAwait(false); bool dsLoggingResult = await _dsLoggingService.LogToDataStoreAsync(timestamp, operation, identifier, ipAddress, errorType).ConfigureAwait(false); int count = 0; // Retry whichever one failed, a maximum number of times. while (!(ffLoggingResult && dsLoggingResult) && count < Constants.LoggingRetriesAmount) { if (!ffLoggingResult) { ffLoggingResult = await _ffLoggingService.LogToFlatFileAsync(timestamp, operation, identifier, ipAddress, errorType, Constants.LogFolder, Constants.LogFileType).ConfigureAwait(false); } if (!dsLoggingResult) { dsLoggingResult = await _dsLoggingService.LogToDataStoreAsync(timestamp, operation, identifier, ipAddress, errorType).ConfigureAwait(false); } count++; } // If both succeeded we are finished. if (ffLoggingResult && dsLoggingResult) { return(true); } else { // Otherwise, if both failed notify the system admin. if (!ffLoggingResult && !dsLoggingResult) { await SystemUtilityService.NotifySystemAdminAsync($"Data Store and Flat File Logging failure for the following information:\n\n\t{timestamp}, {operation}, {identifier}, {ipAddress}, {errorType}", Constants.SystemAdminEmailAddress).ConfigureAwait(false); } else { // Otherwise rollback whichever one succeeded and notify the system admin. bool rollbackSuccess = false; if (ffLoggingResult) { rollbackSuccess = await _ffLoggingService.DeleteFromFlatFileAsync(timestamp, operation, identifier, ipAddress, errorType, Constants.LogFolder, Constants.LogFileType).ConfigureAwait(false); } if (dsLoggingResult) { rollbackSuccess = await _dsLoggingService.DeleteLogFromDataStoreAsync(timestamp, operation, identifier, ipAddress, errorType).ConfigureAwait(false); } await SystemUtilityService.NotifySystemAdminAsync($"{(ffLoggingResult ? "Flat File" : "Data Store")} Logging failure for the following information:\n\n\t{timestamp}, {operation}, {identifier}, {ipAddress}, {errorType}\n\nRollback status: {(rollbackSuccess ? "successful" : "failed")}", Constants.SystemAdminEmailAddress).ConfigureAwait(false); } return(false); } }
/// <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)); }