Пример #1
0
        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.GetListOfUsersWithCourseRole(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);
        }
Пример #2
0
        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_Course(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.GetListOfUsersWithCourseRole(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)));
        }
Пример #3
0
        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.GetListOfUsersWithCourseRole(request.MinCourseRoleType.Value, request.CourseId, true).ConfigureAwait(false);

            return(users.Where(u => userIds.Contains(u.Id)));
        }
Пример #4
0
        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.GetPublishedUnitIds(course);

                    if (!visibleUnits.Any())
                    {
                        var userIdsWithInstructorRoles = await courseRolesRepo.GetListOfUsersWithCourseRole(CourseRoleType.Tester, notification.CourseId, true);

                        var sysAdminsIds = await usersRepo.GetSysAdminsIds();

                        recipientsIds.IntersectWith(userIdsWithInstructorRoles.Concat(sysAdminsIds));
                    }
                }
            }
            return(recipientsIds);
        }
Пример #5
0
        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.GetListOfUsersWithCourseRole(CourseRoleType.Instructor, course.Id, false).ConfigureAwait(false);

            var instructors = await usersRepo.GetUsersByIds(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);
        }
Пример #6
0
        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.FindUserById(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.HasUserAccessToCourse(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.GetListOfUsersWithCourseRole(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,
                }
            });
        }