private async Task ValidateSubmissionCreateDtoAsync(SubmissionCreateDto dto) { var problem = await Context.Problems.FindAsync(dto.ProblemId); if (problem is null) { throw new ValidationException("Invalid problem ID."); } switch (problem.Type) { case ProblemType.Ordinary: if (dto.Program.Language == Language.LabArchive) { throw new ValidationException("Ordinary problem does not accept this language.."); } else if (!Regex.IsMatch(dto.Program.Code, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None)) { throw new ValidationException("Invalid program code."); } break; case ProblemType.TestKitLab: throw new ValidationException("Cannot submit testkit lab problems through this API."); default: throw new ArgumentOutOfRangeException(); } }
public async Task <SubmissionInfoDto> CreateSubmissionAsync(SubmissionCreateDto dto) { await ValidateSubmissionCreateDtoAsync(dto); var submission = new Submission { UserId = Accessor.HttpContext.User.GetSubjectId(), ProblemId = dto.ProblemId.GetValueOrDefault(), Program = dto.Program, Hidden = true, Verdict = Verdict.Pending, Time = null, Memory = null, FailedOn = null, Score = null, Progress = null, Message = null, JudgedBy = null, JudgedAt = null }; await Context.Submissions.AddAsync(submission); await Context.SaveChangesAsync(); _queue.EnqueueTask(new JobRequestMessage(JobType.JudgeSubmission, submission.Id, 1)); await Context.Entry(submission).Reference(s => s.User).LoadAsync(); var result = new SubmissionInfoDto(submission, true); await LogInformation($"CreateSubmission [Admin] ProblemId={result.ProblemId} " + $"Language={result.Language} Length={result.CodeBytes}"); return(result); }
public async Task <ActionResult <SubmissionInfoDto> > CreateSubmission(SubmissionCreateDto dto) { try { return(Ok(await _service.CreateSubmissionAsync(dto))); } catch (ValidationException e) { return(BadRequest(e.Message)); } }
public async Task <SubmissionInfoDto> CreateSubmissionAsync(SubmissionCreateDto dto) { var contest = await ValidateSubmissionCreateDtoAsync(dto); var user = await Manager.GetUserAsync(Accessor.HttpContext.User); var lastSubmission = await Context.Submissions .Where(s => s.UserId == user.Id) .OrderByDescending(s => s.Id) .FirstOrDefaultAsync(); if (lastSubmission != null && (DateTime.Now.ToUniversalTime() - lastSubmission.CreatedAt).TotalSeconds < 5) { throw new TooManyRequestsException("Cannot submit twice between 5 seconds."); } var submission = new Submission { UserId = Accessor.HttpContext.User.GetSubjectId(), ProblemId = dto.ProblemId.GetValueOrDefault(), Program = dto.Program, Verdict = Verdict.Pending, Hidden = DateTime.Now.ToUniversalTime() < contest.BeginTime, Time = null, Memory = null, FailedOn = null, Score = null, Progress = null, Message = null, JudgedBy = null, JudgedAt = null }; await Context.Submissions.AddAsync(submission); await Context.SaveChangesAsync(); _queue.EnqueueTask(new JobRequestMessage(JobType.JudgeSubmission, submission.Id, 1)); await Context.Entry(submission).Reference(s => s.User).LoadAsync(); var result = new SubmissionInfoDto(submission, true); await LogInformation($"CreateSubmission Id={result.Id} ProblemId={result.ProblemId}" + $" ContestantId={user.ContestantId} Language={result.Language}"); return(result); }
public async Task <ActionResult <SubmissionInfoDto> > CreateSubmission(SubmissionCreateDto dto) { try { return(Ok(await _service.CreateSubmissionAsync(dto))); } catch (ValidationException e) { return(BadRequest(e.Message)); } catch (UnauthorizedAccessException e) { return(Unauthorized(e.Message)); } catch (TooManyRequestsException e) { return(StatusCode(StatusCodes.Status429TooManyRequests, e.Message)); } }
private async Task <Contest> ValidateSubmissionCreateDtoAsync(SubmissionCreateDto dto) { var problem = await Context.Problems.FindAsync(dto.ProblemId); if (problem is null) { throw new ValidationException("Invalid problem ID."); } var user = await Manager.GetUserAsync(Accessor.HttpContext.User); var contest = await Context.Contests.FindAsync(problem.ContestId); var registered = await Context.Registrations .AnyAsync(r => r.ContestId == contest.Id && r.UserId == user.Id); if (await Manager.IsInRoleAsync(user, ApplicationRoles.Administrator) || await Manager.IsInRoleAsync(user, ApplicationRoles.ContestManager)) { // Administrator and contest manager can submit to any problem. } else if (DateTime.Now.ToUniversalTime() < contest.BeginTime) { throw new UnauthorizedAccessException("Cannot submit until contest has begun."); } else if (DateTime.Now.ToUniversalTime() < contest.EndTime && !registered) { if (contest.IsPublic) { // Automatically register for user if it is submitting during contest. var registration = new Registration { UserId = user.Id, ContestId = contest.Id, IsParticipant = true, IsContestManager = false, Statistics = new List <RegistrationProblemStatistics>() }; await Context.Registrations.AddAsync(registration); await Context.SaveChangesAsync(); } else { throw new UnauthorizedAccessException("Unregistered user cannot submit until contest has ended."); } } switch (problem.Type) { case ProblemType.Ordinary: if (dto.Program.Language == Language.LabArchive) { throw new ValidationException("Ordinary problem does not accept this language.."); } else if (!Regex.IsMatch(dto.Program.Code, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None)) { throw new ValidationException("Invalid program code."); } break; case ProblemType.TestKitLab: throw new ValidationException("Cannot submit testkit lab problems through this API."); default: throw new ArgumentOutOfRangeException(); } return(contest); }