} // 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
Exemple #2
0
        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