Пример #1
0
            public async Task <ExamDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var tags = await context.SaveTagsAsync(request.Exam.Tags ?? Enumerable.Empty <string>(), cancellationToken);

                var exam = mapper.Map <ExamData, Domain.Exam>(request.Exam);

                exam.UserId = this.currentUserAccessor.GetCurrentUserId();
                var utcNow = DateTime.UtcNow;

                exam.CreatedAt = utcNow;
                exam.UpdatedAt = utcNow;

                await this.context.Exams.AddAsync(exam, cancellationToken);

                await context.ExamTags.AddRangeAsync(tags.Select(tag => new Domain.ExamTag()
                {
                    Exam = exam,
                    Tag  = tag
                }), cancellationToken);

                await context.SaveChangesAsync(cancellationToken);

                var examDto = mapper.Map <Domain.Exam, ExamDTO>(exam);

                return(new ExamDTOEnvelope(examDto));
            }
Пример #2
0
            public async Task <QuestionDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId   = currentUserAccessor.GetCurrentUserId();
                var question = context.Questions.Where(q => q.Id == request.Id)
                               .Include(q => q.AnswerOptions).FirstOrDefault();

                if (question == null)
                {
                    throw new Exceptions.QuestionNotFoundException();
                }

                var examId = question.ExamId;
                var exam   = context.Exams.NotPublishedByIdAndUserId(examId, userId).FirstOrDefault();

                if (exam == null)
                {
                    throw new Exceptions.ExamNotFoundException();
                }

                context.AnswerOptions.RemoveRange(question.AnswerOptions);
                context.Questions.Remove(question);
                await context.SaveChangesAsync();

                var questionDto = mapper.Map <Domain.Question, QuestionDTO>(question);

                return(new QuestionDTOEnvelope(questionDto));
            }
Пример #3
0
            public async Task <UserExamDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId = this.currentUserAccessor.GetCurrentUserId();

                var userExam = await this.context.UserExams
                               .Include(e => e.Exam).Where(e => e.Id == request.Id && e.UserId == userId && e.Exam.IsPublished == true).FirstOrDefaultAsync();

                if (userExam == null)
                {
                    throw new Exceptions.UserExamNotFoundException();
                }

                if (userExam.Exam.IsPrivate && userExam.Exam.UserId != userId)
                {
                    throw new Exceptions.PrivateUserExamEditException();
                }

                if (userExam.EndedAt.HasValue)
                {
                    throw new Exceptions.UserExamAlreadyEndedException();
                }


                userExam.EndedAt = DateTime.UtcNow;
                await context.SaveChangesAsync(cancellationToken);

                context.Entry(userExam).Reload();
                var userExamDto = mapper.Map <Domain.UserExam, UserExamDTO>(userExam);

                return(new UserExamDTOEnvelope(userExamDto));
            }
Пример #4
0
            public async Task <UserExamDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId = this.currentUserAccessor.GetCurrentUserId();
                var exam   = context.Exams.Where(e => e.Id == request.ExamId && e.IsPublished == true).FirstOrDefault();

                if (exam == null)
                {
                    throw new Exceptions.ExamNotFoundException();
                }
                if (exam.IsPrivate && exam.UserId != userId)
                {
                    throw new Exceptions.ExamNotFoundException();
                }

                var userExam = new Domain.UserExam();

                userExam.ExamId       = request.ExamId;
                userExam.UserId       = userId;
                userExam.StartedtedAt = DateTime.UtcNow;

                await this.context.UserExams.AddAsync(userExam, cancellationToken);

                await context.SaveChangesAsync(cancellationToken);

                context.Entry(userExam).Reload();
                var userExamDto = mapper.Map <Domain.UserExam, UserExamDTO>(userExam);

                return(new UserExamDTOEnvelope(userExamDto));
            }
