/// <summary> /// Creates a new code question updater. /// </summary> private static CodeQuestionUpdater <CodeQuestion> GetCodeQuestionUpdater( TestDatabase database, CodeQuestion question, IModelErrorCollection errors) { return(new Mock <CodeQuestionUpdater <CodeQuestion> >(database.Context, question, errors).Object); }
/// <summary> /// Returns a new section validator. /// </summary> private static ISectionValidator CreateMockSectionValidator( Section sectionToValidate, IModelErrorCollection modelErrors, bool valid) { var sectionValidator = new Mock <ISectionValidator>(); sectionValidator .Setup ( m => m.ValidateSectionAsync ( sectionToValidate, modelErrors ) ) .Callback ( (Section section, IModelErrorCollection errors) => { if (!valid) { errors.AddError("Error", "Error Description"); } } ).ReturnsAsync(valid); return(sectionValidator.Object); }
/// <summary> /// Updates a checkpoint. /// </summary> public async Task <bool> UpdateCheckpointAsync( string classroomName, string projectName, Checkpoint checkpoint, IModelErrorCollection modelErrors) { var project = await LoadProjectAsync(classroomName, projectName); checkpoint.ProjectId = project.Id; var currentCheckpoint = await _dbContext.Checkpoints .Where(c => c.Id == checkpoint.Id) .SingleOrDefaultAsync(); _dbContext.Entry(currentCheckpoint).State = EntityState.Detached; if (!UpdateCheckpoint(checkpoint, modelErrors)) { return(false); } _dbContext.Update(checkpoint); await _dbContext.SaveChangesAsync(); return(true); }
/// <summary> /// Validates that the question may be updated, and executes /// the corresponding question updater. /// </summary> private async Task <bool> ValidateAndUpdateQuestionAsync( string classroomName, Question question, IModelErrorCollection errors) { var isValid = await _questionValidator.ValidateQuestionAsync ( question, errors, classroomName ); if (!isValid) { return(false); } await _questionUpdaterFactory .CreateQuestionUpdater(question, errors) .UpdateQuestionAsync(); if (errors.HasErrors) { return(false); } return(true); }
/// <summary> /// Updates a assignment. /// </summary> private async Task <bool> UpdateAssignmentAsync(Assignment assignment, IModelErrorCollection modelErrors) { UpdateQuestionOrder(assignment.Questions); await UpdateQuestionNames(assignment.Questions); if (!await _assignmentValidator.ValidateAssignmentAsync(assignment, modelErrors)) { return(false); } if (string.IsNullOrWhiteSpace(assignment.GroupName)) { assignment.GroupName = assignment.Name; } _dbContext.RemoveUnwantedObjects ( _dbContext.AssignmentQuestions, question => question.Id, question => question.AssignmentId == assignment.Id, assignment.Questions ); _dbContext.RemoveUnwantedObjects ( _dbContext.AssignmentDueDates, dueDate => dueDate.Id, dueDate => dueDate.AssignmentId == assignment.Id, assignment.DueDates ); return(true); }
/// <summary> /// Returns a new assignment validator. /// </summary> private static IAssignmentValidator CreateMockAssignmentValidator( Assignment assignmentToValidate, IModelErrorCollection modelErrors, bool validAssignment) { var assignmentValidator = new Mock <IAssignmentValidator>(); assignmentValidator .Setup ( m => m.ValidateAssignmentAsync ( assignmentToValidate, modelErrors ) ) .Callback ( (Assignment assignment, IModelErrorCollection errors) => { if (!validAssignment) { errors.AddError("Error", "Error Description"); } } ).ReturnsAsync(validAssignment); return(assignmentValidator.Object); }
/// <summary> /// Updates a section. /// </summary> public async Task <bool> UpdateSectionAsync( string classroomName, Section section, IModelErrorCollection errors) { var classroom = await LoadClassroomAsync(classroomName); section.ClassroomId = classroom.Id; var currentSection = await _dbContext.Sections .Where(s => s.Id == section.Id) .SingleOrDefaultAsync(); _dbContext.Entry(currentSection).State = EntityState.Detached; if (!await _sectionValidator.ValidateSectionAsync(section, errors)) { return(false); } UpdateSection(section); _dbContext.Update(section); await _dbContext.SaveChangesAsync(); return(true); }
/// <summary> /// Ensures that a question to add or update is in a valid state. /// </summary> public async Task <bool> ValidateQuestionAsync( Question question, IModelErrorCollection errors, string classroomName) { var existingQuestion = await _dbContext.Questions .Where(q => q.QuestionCategory.Classroom.Name == classroomName) .Where(q => q.Id == question.Id) .Include(q => q.QuestionCategory) .SingleOrDefaultAsync(); if (existingQuestion != null) { _dbContext.Entry(existingQuestion).State = EntityState.Detached; } var newQuestionCategory = await _dbContext.QuestionCategories .Include(qc => qc.Classroom) .SingleOrDefaultAsync ( category => category.Id == question.QuestionCategoryId ); if (newQuestionCategory.Classroom.Name != classroomName) { throw new InvalidOperationException( "Category of question is not in the given classroom."); } if (existingQuestion?.QuestionCategory?.RandomlySelectedQuestionId != null && question.QuestionCategoryId != existingQuestion?.QuestionCategoryId) { throw new InvalidOperationException ( "The category cannot be changed for a randomly selected question choice." ); } if (existingQuestion != null && existingQuestion?.QuestionCategory?.RandomlySelectedQuestionId == null && newQuestionCategory.RandomlySelectedQuestionId != null) { throw new InvalidOperationException ( "The category cannot be changed from a non-random-choice category " + "to a random choice category." ); } if (await _dbContext.Questions.AnyAsync( q => q.Id != question.Id && q.Name == question.Name && q.QuestionCategoryId == question.QuestionCategoryId)) { errors.AddError("Name", "Another question with that name already exists."); } return(!errors.HasErrors); }
/// <summary> /// Publish a new announcement. /// </summary> public async Task <bool> EditAnnouncementAsync( string classroomName, Announcement announcement, Func <DateTime, string> formatDateTime, IModelErrorCollection modelErrors) { var existingAnnouncement = await _dbContext.Announcements .AsNoTracking() .Where(a => a.Classroom.Name == classroomName) .Include(a => a.Sections) .Include(a => a.Classroom.Sections) .SingleOrDefaultAsync(a => a.Id == announcement.Id); var classroom = existingAnnouncement.Classroom; if (!_validator.ValidateAnnouncement(classroom, announcement, modelErrors)) { return(false); } announcement.ClassroomId = existingAnnouncement.ClassroomId; announcement.UserId = existingAnnouncement.UserId; announcement.DatePosted = existingAnnouncement.DatePosted; announcement.Contents = _htmlSanitizer.SanitizeHtml(announcement.Contents); _dbContext.RemoveUnwantedObjects ( _dbContext.AnnouncementSections, announcementSection => announcementSection.Id, announcementSection => announcementSection.AnnouncementId == announcement.Id, announcement.Sections ); var newSectionIds = announcement.Sections .Select(s => s.SectionId) .Where ( sectionId => !existingAnnouncement.Sections.Any ( s => s.SectionId == sectionId ) ).ToList(); _dbContext.Entry(existingAnnouncement).State = EntityState.Detached; _dbContext.Announcements.Update(announcement); await _dbContext.SaveChangesAsync(); await SendAnnouncementEmailAsync ( announcement, classroom, newSectionIds, formatDateTime, emailAdmins : false ); return(true); }
/// <summary> /// Registers a user. /// </summary> public async Task <RegisterNewUserResult> RegisterNewStudentAsync( string classroomName, string sectionName, StudentRegistration registration, string confirmationUrlBuilder, IModelErrorCollection errors) { var section = _dbContext.Sections .Where(s => s.Classroom.Name == classroomName) .Include(s => s.Classroom) .SingleOrDefault(s => s.Name == sectionName); if (section == null) { return(RegisterNewUserResult.SectionNotFound); } if (!section.AllowNewRegistrations) { return(RegisterNewUserResult.SectionNotOpen); } var user = await GetAndUpdateCurrentUserAsync(); if (user != null) { return(RegisterNewUserResult.AlreadyRegistered); } if (!await _gitHubUserClient.DoesUserExistAsync(registration.GitHubLogin)) { errors.AddError("GitHubLogin", "The GitHub username does not exist."); return(RegisterNewUserResult.Failed); } user = new User() { UniqueId = _identityProvider.CurrentIdentity.UniqueId, UserName = _identityProvider.CurrentIdentity.UserName, FirstName = registration.FirstName, LastName = _identityProvider.CurrentIdentity.LastName, EmailAddress = registration.EmailAddress, EmailConfirmationCode = GenerateEmailConfirmationCode(), EmailAddressConfirmed = false, GitHubLogin = registration.GitHubLogin, SuperUser = false }; var membership = await EnsureSectionMembershipAsync(user, section, SectionRole.Student); await EnsureUserInGithubOrgAsync(user, membership.ClassroomMembership); await SendUserInvitationMailAsync(user, confirmationUrlBuilder); _dbContext.Users.Add(user); await _dbContext.SaveChangesAsync(); return(RegisterNewUserResult.Success); }
/// <summary> /// Returns whether or not a section is valid. /// </summary> public async Task <bool> ValidateSectionAsync( Section section, IModelErrorCollection errors) { EnsureNoDuplicateSectionGradebooks(section, errors); EnsureNoDuplicateSectionRecipients(section, errors); await EnsureSectionRecipientsAreClassAdmins(section, errors); return(!errors.HasErrors); }
/// <summary> /// Constructor. /// </summary> public GeneratedQuestionUpdater( DatabaseContext dbContext, GeneratedQuestionTemplate question, IModelErrorCollection errors, IQuestionGenerator questionGenerator, ITimeProvider timeProvider) : base(dbContext, question, errors) { _questionGenerator = questionGenerator; _timeProvider = timeProvider; }
/// <summary> /// Updates a question. /// </summary> public async Task <bool> UpdateQuestionAsync( string classroomName, Question question, IModelErrorCollection errors) { if (!await ValidateAndUpdateQuestionAsync(classroomName, question, errors)) { return(false); } _dbContext.Update(question); await _dbContext.SaveChangesAsync(); return(true); }
/// <summary> /// Validates that an announcement is correctly configured. /// </summary> public bool ValidateAnnouncement( Classroom classroom, Announcement announcement, IModelErrorCollection modelErrors) { var sectionIds = announcement.Sections ?.Select(s => s.SectionId) ?.ToList() ?? new List <int>(); if (!sectionIds.Any()) { modelErrors.AddError ( "Sections", "At least one section must be included." ); return(false); } if (sectionIds.Distinct().Count() != sectionIds.Count) { modelErrors.AddError ( "Sections", "Duplicate sections are not permitted." ); return(false); } if (sectionIds .Intersect(classroom.Sections.Select(s => s.Id)) .Count() != sectionIds.Count) { modelErrors.AddError ( "Sections", "Invalid sections selected." ); return(false); } return(true); }
/// <summary> /// Creates a checkpoint. /// </summary> public async Task<bool> CreateCheckpointAsync( string classroomName, string projectName, Checkpoint checkpoint, IModelErrorCollection modelErrors) { var project = await LoadProjectAsync(classroomName, projectName); if (!UpdateCheckpoint(checkpoint, modelErrors)) return false; checkpoint.ProjectId = project.Id; _dbContext.Add(checkpoint); await _dbContext.SaveChangesAsync(); return true; }
/// <summary> /// Updates an assignment. /// </summary> public async Task <bool> UpdateAssignmentAsync( string classroomName, Assignment assignment, IModelErrorCollection modelErrors) { var classroom = await LoadClassroomAsync(classroomName); if (!await UpdateAssignmentAsync(assignment, modelErrors)) { return(false); } assignment.ClassroomId = classroom.Id; _dbContext.Update(assignment); await _dbContext.SaveChangesAsync(); return(true); }
/// <summary> /// Updates a checkpoint. /// </summary> private bool UpdateCheckpoint(Checkpoint checkpoint, IModelErrorCollection modelErrors) { if (checkpoint.SectionDates != null) { var sections = checkpoint.SectionDates.Select(d => d.SectionId).ToList(); if (sections.Distinct().Count() != sections.Count) { modelErrors.AddError("SectionDates", "You may only have one due date per section."); } } if (checkpoint.TestClasses != null) { var testClasses = checkpoint.TestClasses.Select(tc => tc.TestClassId).ToList(); if (testClasses.Distinct().Count() != testClasses.Count) { modelErrors.AddError("TestClasses", "You may only have one entry per test class."); } } if (modelErrors.HasErrors) { return(false); } _dbContext.RemoveUnwantedObjects ( _dbContext.CheckpointDates, checkpointDates => checkpointDates.Id, checkpointDates => checkpointDates.CheckpointId == checkpoint.Id, checkpoint.SectionDates ); _dbContext.RemoveUnwantedObjects ( _dbContext.CheckpointTestClasses, testClass => testClass.Id, testClass => testClass.CheckpointId == checkpoint.Id, checkpoint.TestClasses ); return(true); }
/// <summary> /// Creates a checkpoint. /// </summary> public async Task <bool> CreateCheckpointAsync( string classroomName, string projectName, Checkpoint checkpoint, IModelErrorCollection modelErrors) { var project = await LoadProjectAsync(classroomName, projectName); if (!UpdateCheckpoint(checkpoint, modelErrors)) { return(false); } checkpoint.ProjectId = project.Id; _dbContext.Add(checkpoint); await _dbContext.SaveChangesAsync(); return(true); }
/// <summary> /// Ensures that there are no duplicate section recipients. /// </summary> private void EnsureNoDuplicateSectionRecipients( Section section, IModelErrorCollection errors) { if (section.SectionRecipients != null) { var cmIds = section.SectionRecipients .Select(d => d.ClassroomMembershipId) .ToList(); if (cmIds.Distinct().Count() != cmIds.Count) { errors.AddError ( "SectionRecipients", "Duplicate section recipients are not permitted." ); } } }
/// <summary> /// Ensures that there are no duplicate section gradebooks. /// </summary> private void EnsureNoDuplicateSectionGradebooks( Section section, IModelErrorCollection errors) { if (section.SectionGradebooks != null) { var classroomGradebookIds = section.SectionGradebooks .Select(d => d.ClassroomGradebookId) .ToList(); if (classroomGradebookIds.Distinct().Count() != classroomGradebookIds.Count) { errors.AddError ( "SectionGradebooks", "You may only have one section gradebook per classroom gradebook." ); } } }
/// <summary> /// Creates a section. /// </summary> public async Task <bool> CreateSectionAsync( string classroomName, Section section, IModelErrorCollection errors) { var classroom = await LoadClassroomAsync(classroomName); section.ClassroomId = classroom.Id; if (!await _sectionValidator.ValidateSectionAsync(section, errors)) { return(false); } _dbContext.Add(section); await _dbContext.SaveChangesAsync(); return(true); }
/// <summary> /// Publish a new announcement. /// </summary> public async Task <bool> PostAnnouncementAsync( string classroomName, int userId, Announcement announcement, Func <DateTime, string> formatDateTime, IModelErrorCollection modelErrors) { var classroom = await _dbContext.Classrooms .Where(c => c.Name == classroomName) .Include(c => c.Sections) .SingleAsync(); var sectionIds = announcement.Sections ?.Select(s => s.SectionId) ?.ToList() ?? new List <int>(); if (!_validator.ValidateAnnouncement(classroom, announcement, modelErrors)) { return(false); } announcement.ClassroomId = classroom.Id; announcement.UserId = userId; announcement.Contents = _htmlSanitizer.SanitizeHtml(announcement.Contents); announcement.DatePosted = _timeProvider.UtcNow; _dbContext.Announcements.Add(announcement); await _dbContext.SaveChangesAsync(); await SendAnnouncementEmailAsync ( announcement, classroom, sectionIds, formatDateTime, emailAdmins : true ); return(true); }
/// <summary> /// Ensures that section recipients are class admins. /// </summary> private async Task EnsureSectionRecipientsAreClassAdmins( Section section, IModelErrorCollection errors) { var classroomMemberships = await _dbContext.ClassroomMemberships .Where(cm => cm.ClassroomId == section.ClassroomId) .Where(cm => cm.Role >= ClassroomRole.Admin) .ToListAsync(); var cmIds = classroomMemberships.Select(cm => cm.Id).ToHashSet(); if (section.SectionRecipients != null && section.SectionRecipients.Any(sr => !cmIds.Contains(sr.ClassroomMembershipId))) { errors.AddError ( "SectionRecipients", "All section recipients must be class admins." ); } }
/// <summary> /// Called to register the first super-user. /// </summary> public async Task <RegisterNewUserResult> RegisterFirstSuperUserAsync( SuperUserRegistration registration, IModelErrorCollection errors) { if (await AnyRegisteredUsersAsync()) { return(RegisterNewUserResult.AlreadyRegistered); } if (registration.ActivationToken != _activationToken.Value) { errors.AddError("ActivationToken", "Incorrect activation token."); return(RegisterNewUserResult.Failed); } if (!await _gitHubUserClient.DoesUserExistAsync(registration.GitHubLogin)) { errors.AddError("GitHubLogin", "The GitHub username does not exist."); return(RegisterNewUserResult.Failed); } User user = new User() { UniqueId = _identityProvider.CurrentIdentity.UniqueId, UserName = _identityProvider.CurrentIdentity.UserName, FirstName = registration.FirstName, LastName = registration.LastName, EmailAddress = registration.EmailAddress, EmailAddressConfirmed = true, GitHubLogin = registration.GitHubLogin, SuperUser = true }; _dbContext.Users.Add(user); await _dbContext.SaveChangesAsync(); return(RegisterNewUserResult.Success); }
/// <summary> /// Returns a mock question updater factory. /// </summary> private Mock <IQuestionUpdaterFactory> GetMockQuestionUpdaterFactory( bool isValid) { var updater = new Mock <IQuestionUpdater>(); IModelErrorCollection errors = null; var updaterFactory = new Mock <IQuestionUpdaterFactory>(); updaterFactory .Setup ( m => m.CreateQuestionUpdater ( It.IsNotNull <Question>(), It.IsNotNull <IModelErrorCollection>() ) ).Callback <Question, IModelErrorCollection> ( (_unused, modelErrors) => errors = modelErrors ).Returns(updater.Object); updater .Setup(m => m.UpdateQuestionAsync()) .Callback ( () => { if (!isValid) { errors.AddError("Error", "ErrorDescription"); } } ).Returns(Task.CompletedTask); return(updaterFactory); }
/// <summary> /// Constructor. /// </summary> public MethodQuestionUpdater(DatabaseContext dbContext, MethodQuestion question, IModelErrorCollection errors) : base(dbContext, question, errors) { }
/// <summary> /// Constructor. /// </summary> public MultipleChoiceQuestionUpdater( DatabaseContext dbContext, MultipleChoiceQuestion question, IModelErrorCollection errors) : base(dbContext, question, errors) { }
/// <summary> /// Updates a question. /// </summary> public async Task<bool> UpdateQuestionAsync( string classroomName, Question question, IModelErrorCollection errors) { var classroom = await LoadClassroomAsync(classroomName); var questionCategory = await _dbContext.QuestionCategories .SingleOrDefaultAsync ( category => category.Id == question.QuestionCategoryId ); if (questionCategory.ClassroomId != classroom.Id) { throw new InvalidOperationException( "Category of question is not in the given classroom."); } if (await _dbContext.Questions.AnyAsync( q => q.Id != question.Id && q.Name == question.Name && q.QuestionCategoryId == question.QuestionCategoryId)) { errors.AddError("Name", "Another question with that name already exists."); return false; } await _questionUpdaterFactory.CreateQuestionUpdater(question, errors) .UpdateQuestionAsync(); if (errors.HasErrors) { return false; } _dbContext.Update(question); await _dbContext.SaveChangesAsync(); return true; }
/// <summary> /// Constructor. /// </summary> public RandomlySelectedQuestionUpdater( DatabaseContext dbContext, RandomlySelectedQuestion question, IModelErrorCollection errors) : base(dbContext, question, errors) { }
/// <summary> /// Updates the given user. /// </summary> public async Task<bool> UpdateUserAsync( User user, string confirmationUrlBuilder, IModelErrorCollection modelErrors) { var existingUser = await _dbContext.Users .Include(u => u.ClassroomMemberships) .ThenInclude(cm => cm.Classroom) .SingleAsync(u => u.Id == user.Id); bool updatedEmail = false; if (user.GitHubLogin != existingUser.GitHubLogin) { if (!await _gitHubUserClient.DoesUserExistAsync(user.GitHubLogin)) { modelErrors.AddError("GitHubLogin", "The GitHub username does not exist."); return false; } if (existingUser.ClassroomMemberships != null) { foreach (var membership in existingUser.ClassroomMemberships) { var orgName = membership.Classroom.GitHubOrganization; var team = await _gitHubTeamClient.GetTeamAsync ( orgName, membership.GitHubTeam ); await _gitHubTeamClient.InviteUserToTeamAsync ( orgName, team, user.GitHubLogin ); await _gitHubTeamClient.RemoveUserFromTeamAsync ( orgName, team, existingUser.GitHubLogin ); membership.InGitHubOrganization = false; } } existingUser.GitHubLogin = user.GitHubLogin; } if (user.EmailAddress != existingUser.EmailAddress) { existingUser.EmailAddress = user.EmailAddress; existingUser.EmailAddressConfirmed = false; existingUser.EmailConfirmationCode = GenerateEmailConfirmationCode(); updatedEmail = true; } await _dbContext.SaveChangesAsync(); if (updatedEmail) { await SendUserInvitationMailAsync(existingUser, confirmationUrlBuilder); } return true; }
/// <summary> /// Updates a checkpoint. /// </summary> public async Task<bool> UpdateCheckpointAsync( string classroomName, string projectName, Checkpoint checkpoint, IModelErrorCollection modelErrors) { var project = await LoadProjectAsync(classroomName, projectName); checkpoint.ProjectId = project.Id; var currentCheckpoint = await _dbContext.Checkpoints .Where(c => c.Id == checkpoint.Id) .SingleOrDefaultAsync(); _dbContext.Entry(currentCheckpoint).State = EntityState.Detached; if (!UpdateCheckpoint(checkpoint, modelErrors)) return false; _dbContext.Update(checkpoint); await _dbContext.SaveChangesAsync(); return true; }
/// <summary> /// Called to register the first super-user. /// </summary> public async Task<RegisterNewUserResult> RegisterFirstSuperUserAsync( SuperUserRegistration registration, IModelErrorCollection errors) { if (await AnyRegisteredUsersAsync()) { return RegisterNewUserResult.AlreadyRegistered; } if (registration.ActivationToken != _activationToken.Value) { errors.AddError("ActivationToken", "Incorrect activation token."); return RegisterNewUserResult.Failed; } if (!await _gitHubUserClient.DoesUserExistAsync(registration.GitHubLogin)) { errors.AddError("GitHubLogin", "The GitHub username does not exist."); return RegisterNewUserResult.Failed; } User user = new User() { UniqueId = _identityProvider.CurrentIdentity.UniqueId, UserName = _identityProvider.CurrentIdentity.UserName, FirstName = registration.FirstName, LastName = registration.LastName, EmailAddress = registration.EmailAddress, EmailAddressConfirmed = true, GitHubLogin = registration.GitHubLogin, SuperUser = true }; _dbContext.Users.Add(user); await _dbContext.SaveChangesAsync(); return RegisterNewUserResult.Success; }
/// <summary> /// Updates a checkpoint. /// </summary> private bool UpdateCheckpoint(Checkpoint checkpoint, IModelErrorCollection modelErrors) { if (checkpoint.SectionDates != null) { var sections = checkpoint.SectionDates.Select(d => d.SectionId).ToList(); if (sections.Distinct().Count() != sections.Count) { modelErrors.AddError("SectionDates", "You may only have one due date per section."); } } if (checkpoint.TestClasses != null) { var testClasses = checkpoint.TestClasses.Select(tc => tc.TestClassId).ToList(); if (testClasses.Distinct().Count() != testClasses.Count) { modelErrors.AddError("TestClasses", "You may only have one entry per test class."); } } if (modelErrors.HasErrors) { return false; } _dbContext.RemoveUnwantedObjects ( _dbContext.CheckpointDates, checkpointDates => checkpointDates.Id, checkpointDates => checkpointDates.CheckpointId == checkpoint.Id, checkpoint.SectionDates ); _dbContext.RemoveUnwantedObjects ( _dbContext.CheckpointTestClasses, testClass => testClass.Id, testClass => testClass.CheckpointId == checkpoint.Id, checkpoint.TestClasses ); return true; }
/// <summary> /// Registers a user. /// </summary> public async Task<RegisterNewUserResult> RegisterNewStudentAsync( string classroomName, string sectionName, StudentRegistration registration, string confirmationUrlBuilder, IModelErrorCollection errors) { var section = _dbContext.Sections .Where(s => s.Classroom.Name == classroomName) .Include(s => s.Classroom) .SingleOrDefault(s => s.Name == sectionName); if (section == null) { return RegisterNewUserResult.SectionNotFound; } if (!section.AllowNewRegistrations) { return RegisterNewUserResult.SectionNotOpen; } var user = await GetAndUpdateCurrentUserAsync(); if (user != null) { return RegisterNewUserResult.AlreadyRegistered; } if (!await _gitHubUserClient.DoesUserExistAsync(registration.GitHubLogin)) { errors.AddError("GitHubLogin", "The GitHub username does not exist."); return RegisterNewUserResult.Failed; } user = new User() { UniqueId = _identityProvider.CurrentIdentity.UniqueId, UserName = _identityProvider.CurrentIdentity.UserName, FirstName = registration.FirstName, LastName = _identityProvider.CurrentIdentity.LastName, EmailAddress = registration.EmailAddress, EmailConfirmationCode = GenerateEmailConfirmationCode(), EmailAddressConfirmed = false, GitHubLogin = registration.GitHubLogin, SuperUser = false }; var membership = await EnsureSectionMembershipAsync(user, section, SectionRole.Student); await EnsureUserInGithubOrgAsync(user, membership.ClassroomMembership); await SendUserInvitationMailAsync(user, confirmationUrlBuilder); _dbContext.Users.Add(user); await _dbContext.SaveChangesAsync(); return RegisterNewUserResult.Success; }
/// <summary> /// Creates a new code question updater. /// </summary> private static CodeQuestionUpdater<CodeQuestion> GetCodeQuestionUpdater( TestDatabase database, CodeQuestion question, IModelErrorCollection errors) { return new Mock<CodeQuestionUpdater<CodeQuestion>>(database.Context, question, errors).Object; }
/// <summary> /// Updates a assignment. /// </summary> private bool UpdateAssignment(Assignment assignment, IModelErrorCollection modelErrors) { if (assignment.DueDates != null) { var sections = assignment.DueDates.Select(d => d.SectionId).ToList(); if (sections.Distinct().Count() != sections.Count) { modelErrors.AddError("DueDates", "You may only have one due date per section."); return false; } } UpdateQuestionOrder(assignment.Questions); _dbContext.RemoveUnwantedObjects ( _dbContext.AssignmentQuestions, question => question.Id, question => question.AssignmentId == assignment.Id, assignment.Questions ); _dbContext.RemoveUnwantedObjects ( _dbContext.AssignmentDueDates, dueDate => dueDate.Id, dueDate => dueDate.AssignmentId == assignment.Id, assignment.DueDates ); return true; }
/// <summary> /// Constructor. /// </summary> protected CodeQuestionUpdater(DatabaseContext dbContext, TQuestion question, IModelErrorCollection errors) : base(dbContext, question, errors) { }
/// <summary> /// Updates the given user. /// </summary> public async Task <bool> UpdateUserAsync( User user, string confirmationUrlBuilder, IModelErrorCollection modelErrors) { var existingUser = await _dbContext.Users .Include(u => u.ClassroomMemberships) .ThenInclude(cm => cm.Classroom) .Include(u => u.AdditionalContacts) .SingleAsync(u => u.Id == user.Id); bool updatedEmail = false; if (user.GitHubLogin != existingUser.GitHubLogin) { if (!await _gitHubUserClient.DoesUserExistAsync(user.GitHubLogin)) { modelErrors.AddError("GitHubLogin", "The GitHub username does not exist."); return(false); } if (existingUser.ClassroomMemberships != null) { foreach (var membership in existingUser.ClassroomMemberships) { var orgName = membership.Classroom.GitHubOrganization; var team = await _gitHubTeamClient.GetTeamAsync ( orgName, membership.GitHubTeam ); await _gitHubTeamClient.InviteUserToTeamAsync ( orgName, team, user.GitHubLogin ); await _gitHubTeamClient.RemoveUserFromTeamAsync ( orgName, team, existingUser.GitHubLogin ); membership.InGitHubOrganization = false; } } existingUser.GitHubLogin = user.GitHubLogin; } if (user.PublicName != existingUser.PublicName) { existingUser.PublicName = user.PublicName; } if (user.EmailAddress != existingUser.EmailAddress) { existingUser.EmailAddress = user.EmailAddress; existingUser.EmailAddressConfirmed = false; existingUser.EmailConfirmationCode = GenerateEmailConfirmationCode(); updatedEmail = true; } foreach (var additionalContact in existingUser.AdditionalContacts.ToList()) { var modifiedContact = user.AdditionalContacts ?.SingleOrDefault(ac => ac.Id == additionalContact.Id); if (modifiedContact != null) { additionalContact.LastName = modifiedContact.LastName; additionalContact.FirstName = modifiedContact.FirstName; additionalContact.EmailAddress = modifiedContact.EmailAddress; } else { existingUser.AdditionalContacts.Remove(additionalContact); } } if (user.AdditionalContacts != null) { foreach (var potentialNewContact in user.AdditionalContacts) { if (!existingUser.AdditionalContacts.Any(ac => ac.Id == potentialNewContact.Id)) { existingUser.AdditionalContacts.Add(potentialNewContact); } } } await _dbContext.SaveChangesAsync(); if (updatedEmail) { await SendUserInvitationMailAsync(existingUser, confirmationUrlBuilder); } return(true); }
/// <summary> /// Constructor. /// </summary> protected QuestionUpdater(DatabaseContext dbContext, TQuestion question, IModelErrorCollection errors) { DbContext = dbContext; Question = question; Errors = errors; }
/// <summary> /// Updates an assignment. /// </summary> public async Task<bool> UpdateAssignmentAsync( string classroomName, Assignment assignment, IModelErrorCollection modelErrors) { var classroom = await LoadClassroomAsync(classroomName); if (!UpdateAssignment(assignment, modelErrors)) return false; assignment.ClassroomId = classroom.Id; _dbContext.Update(assignment); await _dbContext.SaveChangesAsync(); return true; }