} // End of AddCohort

        /// <summary>
        /// Business logic for modifying Cohort records
        /// </summary>
        /// <param name="cohort"></param>
        /// <returns></returns>
        internal object ModifyCohortBLL(CohortDTO cohort)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            // Check if the id matches a CohortID already in the database.
            if (!CohortExists(cohort.CohortID))
            {
                exceptionList.AddExMessage($"Cohort does not exist with the ID {cohort.CohortID}");
            }
            else
            {
                // Check if the supplied changes meet requirements as for addition
                if (cohort.Name == null || cohort.Name.Trim() == string.Empty)
                {
                    exceptionList.AddExMessage("Name parameter cannot be empty.");
                }
                else
                {
                    // Check if a cohort with the same name exists in the database (trim + case insensitive)
                    // If it does, it has to have a different CohortID from the one supplied (i.e. ignore if they have the same ID)
                    bool dbContainsName = _context.Cohorts.Any(x => (x.Name.ToLower() == cohort.Name.Trim().ToLower()) && (x.CohortID != cohort.CohortID));

                    if (dbContainsName)
                    {
                        exceptionList.AddExMessage("A cohort with the same name already exists in the database.");
                    }

                    // Check that the startDate is less than endDate
                    bool datesConsistent = cohort.StartDate < cohort.EndDate;
                    if (!datesConsistent)
                    {
                        exceptionList.AddExMessage("Start date must be before the end date, check for consistency.");
                    }
                }
            }

            if (!exceptionList.HasExceptions)
            {
                // New database name will be trimmed and in Proper Case.
                string dbName = String.Join(" ", cohort.Name.Trim().Split(" ").Select(x => $"{x.Substring(0, 1).ToUpper()}{x.Substring(1)?.ToLower()}").ToArray());

                // Create a new Cohort object
                Cohort newDbObject = new Cohort {
                    CohortID = cohort.CohortID, Name = dbName, StartDate = cohort.StartDate, EndDate = cohort.EndDate
                };

                // Return the Cohort object (conversion from CohortDTO for internal ops)
                return(newDbObject);
            }
            else
            {
                return(exceptionList);
            }
        } // End of ModifyCohort
        } // End of GetNoticeBLL

        /// <summary>
        /// Business logic for processing Notice record addition
        /// </summary>
        /// <param name="notice"></param>
        /// <returns></returns>
        internal object AddNoticeBLL(NoticeDTO notice, ClaimsPrincipal userClaims)
        {
            // Get the StaffID of the currently logged in Staff member
            int loggedInStaffID = _context.Users.Where(x => x.Email == userClaims.FindFirst("Email").Value).Include(user => user.StaffData).Select(x => x.StaffData.StaffID).FirstOrDefault();

            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "cohortID must be valid", notice.CohortID != 0 && !_context.Cohorts.Any(x => x.CohortID == notice.CohortID) },
                { "staffID must be valid", notice.StaffID != 0 && !_context.Staff.Any(x => x.StaffID == notice.StaffID) },
                { "Notice text should not be null or empty", string.IsNullOrEmpty(notice.HTML.Trim()) || string.IsNullOrEmpty(notice.Markdown.Trim()) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                notice.StaffID = loggedInStaffID;

                return(notice);
            }
            else
            {
                return(exceptionList);
            }
        } // End of AddNoticeBLL
        /// <summary>
        /// Business logic for detailed Student records
        /// </summary>
        /// <param name="cohortID"></param>
        /// <returns></returns>
        internal object StudentDetailBLL(int cohortID)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "Specified CohortID does not exist", !(_context.Cohorts.Any(x => x.CohortID == cohortID) || cohortID == 0) },
                { "Specified cohort is inactive.", cohortID != 0 && !_context.Cohorts.Any(x => x.CohortID == cohortID && DateTime.Now >= x.StartDate && DateTime.Now <= x.EndDate) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                return(cohortID);
            }
            else
            {
                return(exceptionList);
            }
        } // End of StudentDetailBLL
        /// <summary>
        /// Business logic for processing TaskType record addition
        /// </summary>
        /// <param name="description"></param>
        /// <returns></returns>
        internal object AddTaskTypeBLL(string description)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "description parameter cannot be empty", description == null || description.Trim() == string.Empty },
                { "description must be unique", !string.IsNullOrEmpty(description) && _context.TaskTypes.Any(x => x.Description.ToLower() == description.Trim().ToLower()) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                // Capitalise the first letter of the first word of the description
                string dbDescription = $"{description.Trim().Substring(0, 1).ToUpper()}{description.Trim().Substring(1)?.ToLower()}";

                TaskTypeDTO newDbObject = new TaskTypeDTO {
                    Description = dbDescription
                };

                return(newDbObject);
            }
            else
            {
                return(exceptionList);
            }
        } // End of AddTaskTypeBLL
        } // End of AddTaskBLL

        /// <summary>
        /// Business logic for processing modifications to the Task record
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        internal object ModifyTaskBLL(TaskDTO task)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "title cannot be empty.", task.Title == null || task.Title.Trim() == string.Empty },
                { "Specified UnitID does not exist", !_context.Units.Any(x => x.UnitID == task.UnitID) },
                { "Specified CohortID does not exist", !_context.Cohorts.Any(x => x.CohortID == task.CohortID) },
                { "Specified TypeID does not exist", !_context.TaskTypes.Any(x => x.TypeID == task.TypeID) },
                { "Document URL must start with http:// or https://", !string.IsNullOrEmpty(task.DocURL) && !(task.DocURL.ToLower().StartsWith("http://") | task.DocURL.ToLower().StartsWith("https://")) },
                { "Document URL must be valid", !string.IsNullOrEmpty(task.DocURL) && !Uri.IsWellFormedUriString(task.DocURL, UriKind.Absolute) },
                { "Specified cohort is inactive.", !_context.Cohorts.Any(x => x.CohortID == task.CohortID && DateTime.Now >= x.StartDate && DateTime.Now <= x.EndDate) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                return(task);
            }
            else
            {
                return(exceptionList);
            }
        } // End of ModifyTaskBLL
        } // End of AddTaskTypeBLL

        /// <summary>
        /// Business logic for processing TaskType description change.
        /// </summary>
        /// <param name="taskType"></param>
        /// <returns></returns>
        internal object ModifyTaskTypeBLL(TaskTypeDTO taskType)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            // Due to the number of checks, this approach is more appropriate
            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "Specified TypeID does not exist", !_context.TaskTypes.Any(x => x.TypeID == taskType.TypeID) },
                { "description parameter cannot be empty", taskType.Description == null || taskType.Description.Trim() == string.Empty },
                { "description must be unique", !string.IsNullOrEmpty(taskType.Description) && _context.TaskTypes.Any(x => x.Description.ToLower() == taskType.Description.Trim().ToLower() && x.TypeID != taskType.TypeID) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                // Capitalise the first letter of the first word of the description
                string dbDescription = $"{taskType.Description.Trim().Substring(0, 1).ToUpper()}{taskType.Description.Trim().Substring(1)?.ToLower()}";
                taskType.Description = dbDescription;
                return(taskType);
            }
            else
            {
                return(exceptionList);
            }
        } // End of ModifyTaskTypeBLL
        } // End of ModifyTimesheetRecordBLL

        /// <summary>
        /// Business Logic for deleting an existing record
        /// </summary>
        /// <param name="recordID"></param>
        /// <param name="userClaims"></param>
        /// <returns></returns>
        internal object DeleteTimesheetRecordBLL(int recordID, ClaimsPrincipal userClaims)
        {
            // Check if the current user is a staff member (or Super Admin)
            bool isUserStaff = userClaims.IsInRole("Staff") || userClaims.IsInRole("SuperAdmin");

            // Get the StudentID of the currrent user (or 0)
            int currentStudentID = isUserStaff ? 0 : _context.Users.Where(x => x.Email == userClaims.FindFirstValue("email")).Include(users => users.StudentData).FirstOrDefault()?.StudentData.StudentID ?? 0;

            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "StudentID in the record cannot differ from the StudentID of the authenticated user", !(_context.Timesheets.Where(x => x.RecordID == recordID).First().StudentID == currentStudentID) || isUserStaff }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                return(recordID);
            }
            else
            {
                return(exceptionList);
            }
        } // End of TimesheetDeleteBLL
        /// <summary>
        /// Business logic for creating staff records in database
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="superUser"</param>
        /// <returns>BLL result object</returns>
        internal object AddStaffBLL(int userID, bool superUser)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "Specified userID does not exist", !_context.Users.Any(x => x.UserID == userID) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                StaffDTO newStaff = new StaffDTO
                {
                    UserID    = userID,
                    SuperUser = superUser
                };

                return(newStaff);
            }
            else
            {
                return(exceptionList);
            }
        } // End of AddStaffBLL