Пример #5
0
            public async Task <UserExamResultDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId = currentUserAccessor.GetCurrentUserId();

                var userExam = await this.context.UserExams
                               .Include(e => e.Exam).Where(e => e.Id == request.UserExamId && e.UserId == userId && e.Exam.IsPublished == true).FirstOrDefaultAsync();

                if (userExam == null)
                {
                    throw new Exceptions.UserExamNotFoundException();
                }

                if (!userExam.EndedAt.HasValue)
                {
                    await UserExam.UserExamHelper.EndUserExamIfTimeExpired(context, cancellationToken, userExam);
                }
                if (!userExam.EndedAt.HasValue)
                {
                    throw new Exceptions.UserExamNotFoundException();
                }
                var userExamResult = await context.UserExamResults.FindAsync(userExam.Id);

                if (userExamResult != null)
                {
                    return(MakeEnvelope(userExamResult));
                }
                userExamResult = new Domain.UserExamResult()
                {
                    UserExamId = userExam.Id
                };

                userExamResult.QuestionCount = context.Questions.Where(e => e.ExamId == userExam.ExamId).Count();

                var userExamQuestionAnswers = context.UserExamQuestions.Where(e => e.UserExamId == userExam.Id)
                                              .Include(e => e.UserExamQuestionAnswers).ToArray();

                foreach (var userExamQuestionAnswer in userExamQuestionAnswers)
                {
                    userExamQuestionAnswer.HasRightAnswer = IsRight(userExamQuestionAnswer);
                }

                userExamResult.AnsweredQuestionCount    = userExamQuestionAnswers.Length;
                userExamResult.NotAnsweredQuestionCount = userExamResult.QuestionCount - userExamResult.AnsweredQuestionCount;
                userExamResult.RightAnswerCount         = userExamQuestionAnswers.Where(e => e.HasRightAnswer == true).Count();
                userExamResult.WrongAnswerCount         = userExamQuestionAnswers.Where(e => e.HasRightAnswer == false).Count();
                userExamResult.IsPassed = (float)userExamResult.RightAnswerCount / (float)userExamResult.QuestionCount * 100
                                          >= userExam.Exam.PassPercentage;

                await context.UserExamResults.AddAsync(userExamResult);

                await context.SaveChangesAsync();

                context.Entry(userExamResult).Reload();
                return(MakeEnvelope(userExamResult));
            }
        public static async Task <bool> EndUserExamIfTimeExpired(
            SampleExamContext context,
            CancellationToken cancellationToken,
            Domain.UserExam userExam)
        {
            var expired = userExam.StartedtedAt.AddMinutes(userExam.Exam.TimeInMinutes) <= DateTime.UtcNow;

            if (expired)
            {
                userExam.EndedAt = userExam.StartedtedAt.AddMinutes(userExam.Exam.TimeInMinutes);
                await context.SaveChangesAsync(cancellationToken);
            }
            return(expired);
        }
Пример #7
0
            public async Task <ExamDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId   = currentUserAccessor.GetCurrentUserId();
                var examData = request.Exam;
                var exam     = await context.Exams.NotPublishedByIdAndUserId(request.Id, userId)
                               .IncludeTags()
                               .FirstOrDefaultAsync(cancellationToken);

                if (exam == null)
                {
                    throw new Exceptions.ExamNotFoundException();
                }

                exam.Title          = examData.Title ?? exam.Title;
                exam.Description    = examData.Description ?? exam.Description;
                exam.TimeInMinutes  = examData.TimeInMinutes ?? exam.TimeInMinutes;
                exam.PassPercentage = examData.PassPercentage ?? exam.PassPercentage;
                exam.IsPrivate      = examData.IsPrivate ?? exam.IsPrivate;
                var examTagsToAdd    = Array.Empty <Domain.ExamTag>();
                var examTagsToDelete = Array.Empty <Domain.ExamTag>();

                if (request.Exam.Tags != null)
                {
                    var tags = await context.SaveTagsAsync(request.Exam.Tags ?? Enumerable.Empty <string>(), cancellationToken);

                    var examTags = exam.ExamTags;
                    examTagsToDelete = examTags.Where(et => !tags.Any(t => t.TagId == et.TagId)).ToArray();
                    examTagsToAdd    = tags.Where(t => !examTags.Any(et => et.TagId == t.TagId))
                                       .Select(t => new Domain.ExamTag()
                    {
                        Tag = t, TagId = t.TagId, Exam = exam, ExamId = exam.Id
                    }).ToArray();
                }

                if (context.IsModified(exam) || examTagsToAdd.Length > 0 || examTagsToDelete.Length > 0)
                {
                    exam.UpdatedAt = DateTime.UtcNow;
                }

                await context.ExamTags.AddRangeAsync(examTagsToAdd, cancellationToken);

                context.ExamTags.RemoveRange(examTagsToDelete);

                await context.SaveChangesAsync(cancellationToken);

                var examDto = mapper.Map <Domain.Exam, ExamDTO>(exam);

                return(new ExamDTOEnvelope(examDto));
            }
Пример #8
0
            public async Task <UserDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var user = mapper.Map <UserData, Domain.User>(request.User);

                user.Password = hasher.HashPassword(user, user.Password);
                var utcNow = DateTime.UtcNow;

                user.CreatedAt = utcNow;
                user.UpdatedAt = utcNow;

                await this.context.Users.AddAsync(user, cancellationToken);

                await context.SaveChangesAsync(cancellationToken);

                var userDto = mapper.Map <Domain.User, UserDTO>(user);

                return(new UserDTOEnvelope(userDto));
            }
