} // End of AddStudent /// <summary> /// Business logic for modifying Student records /// </summary> /// <param name="student"></param> /// <param name="userIsSuperAdmin"></param> /// <returns></returns> internal object ModifyStudentBLL(StudentModDTO student, bool userIsSuperAdmin) { // Create a new APIException object to store possible exceptions as checks are performed. APIException exceptionList = new APIException(); // Email check regex in Dictionary below // Ref: https://stackoverflow.com/a/45177249/12802214 // Check is virtually identical to that of the AddStudent method, except for the e-mail address unique check Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>() { { "firstname parameter cannot be empty.", student.Firstname == null || student.Firstname.Trim() == string.Empty }, { "lastname parameter cannot be empty", student.Lastname == null || student.Lastname.Trim() == string.Empty }, { "Email needs to be a valid email address", student.Email == null || !Regex.IsMatch(student.Email, @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$") }, { "Email address needs to be unique in the database (student record with that email already exists)", student.Email != null && _context.Users.Where(x => x.Email == student.Email).Include(student => student.StudentData).Any(x => x.StudentData.StudentID != student.StudentID) }, { "Email address domain not found in the list of valid domains", student.Email != null && !APIConfig.Configuration.GetSection("ValidEmailDomains").GetChildren().ToArray().Select(x => x.Value).ToArray().Contains(student.Email.Split("@")?[1] ?? "") }, { "Specified CohortID does not exist", !_context.Cohorts.Any(x => x.CohortID == student.CohortID) }, { "Specified cohort is inactive.", !(_context.Cohorts.Any(x => x.CohortID == student.CohortID && DateTime.Now >= x.StartDate && DateTime.Now <= x.EndDate) || userIsSuperAdmin) } }; foreach (KeyValuePair <string, bool> kvp in exceptionTests) { if (kvp.Value) { exceptionList.AddExMessage(kvp.Key); } } if (!exceptionList.HasExceptions) { // New database names will be trimmed and in Proper Case. string dbFirstname = String.Join(" ", student.Firstname.Trim().Split(" ").Select(x => $"{x.Substring(0, 1).ToUpper()}{x.Substring(1)?.ToLower()}").ToArray()); string dbLastname = String.Join(" ", student.Lastname.Trim().Split(" ").Select(x => $"{x.Substring(0, 1).ToUpper()}{x.Substring(1)?.ToLower()}").ToArray()); // Create a dictionary containing all data needed to create the user and pass back to API Target. StudentModDTO modifiedDbObject = new StudentModDTO { StudentID = student.StudentID, Firstname = dbFirstname, Lastname = dbLastname, Email = student.Email, Active = student.Active, CohortID = student.CohortID, BearTracksID = student.BearTracksID }; return(modifiedDbObject); } else { return(exceptionList); } } // End of ModifyStudent
public async Task <ActionResult> ModifyStudent(StudentModDTO student) { if (StudentExists(student.StudentID)) { // Figure out if the user is a Super Admin (important for override on active cohort) bool isSuperAdmin = User.Claims.Any(x => x.Type == System.Security.Claims.ClaimTypes.Role && x.Value == "SuperAdmin"); // Call BLL Student Modify method with all the parameters object BLLResponse = new StudentBLL(_context).ModifyStudentBLL(student: student, userIsSuperAdmin: isSuperAdmin); if (BLLResponse.GetType().BaseType == typeof(Exception)) { // Create log entries for Debug log ((APIException)BLLResponse).Exceptions.ForEach(ex => Logger.Msg <StudentsController>((Exception)ex, Serilog.Events.LogEventLevel.Debug)); // Return response from API return(BadRequest(new { errors = ((APIException)BLLResponse).Exceptions.Select(x => x.Message).ToArray() })); } else { try { StudentModDTO modifiedStudentData = (StudentModDTO)BLLResponse; // Determine the UserID corresponding to the UserID int studentUserID = _context.Students.Where(x => x.StudentID == modifiedStudentData.StudentID).First().UserID; // Modify UserID record accordingly User userRecord = _context.Users.Where(x => x.UserID == studentUserID).First(); userRecord.Firstname = modifiedStudentData.Firstname; userRecord.Lastname = modifiedStudentData.Lastname; userRecord.Email = modifiedStudentData.Email; userRecord.Active = modifiedStudentData.Active; // Save changes await _context.SaveChangesAsync(); // Modify Student record Student studentRecord = _context.Students.Where(x => x.StudentID == modifiedStudentData.StudentID).First(); studentRecord.CohortID = modifiedStudentData.CohortID; studentRecord.BearTracksID = modifiedStudentData.BearTracksID; // Save changes await _context.SaveChangesAsync(); Logger.Msg <StudentsController>($"[{User.FindFirstValue("email")}] [MODIFY] student '{modifiedStudentData.Email}' successful", Serilog.Events.LogEventLevel.Information); StudentDTO response = new StudentDTO(studentRecord); return(Ok(response)); } catch (Exception ex) { // Local log entry. Database reconciliation issues are more serious so reported as Error Logger.Msg <StudentsController>($"[MODIFY] Database sync error {ex.Message}", Serilog.Events.LogEventLevel.Error); // Return response to client return(StatusCode(500, new { errors = "Database update failed. Contact the administrator to resolve this issue." })); } } } else { return(NotFound()); } } // End of ModifyStudent