Exemple #9
0
        } // End of AddAttendanceBLL

        /// <summary>
        /// Business Logic for modifying Attendances table records
        /// </summary>
        /// <param name="attendance">AttendanceModDTO object with properties to modify</param>
        /// <param name="userClaims">ClaimsPrincipal object containing User Identity</param>
        /// <returns>object Exception or AttendanceModDTO</returns>
        internal object ModifyAttendanceBLL(AttendanceModDTO attendance, ClaimsPrincipal userClaims)
        {

            // Create a new APIException object to store possible exceptions as checks are performed. 
            APIException exceptionList = new APIException();

            // Due to the number of checks, this approach is more appropriate
            Dictionary<string, bool> exceptionTests = new Dictionary<string, bool>()
            {
                { "Specified RecordID does not exist", !_context.AttendanceRecords.Any(x => x.RecordID == attendance.RecordID) },
                { "Specified AttendanceStateID does not exist", !_context.AttendanceStates.Any(x => x.StateID == attendance.AttendanceStateID) }
            };

            foreach (KeyValuePair<string, bool> kvp in exceptionTests)
            {
                if (kvp.Value) exceptionList.AddExMessage(kvp.Key);
            }

            if (!exceptionList.HasExceptions)
            {
                return attendance;
            }
            else
            {
                return exceptionList;
            }
        } // End of ModifyAttendanceBLL
        } // End of AddStaffBLL

        /// <summary>
        /// Business logic for modifying Staff records
        /// </summary>
        /// <param name="staff"></param>
        /// <returns></returns>
        internal object ModifyUserBLL(StaffDTO staff)
        {
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "Specified UserID does not exist", !_context.Users.Any(x => x.UserID == staff.UserID) },
                { "Specified StaffID does not exist", !_context.Staff.Any(x => x.StaffID == staff.StaffID) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                return(staff);
            }
            else
            {
                return(exceptionList);
            }
        } // End of ModifyStaff
        /// <summary>
        /// Business logic for adding Cohort records
        /// </summary>
        /// <param name="name"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        internal object AddCohortBLL(string name, DateTime startDate, DateTime endDate)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            // Check if the name has been supplied or if it's empty after trimming
            if (name == null || name.Trim() == string.Empty)
            {
                exceptionList.AddExMessage("Name parameter cannot be empty.");
            }
            else
            {
                // Check if a cohort with the same name exists in the database (trim + case insensitive)
                bool dbContainsName = _context.Cohorts.Where(x => x.Name.ToLower() == name.Trim().ToLower()).Count() > 0;

                if (dbContainsName)
                {
                    exceptionList.AddExMessage("A cohort with the same name already exists in the database.");
                }

                // Check that the startDate is less than endDate
                bool datesConsistent = startDate < endDate;
                if (!datesConsistent)
                {
                    exceptionList.AddExMessage("Start date must be before the end date, check for consistency.");
                }
            }


            if (!exceptionList.HasExceptions)
            {
                // New database name will be trimmed and in Proper Case.
                string dbName = String.Join(" ", name.Trim().Split(" ").Select(x => $"{x.Substring(0, 1).ToUpper()}{x.Substring(1)?.ToLower()}").ToArray());

                Cohort newDbObject = new Cohort {
                    Name = dbName, StartDate = startDate, EndDate = endDate
                };

                return(newDbObject);
            }
            else
            {
                return(exceptionList);
            }
        } // End of AddCohort
        } // End of StudentDetailBLL

        /// <summary>
        /// Business logic for adding Student records
        /// </summary>
        /// <param name="firstname"></param>
        /// <param name="lastname"></param>
        /// <param name="email"></param>
        /// <param name="active"></param>
        /// <param name="cohortID"></param>
        /// <param name="bearTracksID"></param>
        /// <param name="userIsSuperAdmin"></param>
        /// <returns></returns>
        internal object AddStudentBLL(string firstname, string lastname, string email, bool active, int cohortID, string bearTracksID, 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

            // Due to the number of checks, this approach is more appropriate
            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "firstname parameter cannot be empty.", firstname == null || firstname.Trim() == string.Empty },
                { "lastname parameter cannot be empty", lastname == null || lastname.Trim() == string.Empty },
                { "Email needs to be a valid email address", email == null || !Regex.IsMatch(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 already exists)", email != null && _context.Users.Any(x => x.Email == email) && _context.Students.Any(x => x.UserID == _context.Users.Where(y => y.Email == email).First().UserID) },
                { "Email address domain not found in the list of valid domains", email != null && !APIConfig.Configuration.GetSection("ValidEmailDomains").GetChildren().ToArray().Select(x => x.Value).ToArray().Contains(email.Split("@")?[1] ?? "") },
                { "Specified CohortID does not exist", !_context.Cohorts.Any(x => x.CohortID == cohortID) },
                { "Specified cohort is inactive.", !(_context.Cohorts.Any(x => x.CohortID == 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(" ", firstname.Trim().Split(" ").Select(x => $"{x.Substring(0, 1).ToUpper()}{x.Substring(1)?.ToLower()}").ToArray());
                string dbLastname  = String.Join(" ", 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
                Dictionary <string, object> newDbObject = new Dictionary <string, object>()
                {
                    { "Firstname", dbFirstname },
                    { "Lastname", dbLastname },
                    { "Email", email },
                    { "Active", active },
                    { "CohortID", cohortID },
                    { "BearTracksID", bearTracksID },
                    { "UserAlreadyInUsersTable", _context.Users.Any(x => x.Email == email) }
                };

                return(newDbObject);
            }
            else
            {
                return(exceptionList);
            }
        } // End of AddStudent
        } // End of GetTimesheetRecordBLL

        /// <summary>
        /// Business logic for processing Timesheet record addition
        /// </summary>
        /// <param name="timesheetRecord"></param>
        /// <param name="userClaims"></param>
        /// <returns></returns>
        internal object AddTimesheetRecordBLL(TimesheetDTO timesheetRecord, ClaimsPrincipal userClaims)
        {
            // Check if the current user is a staff member (or Super Admin)
            bool isUserStaff = userClaims.IsInRole("Staff") || userClaims.IsInRole("SuperAdmin");

            // Get the StudentID of the currrent user (or 0)
            int currentStudentID = isUserStaff ? 0 : _context.Users.Where(x => x.Email == userClaims.FindFirstValue("email")).Include(users => users.StudentData).FirstOrDefault()?.StudentData.StudentID ?? 0;

            if (timesheetRecord.StudentID == 0 && !isUserStaff)
            {
                timesheetRecord.StudentID = currentStudentID;
            }

            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "Specified StudentID does not exist", !_context.Students.Any(x => x.StudentID == timesheetRecord.StudentID) },
                { "StudentID cannot differ from the authenticated user", !(timesheetRecord.StudentID == currentStudentID || isUserStaff) },
                { "Student account matching the StudentID must be active", !(_context.Students.Where(x => x.StudentID == timesheetRecord.StudentID).Include(student => student.UserData).FirstOrDefault().UserData.Active || isUserStaff) },
                { "Specified AssignmentID does not exist", !_context.Tasks.Any(x => x.TaskID == timesheetRecord.AssignmentID) },
                { "Specified date is older than 7 days", ((DateTime.Today - timesheetRecord.Date).Days > 7) && !isUserStaff },
                { "Specified date cannot be in the future", !(timesheetRecord.Date <= DateTime.Today) },
                { "TimeAllocation has to be a positive number, or zero", !(timesheetRecord.TimeAllocation >= 0) },
                { "TimeAllocation has to be less than or equal to 18h", !(timesheetRecord.TimeAllocation <= 18) }
                // { "Only one record per AssignmentID per date is allowed", _context.Timesheets.Any(x => x.Date == timesheetRecord.Date && x.AssignmentID == timesheetRecord.AssignmentID && x.StudentID == timesheetRecord.StudentID) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                // Round the TimeAlllocation to 15 min (0.25h)
                // Ref: https://stackoverflow.com/a/2826278/12802214
                timesheetRecord.TimeAllocation = Math.Round(timesheetRecord.TimeAllocation * 4, MidpointRounding.AwayFromZero) / 4;

                return(timesheetRecord);
            }
            else
            {
                return(exceptionList);
            }
        } // End of AddTimesheetRecordBLL
