private async Task CopyGroupAccessesAsync(Group group, Group newGroup) { log.Info($"Копирую доступы к группе «{group.Name}» (id={group.Id}) в группу «{newGroup.Name}» (id={newGroup.Id})"); var accesses = await db.GroupAccesses.Where(a => a.GroupId == group.Id && a.IsEnabled).ToListAsync().ConfigureAwait(false); var courseInstructorsIds = await courseRolesRepo.GetListOfUsersWithCourseRoleAsync(CourseRoleType.Instructor, newGroup.CourseId, includeHighRoles : true).ConfigureAwait(false); foreach (var access in accesses) { if (!courseInstructorsIds.Contains(access.UserId)) { continue; } if (newGroup.OwnerId == access.UserId) { continue; } db.GroupAccesses.Add(new GroupAccess { GroupId = newGroup.Id, UserId = access.UserId, AccessType = access.AccessType, GrantedById = access.GrantedById, GrantTime = DateTime.Now, IsEnabled = true, }); } await db.SaveChangesAsync().ConfigureAwait(false); }
public async Task <IQueryable <ApplicationUser> > RestrictUsersSetAsync(IQueryable <ApplicationUser> users, ApplicationUser currentUser, string courseId, bool hasSystemAdministratorAccess, bool hasCourseAdminAccess, bool hasInstructorAccessToGroupMembers, bool hasInstructorAccessToCourseInstructors) { if (hasSystemAdministratorAccess && usersRepo.IsSystemAdministrator(currentUser)) { return(users); } if (hasCourseAdminAccess && await courseRolesRepo.HasUserAccessTo_Any_CourseAsync(currentUser.Id, CourseRoleType.CourseAdmin).ConfigureAwait(false)) { return(users); } var userIds = new HashSet <string>(); if (hasInstructorAccessToGroupMembers) { var groupsMembers = await groupAccessesRepo.GetMembersOfAllGroupsAvailableForUserAsync(currentUser.Id).ConfigureAwait(false); userIds.UnionWith(groupsMembers.Select(m => m.UserId)); } if (hasInstructorAccessToCourseInstructors) { var courseInstructors = courseId != null ? await courseRolesRepo.GetListOfUsersWithCourseRoleAsync(CourseRoleType.Instructor, courseId, true) : (await groupAccessesRepo.GetInstructorsOfAllGroupsAvailableForUserAsync(currentUser.Id).ConfigureAwait(false)).Select(u => u.Id); userIds.UnionWith(courseInstructors); } return(users.Where(u => userIds.Contains(u.Id))); }
public async Task <IQueryable <ApplicationUser> > FilterAsync(IQueryable <ApplicationUser> users, UserSearchRequest request) { if (string.IsNullOrEmpty(request.CourseId) || !request.MinCourseRoleType.HasValue) { return(users); } if (request.MinCourseRoleType == CourseRoleType.Student) { throw new ArgumentException($"Can't search by students, sorry: there are too many students"); } var userIds = await courseRolesRepo.GetListOfUsersWithCourseRoleAsync(request.MinCourseRoleType.Value, request.CourseId, true).ConfigureAwait(false); return(users.Where(u => userIds.Contains(u.Id))); }
private async Task <HashSet <string> > FilterUsersWhoNotSeeCourse(Notification notification, HashSet <string> recipientsIds) { if (notification.CourseId != "") { var course = await courseManager.FindCourseAsync(notification.CourseId); if (course != null) { var visibleUnits = await unitsRepo.GetPublishedUnitIdsAsync(course); if (!visibleUnits.Any()) { var userIdsWithInstructorRoles = await courseRolesRepo.GetListOfUsersWithCourseRoleAsync(CourseRoleType.Tester, notification.CourseId, true); var sysAdminsIds = await usersRepo.GetSysAdminsIdsAsync(); recipientsIds.IntersectWith(userIdsWithInstructorRoles.Concat(sysAdminsIds)); } } } return(recipientsIds); }
public async Task <ActionResult <UsersSearchResponse> > Search([FromQuery] UsersSearchParameters parameters) { var words = parameters.Query?.Split(' ', '\t').ToList() ?? new List <string>(); if (words.Count > 10) { return(BadRequest(new ErrorResponse("Too many words in query"))); } var currentUser = await usersRepo.FindUserByIdAsync(UserId).ConfigureAwait(false); var isSystemAdministrator = usersRepo.IsSystemAdministrator(currentUser); if (!string.IsNullOrEmpty(parameters.CourseId)) { if (!parameters.CourseRoleType.HasValue) { return(BadRequest(new ErrorResponse("You should specify course_role with course_id"))); } if (parameters.CourseRoleType == CourseRoleType.Student) { return(BadRequest(new ErrorResponse("You can not search students by this method: there are too many students"))); } /* Only instructors can search by course role */ var isInstructor = await courseRolesRepo.HasUserAccessToCourseAsync(UserId, parameters.CourseId, CourseRoleType.Instructor).ConfigureAwait(false); if (!isInstructor) { return(StatusCode((int)HttpStatusCode.Unauthorized, new ErrorResponse("Only instructors can search by course role"))); } } else if (parameters.CourseRoleType.HasValue) { /* Only sys-admins can search all instructors or all course-admins */ if (!isSystemAdministrator) { return(StatusCode((int)HttpStatusCode.Unauthorized, new ErrorResponse("Only system administrator can search by course role without specified course_id"))); } } if (parameters.LmsRoleType.HasValue) { if (!isSystemAdministrator) { return(StatusCode((int)HttpStatusCode.Unauthorized, new ErrorResponse("Only system administrator can search by lms role"))); } } var request = new UserSearchRequest { CurrentUser = currentUser, Words = words, CourseId = parameters.CourseId, MinCourseRoleType = parameters.CourseRoleType, LmsRole = parameters.LmsRoleType, }; /* Start the search! * First of all we will try to find `strict` users: users with strict match for pattern. These users will be at first place in the response. */ var strictUsers = await userSearcher.SearchUsersAsync(request, strict : true, offset : 0, count : parameters.Offset + parameters.Count).ConfigureAwait(false); var users = strictUsers.ToList(); /* If strict users count is enough for answer, just take needed piece of list */ if (users.Count >= parameters.Offset + parameters.Count) { users = users.Skip(parameters.Offset).Take(parameters.Count).ToList(); } else { /* If there is part of strict users which we should return, then cut off it */ if (parameters.Offset < users.Count) { users = users.Skip(parameters.Offset).ToList(); } else { users.Clear(); } /* * (strict users) (non-strict users) * 0 1 2 3 4 5 6 * ^ ^ * offset offset+count */ var nonStrictUsers = await userSearcher.SearchUsersAsync(request, strict : false, offset : parameters.Offset - strictUsers.Count, count : parameters.Count - users.Count).ConfigureAwait(false); /* Add all non-strict users if there is no this user in strict users list */ foreach (var user in nonStrictUsers) { var alreadyExistUser = strictUsers.FirstOrDefault(u => u.User.Id == user.User.Id); if (alreadyExistUser != null) { alreadyExistUser.Fields.UnionWith(user.Fields); } else { users.Add(user); } } } var instructors = await courseRolesRepo.GetListOfUsersWithCourseRoleAsync(CourseRoleType.Instructor, null, true).ConfigureAwait(false); var currentUserIsInstructor = instructors.Contains(User.GetUserId()); return(new UsersSearchResponse { Users = users.Select(u => new FoundUserResponse { User = BuildShortUserInfo(u.User, discloseLogin: u.Fields.Contains(SearchField.Login) || currentUserIsInstructor && instructors.Contains(u.User.Id), discloseEmail: u.Fields.Contains(SearchField.Email)), Fields = u.Fields.ToList(), }).ToList(), Pagination = new PaginationResponse { Offset = parameters.Offset, Count = users.Count, } }); }
public async Task <ActionResult <CodeReviewInstructorsStatisticsResponse> > InstructorsStatistics([FromQuery(Name = "course_id")][BindRequired] string courseId, int count = 10000, DateTime?from = null, DateTime?to = null) { var course = await courseManager.FindCourseAsync(courseId); if (course == null) { return(NotFound()); } if (!from.HasValue) { from = DateTime.MinValue; } if (!to.HasValue) { to = DateTime.MaxValue; } count = Math.Min(count, 10000); var instructorIds = await courseRolesRepo.GetListOfUsersWithCourseRoleAsync(CourseRoleType.Instructor, course.Id, false).ConfigureAwait(false); var instructors = await usersRepo.GetUsersByIdsAsync(instructorIds).ConfigureAwait(false); var exerciseSlides = course.GetSlides(true).OfType <ExerciseSlide>().ToList(); var allSlideCheckings = (await slideCheckingsRepo.GetManualCheckingQueue <ManualExerciseChecking>(new ManualCheckingQueueFilterOptions { CourseId = course.Id, Count = count, OnlyChecked = null, From = @from.Value, To = to.Value, }).ConfigureAwait(false)).ToList(); var result = new CodeReviewInstructorsStatisticsResponse { AnalyzedCodeReviewsCount = allSlideCheckings.Count, Instructors = new List <CodeReviewInstructorStatistics>() }; foreach (var instructor in instructors) { var checkingsCheckedByInstructor = allSlideCheckings.Where(c => c.IsChecked && (c.LockedById == instructor.Id || c.Reviews.Any(r => r.AuthorId == instructor.Id))).ToList(); var instructorGroups = await groupsRepo.GetMyGroupsFilterAccessibleToUserAsync(course.Id, instructor.Id).ConfigureAwait(false); var instructorGroupMemberIds = (await groupMembersRepo.GetGroupsMembersAsync(instructorGroups.Select(g => g.Id).ToList()).ConfigureAwait(false)).Select(m => m.UserId); var checkingQueue = allSlideCheckings.Where(c => !c.IsChecked && instructorGroupMemberIds.Contains(c.UserId)).ToList(); var comments = checkingsCheckedByInstructor.SelectMany(c => c.NotDeletedReviews).ToList(); var instructorStatistics = new CodeReviewInstructorStatistics { Instructor = BuildShortUserInfo(instructor, discloseLogin: true), Exercises = exerciseSlides.Select( slide => new CodeReviewExerciseStatistics { SlideId = slide.Id, ReviewedSubmissionsCount = checkingsCheckedByInstructor.Where(c => c.SlideId == slide.Id).DistinctBy(c => c.SubmissionId).Count(), QueueSize = checkingQueue.Count(c => c.SlideId == slide.Id), CommentsCount = comments.Count(c => c.ExerciseChecking.SlideId == slide.Id), } ) .Where(s => s.ReviewedSubmissionsCount + s.QueueSize + s.CommentsCount > 0) // Ignore empty (zeros) records .ToList() }; result.Instructors.Add(instructorStatistics); } return(result); }