Пример #9
0
            public async Task <ExamDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId = currentUserAccessor.GetCurrentUserId();
                var exam   = await context.Exams.ByIdAndUserId(request.Id, userId).FirstOrDefaultAsync(cancellationToken);

                if (exam == null)
                {
                    throw new Exceptions.ExamNotFoundException();
                }

                exam.IsDeleted = true;
                exam.DeletedAt = DateTime.UtcNow;

                await context.SaveChangesAsync(cancellationToken);

                var examDto = mapper.Map <Domain.Exam, ExamDTO>(exam);

                return(new ExamDTOEnvelope(examDto));
            }
Пример #10
0
            public async Task <QuestionDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId = currentUserAccessor.GetCurrentUserId();

                var question = context.Questions.Where(q => q.Id == request.Question.Id)
                               .Include(q => q.AnswerOptions).FirstOrDefault();

                if (question == null)
                {
                    throw new Exceptions.QuestionNotFoundException();
                }
                var examId = question.ExamId;
                var exam   = context.Exams.NotPublishedByIdAndUserId(examId, userId).FirstOrDefault();

                if (exam == null)
                {
                    throw new Exceptions.ExamNotFoundException();
                }

                var  utcNow            = DateTime.UtcNow;
                var  answers           = request.Question.Answers;
                bool hasAnswersChanged = false;

                if (answers != null && answers.Count() > 0)
                {
                    hasAnswersChanged = await SaveAnswers(question, utcNow, answers, cancellationToken);
                }


                question.Text           = request.Question.Text ?? question.Text;
                question.QuestionTypeId = request.Question.QuestionTypeId;

                if (context.IsModified(question) || hasAnswersChanged)
                {
                    question.UpdatedAt = utcNow;
                }

                await context.SaveChangesAsync();

                var questionDto = mapper.Map <Domain.Question, QuestionDTO>(question);

                return(new QuestionDTOEnvelope(questionDto));
            }
Пример #11
0
            public async Task <QuestionDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userId = currentUserAccessor.GetCurrentUserId();
                var exam   = context.Exams.NotPublishedByIdAndUserId(request.ExamId, userId).FirstOrDefault();

                if (exam == null)
                {
                    throw new Exceptions.ExamNotFoundException();
                }

                var question = mapper.Map <QuestionData, Domain.Question>(request.Question);

                question.ExamId = exam.Id;
                question.Exam   = exam;
                var utcNow = DateTime.UtcNow;

                question.CreatedAt = utcNow;
                question.UpdatedAt = utcNow;

                question.AnswerOptions.ToList().ForEach(ao =>
                {
                    ao.Question  = question;
                    ao.CreatedAt = utcNow;
                    ao.UpdatedAt = utcNow;
                });
                await this.context.Questions.AddAsync(question);

                await context.SaveChangesAsync();

                context.Entry(question).Reload();
                foreach (var answerOption in question.AnswerOptions)
                {
                    context.Entry(answerOption).Reload();
                }
                var questionDto = mapper.Map <Domain.Question, QuestionDTO>(question);

                return(new QuestionDTOEnvelope(questionDto));
            }
Пример #12
0
            //TODO add middleware to check if user is deleted for authorized action.
            public async Task <LoginUserDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var userData      = request.User;
                var user          = context.Users.Include(e => e.RefreshTokens).Where(u => u.Email == userData.Email).FirstOrDefault();
                var failException = new RestException(HttpStatusCode.Unauthorized,
                                                      "Invalid email / password.",
                                                      "Email or password is invalid",
                                                      new Error(nameof(Login), "Email or password is invalid"));

                if (user == null)
                {
                    throw failException;
                }

                var result = hasher.VerifyHashedPassword(user, user.Password, userData.Password);

                if (result == PasswordVerificationResult.Failed)
                {
                    throw failException;
                }

                var userLoginDto = mapper.Map <Domain.User, LoginUserDTO>(user);

                userLoginDto.Token = await this.tokenGenrator.GenerateToken(userLoginDto.Id, userLoginDto.Email);

                var refreshToken = this.refreshTokenGenerator.GenerateToken();

                user.RefreshTokens.Add(new Domain.RefreshToken()
                {
                    Token = refreshToken, CreatedAt = DateTime.UtcNow
                });
                await context.SaveChangesAsync(cancellationToken);

                userLoginDto.RefresToken = refreshToken;
                return(new LoginUserDTOEnvelope(userLoginDto));
            }