Exemple #14
0
        } // End of ModifyAttendanceBLL

        /// <summary>
        /// Business Logic for processing Get requests for records in the attendance table
        /// </summary>
        /// <param name="studentID"></param>
        /// <param name="attendanceStateID"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="userClaims"></param>
        /// <returns></returns>
        internal object GetAttendanceBLL(int studentID, int attendanceStateID, DateTime startDate, DateTime endDate, ClaimsPrincipal userClaims)
        {
            // Check if the current user is a staff member (or Super Admin)
            bool isUserStaff = userClaims.IsInRole("Staff") || userClaims.IsInRole("SuperAdmin");

            // Get the StudentID of the currrent user (or null)
            int currentStudentID = isUserStaff? 0 : _context.Users.Where(x => x.Email == userClaims.FindFirstValue("email")).Include(users => users.StudentData).FirstOrDefault()?.StudentData.StudentID ?? 0;

            // Apply defaults
            if (startDate == DateTime.MinValue) startDate = DateTime.Today.AddDays(-7);
            if (endDate == DateTime.MinValue) endDate = DateTime.Today;
            if (studentID == 0) studentID = currentStudentID;

            // Create a new APIException object to store possible exceptions as checks are performed. 
            APIException exceptionList = new APIException();

            // Due to the number of checks, this approach is more appropriate
            Dictionary<string, bool> exceptionTests = new Dictionary<string, bool>()
            {
                { "StudentID has to match the current user StudentID", !(studentID == currentStudentID || isUserStaff) },
                { "Start date cannot be after the end date", !(startDate <= endDate) },
                { "Invalid attendanceStateID specified", !(_context.AttendanceStates.Any(x => x.StateID == attendanceStateID) || attendanceStateID == 0) }
            };

            foreach (KeyValuePair<string, bool> kvp in exceptionTests)
            {
                if (kvp.Value) exceptionList.AddExMessage(kvp.Key);
            }

            if (!exceptionList.HasExceptions)
            {

                // Create a dictionary containing all data needed to create the user and pass back to API Target
                Dictionary<string, object> getParams = new Dictionary<string, object>()
                {
                    { "StudentID", studentID },
                    { "AttendanceStateID", attendanceStateID},
                    { "StartDate", startDate},
                    { "EndDate", endDate}
                };

                return getParams;
            }
            else
            {
                return exceptionList;
            }

        }// End of GetAttendanceBLL
Exemple #15
0
        /// <summary>
        /// Business logic for creating users in database
        /// </summary>
        /// <param name="firstname"></param>
        /// <param name="lastname"></param>
        /// <param name="email"></param>
        /// <param name="active"></param>
        /// <returns></returns>
        internal object AddUserBLL(string firstname, string lastname, string email, bool active)
        {
            // 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

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "firstname parameter cannot be empty.", firstname == null || firstname.Trim() == string.Empty },
                { "lastname parameter cannot be empty", lastname == null || lastname.Trim() == string.Empty },
                { "Email needs to be a valid email address", email == null || !Regex.IsMatch(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 (user record already exists)", email != null && _context.Users.Any(x => x.Email == email) && _context.Students.Any(x => x.UserID == _context.Users.Where(y => y.Email == email).First().UserID) },
                { "Email address domain not found in the list of valid domains", email != null && !APIConfig.Configuration.GetSection("ValidEmailDomains").GetChildren().ToArray().Select(x => x.Value).ToArray().Contains(email.Split("@")?[1] ?? "") }
            };

            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(" ", firstname.Trim().Split(" ").Select(x => $"{x.Substring(0, 1).ToUpper()}{x.Substring(1)?.ToLower()}").ToArray());
                string dbLastname  = String.Join(" ", lastname.Trim().Split(" ").Select(x => $"{x.Substring(0, 1).ToUpper()}{x.Substring(1)?.ToLower()}").ToArray());

                UserDTO newUser = new UserDTO
                {
                    Firstname = dbFirstname,
                    Lastname  = dbLastname,
                    Email     = email,
                    Active    = active
                };


                return(newUser);
            }
            else
            {
                return(exceptionList);
            }
        } // End of AddUserBLL
        /// <summary>
        /// Business logic for retrieving Notice records
        /// </summary>
        /// <param name="noticeID"></param>
        /// <param name="cohortID"></param>
        /// <param name="staffID"></param>
        /// <param name="validFrom"></param>
        /// <param name="isUserStaff"></param>
        /// <returns></returns>
        internal object GetNoticeBLL(int noticeID, int cohortID, int staffID, DateTime validFrom, bool isUserStaff)
        {
            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "noticeID must be valid", noticeID != 0 && !_context.Notices.Any(x => x.NoticeID == noticeID) },
                { "cohortID must be valid", cohortID != 0 && !_context.Cohorts.Any(x => x.CohortID == cohortID) },
                { "staffID must be valid", staffID != 0 && !_context.Staff.Any(x => x.StaffID == staffID) },
                { "validFrom date cannot be in the future", !(validFrom <= DateTime.Today) && !isUserStaff }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                // Apply defaults
                if (validFrom == DateTime.MinValue)
                {
                    validFrom = _context.Cohorts.Where(x => x.CohortID == cohortID).First().StartDate;
                }


                NoticeDTO getParams = new NoticeDTO
                {
                    NoticeID  = noticeID,
                    CohortID  = cohortID,
                    StaffID   = staffID,
                    ValidFrom = validFrom
                };

                return(getParams);
            }
            else
            {
                return(exceptionList);
            }
        } // End of GetNoticeBLL
        } // 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 #18