Пример #13
0
            public async Task <QuestionAnswerDTOEnvelope> Handle(Request request, CancellationToken cancellationToken)
            {
                var requestQA       = request.UserExamQuestionAnswer;
                var answerOptionIds = requestQA.AnswerOptionIds.ToArray();
                var userId          = this.currentUserAccessor.GetCurrentUserId();

                var userExam = await this.context.UserExams.Include(e => e.Exam)
                               .Where(e => e.Id == requestQA.UserExamId && e.UserId == userId).FirstOrDefaultAsync();

                if (userExam == null)
                {
                    throw new UserExamNotFoundException();
                }

                if (userExam.EndedAt.HasValue)
                {
                    throw new UserExamAlreadyEndedException();
                }

                if (await UserExam.UserExamHelper.EndUserExamIfTimeExpired(context, cancellationToken, userExam))
                {
                    throw new UserExamAlreadyEndedException();
                }

                var question = await context.Questions.Where(e => e.Id == requestQA.QuestionId && e.ExamId == userExam.ExamId).FirstOrDefaultAsync();

                if (question == null)
                {
                    throw new QuestionNotFoundException();
                }

                if (question.QuestionTypeId == SeedData.QuestionTypes.Radio.Id && answerOptionIds.Count() > 1)
                {
                    throw new AnswerToRadioQuestionFormatException();
                }

                //answer options validation
                foreach (var answerOptionId in answerOptionIds)
                {
                    var answerOption = await this.context.AnswerOptions.Include(e => e.Question).Where(e => e.Id == answerOptionId).FirstOrDefaultAsync(cancellationToken);

                    if (answerOption == null)
                    {
                        throw new AnswerOptionNotFoundException(answerOptionId);
                    }
                    ;

                    if (answerOption.Question.ExamId != userExam.ExamId)
                    {
                        throw new InvalidAnswerOptionExamException(answerOptionId);
                    }
                }

                var userExamQuestion = await this.context.UserExamQuestions
                                       .Where(e => e.QuestionId == requestQA.QuestionId &&
                                              e.UserExamId == requestQA.UserExamId).Include(e => e.UserExamQuestionAnswers)
                                       .FirstOrDefaultAsync(cancellationToken);

                var isCreate = userExamQuestion == null;
                var utcNow   = DateTime.UtcNow;

                userExamQuestion = userExamQuestion ?? new UserExamQuestion()
                {
                    UserExamId = requestQA.UserExamId,
                    QuestionId = requestQA.QuestionId,
                    CreatedAt  = utcNow,
                    UpdatedAt  = utcNow
                };

                var isUnchanged = !isCreate && userExamQuestion.UserExamQuestionAnswers
                                  .Select(e => e.AnswerOptionId).OrderBy(e => e).ToArray()
                                  .SequenceEqual(answerOptionIds.OrderBy(e => e).ToArray());

                if (isUnchanged)
                {
                    return(MakeEnvelope(userExamQuestion));
                }

                if (isCreate)
                {
                    var answers = answerOptionIds.Select(answerOptionId => new UserExamQuestionAnswr()
                    {
                        UserExamId     = requestQA.UserExamId,
                        QuestionId     = requestQA.QuestionId,
                        AnswerOptionId = answerOptionId,
                        CreatedAt      = utcNow,
                        UpdatedAt      = utcNow
                    }).ToList();
                    await this.context.UserExamQuestions.AddAsync(userExamQuestion);

                    await this.context.UserExamQuestionAnswers.AddRangeAsync(answers);
                }
                else
                {
                    var answersToDelete = userExamQuestion.UserExamQuestionAnswers.Where(qa => !answerOptionIds.Any(id => id == qa.AnswerOptionId)).ToArray();
                    var answersToAdd    = answerOptionIds.Where(id => !userExamQuestion.UserExamQuestionAnswers.Any(qa => qa.AnswerOptionId == id))
                                          .Select(answerOptionId => new UserExamQuestionAnswr()
                    {
                        UserExamId     = requestQA.UserExamId,
                        QuestionId     = requestQA.QuestionId,
                        AnswerOptionId = answerOptionId,
                        CreatedAt      = utcNow,
                        UpdatedAt      = utcNow
                    });
                    userExamQuestion.UpdatedAt = utcNow;
                    this.context.UserExamQuestionAnswers.RemoveRange(answersToDelete);
                    await this.context.UserExamQuestionAnswers.AddRangeAsync(answersToAdd);
                }
                await context.SaveChangesAsync(cancellationToken);

                context.Entry(userExamQuestion).Reload();
                foreach (var questionAnswer in userExamQuestion.UserExamQuestionAnswers)
                {
                    context.Entry(questionAnswer).Reload();
                }
                return(MakeEnvelope(userExamQuestion));
            }