0
        /// <summary>
        /// Business logic for adding an attendance record to the database
        /// </summary>
        /// <param name="attendance"></param>
        /// <param name="userClaims"></param>
        /// <returns>object Exception() or object attendanceDTO</returns>
        internal object AddAttendanceBLL(AttendanceDTO attendance, ClaimsPrincipal userClaims)
        {
            // Get the StaffID of the currently logged in Staff member
            int loggedInStaffID = _context.Users.Where(x => x.Email == userClaims.FindFirst("Email").Value).Include(user => user.StaffData).Select(x => x.StaffData.StaffID).First();
            int studentUserID = _context.Students.Where(x => x.StudentID == attendance.StudentID).Select(x => x.UserID).First();

            // Is the user Super Admin?
            bool userIsSuperAdmin = userClaims.IsInRole("SuperAdmin");

            // Create a new APIException object to store possible exceptions as checks are performed. 
            APIException exceptionList = new APIException();

            // Due to the number of checks, this approach is more appropriate
            Dictionary<string, bool> exceptionTests = new Dictionary<string, bool>()
            {
                { "Specified StudentID does not exist", !_context.Students.Any(x => x.StudentID == attendance.StudentID) },
                { "Specified AttendanceStateID does not exist", !_context.AttendanceStates.Any(x => x.StateID == attendance.AttendanceStateID) },
                { "Specified StaffID does not exist", !_context.Staff.Any(x => x.StaffID == attendance.StaffID) },
                { "Specified StaffID does not match current user credentials", !(_context.Staff.Any(x => x.StaffID == attendance.StaffID) && loggedInStaffID == attendance.StaffID) },
                { "Duplicate record exists in the database (StudentID, Date)", _context.AttendanceRecords.Any(x => x.StudentID == attendance.StudentID && x.Date == attendance.Date) },
                { "Specified attendance record cannot be added as the specified date is more than 3 days old", !(((DateTime.Today - attendance.Date.Date).Days <= 3) || userIsSuperAdmin) },
                { "Specified student is inactive.", !(_context.Students.Where(x => x.StudentID == attendance.StudentID).Include(student => student.UserData).Select(x => x.UserData.Active).First() || userIsSuperAdmin) }
            };

            foreach (KeyValuePair<string, bool> kvp in exceptionTests)
            {
                if (kvp.Value) exceptionList.AddExMessage(kvp.Key);
            }

            if (!exceptionList.HasExceptions)
            {
                return attendance;
            }
            else
            {
                return exceptionList;
            }

        } // End of AddAttendanceBLL
        /// <summary>
        /// Business logic for retrieving Timesheet records
        /// </summary>
        /// <param name="recordID"></param>
        /// <param name="studentID"></param>
        /// <param name="assignmentID"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="userClaims"></param>
        /// <returns></returns>
        internal object GetTimesheetRecordBLL(int recordID, int studentID, int unitID, int typeID, int assignmentID, int cohortID, DateTime startDate, DateTime endDate, ClaimsPrincipal userClaims)
        {
            // Check if the current user is a staff member (or Super Admin)
            bool isUserStaff = userClaims.IsInRole("Staff") || userClaims.IsInRole("SuperAdmin");

            // Get the StudentID of the currrent user (or null)
            int currentStudentID = isUserStaff ? 0 : _context.Users.Where(x => x.Email == userClaims.FindFirstValue("email")).Include(users => users.StudentData).FirstOrDefault()?.StudentData.StudentID ?? 0;

            // Apply defaults
            if (startDate == DateTime.MinValue)
            {
                startDate = DateTime.Today;
            }
            if (endDate == DateTime.MinValue)
            {
                endDate = DateTime.Today;
            }
            if (!isUserStaff)
            {
                studentID = currentStudentID;
            }

            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "recordID must be valid", recordID != 0 && !_context.Timesheets.Any(x => x.RecordID == recordID) },
                { "cohortID must be valid", cohortID != 0 && !_context.Cohorts.Any(x => x.CohortID == cohortID) },
                { "unitID must be valid", unitID != 0 && !_context.Units.Any(x => x.UnitID == unitID) },
                { "typeID must be valid", typeID != 0 && !_context.TaskTypes.Any(x => x.TypeID == typeID) },
                { "assignmentID must be valid", assignmentID != 0 && !_context.Tasks.Any(x => x.TaskID == assignmentID) },
                { "studentID must be valid", studentID != 0 && !_context.Students.Any(x => x.StudentID == studentID) },
                { "startDate cannot be after the endDate", !(startDate <= endDate) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                TimesheetGetDTO getParams = new TimesheetGetDTO
                {
                    RecordID     = recordID,
                    StudentID    = studentID,
                    CohortID     = cohortID,
                    AssignmentID = assignmentID,
                    TypeID       = typeID,
                    UnitID       = unitID,
                    StartDate    = startDate,
                    EndDate      = endDate
                };

                return(getParams);
            }
            else
            {
                return(exceptionList);
            }
        } // End of GetTimesheetRecordBLL
        } // End of ModifyTaskBLL

        /// <summary>
        /// Business logic for retrieving Task records
        /// </summary>
        /// <param name="taskID"></param>
        /// <param name="cohortID"></param>
        /// <param name="typeID"></param>
        /// <param name="unitID"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="userClaims"></param>
        /// <returns></returns>
        internal object GetTaskBLL(int taskID, int cohortID, int typeID, int unitID, DateTime startDate, DateTime endDate, ClaimsPrincipal userClaims)
        {
            // Check if the current user is a staff member (or Super Admin)
            bool isUserStaff = userClaims.IsInRole("Staff") || userClaims.IsInRole("SuperAdmin");

            // Get the CohortID of the currrent user (or null)
            int currentCohortID = isUserStaff ? 0 : _context.Users.Where(x => x.Email == userClaims.FindFirstValue("email")).Include(users => users.StudentData).FirstOrDefault()?.StudentData.CohortID ?? 0;

            // Apply defaults
            if (startDate == DateTime.MinValue)
            {
                startDate = DateTime.Today.AddDays(-14);
            }
            if (endDate == DateTime.MinValue)
            {
                endDate = DateTime.Today.AddDays(7);
            }

            // Do not allow students to see future assignments
            if (startDate > DateTime.Today && !isUserStaff)
            {
                startDate = DateTime.Today;
            }
            if (cohortID == 0)
            {
                cohortID = currentCohortID;
            }

            // Create a new APIException object to store possible exceptions as checks are performed.
            APIException exceptionList = new APIException();

            // Due to the number of checks, this approach is more appropriate
            Dictionary <string, bool> exceptionTests = new Dictionary <string, bool>()
            {
                { "cohortID has to match the current user's CohortID", !(cohortID == currentCohortID || isUserStaff) },
                { "taskID must be valid.", taskID != 0 && !_context.Tasks.Any(x => x.TaskID == taskID) },
                { "cohortID must be valid.", cohortID != 0 && !_context.Cohorts.Any(x => x.CohortID == cohortID) },
                { "typeID must be valid.", typeID != 0 && !_context.TaskTypes.Any(x => x.TypeID == typeID) },
                { "unitID must be valid.", unitID != 0 && !_context.Units.Any(x => x.UnitID == unitID) },
                { "Start date cannot be after the end date", !(startDate <= endDate) }
            };

            foreach (KeyValuePair <string, bool> kvp in exceptionTests)
            {
                if (kvp.Value)
                {
                    exceptionList.AddExMessage(kvp.Key);
                }
            }

            if (!exceptionList.HasExceptions)
            {
                TaskDTO getParams = new TaskDTO
                {
                    TaskID    = taskID,
                    CohortID  = cohortID,
                    TypeID    = typeID,
                    UnitID    = unitID,
                    StartDate = startDate,
                    EndDate   = endDate
                };

                return(getParams);
            }
            else
            {
                return(exceptionList);
            }
        }// End of GetTaskBLL