public async Task <IActionResult> SetPassword(string username, SetPasswordModel model) { if (!ModelState.IsValid) { return(View(model)); } var user = await GetUserAsync(); if (!user.HasUserName(username)) { return(NotFound()); } var addPasswordResult = await UserManager.AddPasswordAsync(user, model.NewPassword); if (!addPasswordResult.Succeeded) { return(ViewWithError(addPasswordResult, model)); } await SignInManager.SignInAsync(user, isPersistent : false); await HttpContext.AuditAsync("set password", user.Id.ToString()); StatusMessage = "Your password has been set."; return(RedirectToAction(nameof(SetPassword))); }
public async Task <IActionResult> ImportResult([RPBinder] IRegisterProvider provider) { if (provider == null || !provider.JuryOrContestant) { return(NotFound()); } var context = CreateRegisterProviderContext(); if (!await provider.IsAvailableAsync(context)) { return(BadRequest()); } ViewBag.Provider = provider; ViewBag.Context = context; var model = await provider.CreateInputModelAsync(context); await provider.ReadAsync(model, this); await provider.ValidateAsync(context, model, ModelState); if (ModelState.IsValid) { var output = await provider.ExecuteAsync(context, model); await HttpContext.AuditAsync("import", null, "via " + provider.Name); return(Window("ImportResult", output)); } else { // something got wrong, re-display the form. return(Window(model)); } }
public async Task <IActionResult> Apply(int cid, int rid, [FromServices] IJudgingStore judgings) { var rej = await Store.FindAsync(cid, rid); if (rej == null || rej.EndTime != null) { return(NotFound()); } var pending = await judgings.CountAsync(j => j.RejudgeId == rid && (j.Status == Verdict.Pending || j.Status == Verdict.Running)); if (pending > 0) { StatusMessage = "Error some submissions are not ready."; return(RedirectToAction(nameof(Detail))); } await Store.ApplyAsync(rej, int.Parse(User.GetUserId())); await HttpContext.AuditAsync("applied", $"{rid}"); await Mediator.RefreshScoreboardCache(Contest); StatusMessage = "Rejudging applied. Scoreboard cache will be refreshed."; return(RedirectToAction(nameof(Detail))); }
public async Task <IActionResult> Delete(int cid, int pid, bool post = true) { var prob = Problems.SingleOrDefault(p => p.ProblemId == pid); if (prob == null) { return(NotFound()); } await Store.DeleteAsync(prob); await HttpContext.AuditAsync("detached", $"{pid}"); await Notifier.Delete(cid, prob); var newprobs = await Store.ListAsync(cid); foreach (var @new in newprobs) { if (@new.Rank >= prob.Rank) { await Notifier.Update(cid, @new); } } StatusMessage = $"Contest problem {prob.ShortName} has been deleted."; return(RedirectToAction("Home", "Jury")); }
public async Task <IActionResult> Edit(string execid, ExecutableEditModel model) { var exec = await Store.FindAsync(execid); if (exec == null) { return(NotFound()); } if (!"compile,compare,run".Split(',').Contains(model.Type)) { return(BadRequest()); } if (model.Archive != null) { (exec.ZipFile, exec.Md5sum) = await model.Archive.ReadAsync(); } exec.ZipSize = exec.ZipFile.Length; exec.Description = model.Description ?? execid; exec.Type = model.Type; await Store.UpdateAsync(exec); await HttpContext.AuditAsync("updated", execid); return(RedirectToAction(nameof(Detail), new { execid })); }
public async Task <IActionResult> SendVerificationEmail( [FromRoute] string username, IndexViewModel model, [FromServices] IEmailSender emailSender) { if (!ModelState.IsValid) { return(View(model)); } var user = await GetUserAsync(); if (!user.HasUserName(username)) { return(NotFound()); } var code = await UserManager.GenerateEmailConfirmationTokenAsync(user); var callbackUrl = Url.Action( action: "ConfirmEmail", controller: "Sign", values: new { userId = $"{user.Id}", code, area = "Account" }, protocol: Request.Scheme); await emailSender.SendEmailConfirmationAsync(user.Email, callbackUrl); StatusMessage = "Verification email sent. Please check your email."; await HttpContext.AuditAsync("send verification email", user.Id.ToString()); return(RedirectToAction(nameof(Edit))); }
public async Task <IActionResult> Add(bool isgym, [FromServices] RoleManager <Role> roleManager, [FromServices] UserManager userManager, [FromServices] IContestStore store) { var c = await store.CreateAsync(new Contest { IsPublic = false, RegisterDefaultCategory = 0, ShortName = "DOMjudge", Name = "Round 1", Gym = isgym, }); await HttpContext.AuditAsync("added", $"{c.ContestId}"); int cid = c.ContestId; var roleName = $"JuryOfContest{cid}"; var result = await roleManager.CreateAsync(new Role(roleName) { ContestId = cid }); if (!result.Succeeded) { return(Json(result)); } var firstUser = await userManager.GetUserAsync(User); var roleAttach = await userManager.AddToRoleAsync(firstUser, roleName); if (!roleAttach.Succeeded) { return(Json(roleAttach)); } return(RedirectToAction("Home", "Jury", new { area = "Contest", cid })); }
public async Task <IActionResult> Config( ConfigureEditModel models, [FromServices] IConfigurationRegistry registry) { var items = await registry.ListPublicAsync(); foreach (var item in items) { if (!models.Config.ContainsKey(item.Name) || models.Config[item.Name] == null) { continue; } var newVal = models.Config[item.Name]; if (item.Type == "string") { newVal = newVal.ToJson(); } if (newVal == item.Value) { continue; } await registry.UpdateValueAsync(item.Name, newVal); await HttpContext.AuditAsync("updated", item.Name, "from " + item.Value); } StatusMessage = "Configurations saved successfully."; return(RedirectToAction(nameof(Config))); }
public async Task <IActionResult> Assign( int cid, JuryAssignModel model, [FromServices] UserManager userManager) { var user = await userManager.FindByNameAsync(model.UserName); if (user == null) { StatusMessage = "Error user not found."; } else { var result = await userManager.AddToRoleAsync(user, $"JuryOfContest{cid}"); if (result.Succeeded) { StatusMessage = $"Jury role of user {user.UserName} assigned."; await HttpContext.AuditAsync("assigned jury", $"{user.Id}", $"c{cid}"); } else { StatusMessage = "Error " + string.Join('\n', result.Errors.Select(e => e.Description)); } } return(RedirectToAction(nameof(Home))); }
public async Task <IActionResult> Edit(int catid, CategoryModel model) { var cat = await Context.FindCategoryAsync(catid, false); if (cat == null) { return(NotFound()); } if (!cat.ContestId.HasValue) { return(GoBackHome("Please edit the global category in dashboard.", "List", "JuryCategories")); } if (!ModelState.IsValid) { return(View(model)); } cat.Color = model.Color; cat.IsPublic = model.IsPublic; cat.Name = model.Name; cat.IsEligible = model.IsEligible; cat.SortOrder = model.SortOrder; await Context.UpdateCategoryAsync(cat); await HttpContext.AuditAsync("updated", $"{catid}"); return(RedirectToAction(nameof(Detail), new { catid })); }
public async Task <IActionResult> ForgotPassword(ForgotPasswordModel model) { if (!ModelState.IsValid) { return(View(model)); } var user = await UserManager.FindByEmailAsync(model.Email); if (user == null || !user.EmailConfirmed) { // Don't reveal that the user does not exist or is not confirmed return(RedirectToAction(nameof(ForgotPasswordConfirmation))); } var code = await UserManager.GeneratePasswordResetTokenAsync(user); var callbackUrl = Url.Action( action: "ResetPassword", controller: "Sign", values: new { userId = $"{user.Id}", code, area = "Account" }, protocol: Request.Scheme); await EmailSender.SendEmailAsync( email : model.Email, subject : "Reset Password", message : $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>"); await HttpContext.AuditAsync( "sent forgot password email", user.Id.ToString(), $"at {HttpContext.Connection.RemoteIpAddress}"); return(RedirectToAction(nameof(ForgotPasswordConfirmation))); }
public async Task <IActionResult> ResetPassword(ResetPasswordModel model) { if (!ModelState.IsValid) { return(View(model)); } var user = await UserManager.FindByEmailAsync(model.Email); // Don't reveal that the user does not exist if (user == null) { return(RedirectToAction(nameof(ResetPasswordConfirmation))); } var result = await UserManager.ResetPasswordAsync(user, model.Code, model.Password); if (!result.Succeeded) { return(ErrorView(result, model)); } await HttpContext.AuditAsync( "reset password", user.Id.ToString(), $"at {HttpContext.Connection.RemoteIpAddress}"); return(RedirectToAction(nameof(ResetPasswordConfirmation))); }
public async Task <IActionResult> Apply(int rejudgingid) { var rej = await Context.FindAsync(rejudgingid); if (rej == null || rej.EndTime != null) { return(NotFound()); } var pending = await Context.CountJudgingsAsync( j => j.RejudgingId == rejudgingid && (j.Status == Verdict.Pending || j.Status == Verdict.Running)); if (pending > 0) { StatusMessage = "Error some submissions are not ready."; return(RedirectToAction(nameof(Detail))); } await Context.ApplyAsync(rej, int.Parse(User.GetUserId())); await HttpContext.AuditAsync("applied", $"{rejudgingid}"); await Mediator.Publish(new ScoreboardRefreshEvent(Context)); StatusMessage = "Rejudging applied. Scoreboard cache will be refreshed."; return(RedirectToAction(nameof(Detail))); }
public async Task <IActionResult> ChangeTime( [FromRoute] int cid, [FromForm] DateTimeOffset?start_time) { var now = DateTimeOffset.Now; var newTime = start_time ?? (now + TimeSpan.FromSeconds(30)); var oldtime = Contest.StartTime.Value; if (Contest.GetState(now) >= Xylab.Contesting.Entities.ContestState.Started) { return(StatusCode(403)); // contest is started } if (newTime < now + TimeSpan.FromSeconds(29.5)) { return(StatusCode(403)); // new start time is in the past or within 30s } if (now + TimeSpan.FromSeconds(30) > oldtime) { return(StatusCode(403)); // left time } await Context.UpdateContestAsync( _ => new() { StartTime = newTime, }); await HttpContext.AuditAsync("changed time", $"{Contest.Id}", "via ccs-api"); return(Ok()); }
/// <summary> /// Finish the judging pipe, persist into database, /// create the events and notify scoreboard. /// </summary> private async Task FinishJudging(Judging j, int?cid, int pid, int uid, DateTimeOffset subtime) { if (cid == 0) { cid = null; } await Judgings.UpdateAsync(j); await HttpContext.AuditAsync( AuditlogType.Judging, cid, j.Server, "judged", $"{j.JudgingId}", $"{j.Status}"); if (cid.HasValue && j.Active) { await HttpContext.RequestServices .GetRequiredService <MediatR.IMediator>() .JudgingFinished(cid.Value, subtime, pid, uid, j); } if (j.Active) { await HttpContext.RequestServices .GetRequiredService <ISubmissionStore>() .UpdateStatisticsAsync(cid ?? 0, uid, pid, j.Status == Verdict.Accepted); } Telemetry.TrackDependency( dependencyTypeName: "JudgeHost", dependencyName: j.Server, data: $"j{j.JudgingId} judged " + j.Status, startTime: j.StartTime ?? DateTimeOffset.Now, duration: (j.StopTime - j.StartTime) ?? TimeSpan.Zero, success: j.Status != Verdict.UndefinedError); }
public async Task <IActionResult> ExternalLoginConfirmation(ExternalLoginModel model, string returnUrl = null) { if (await Configurations.GetBooleanAsync("enable_register") == false) { return(ExternalRegisterClosed()); } var check = new RegisterNotification(model.Username); await Mediator.Publish(check); if (check.Failed) { ModelState.AddModelError("xys::custom_rule", "The username is invalid. Please change another one."); } if (!ModelState.IsValid) { ViewData["ReturnUrl"] = returnUrl; return(View(nameof(ExternalLogin), model)); } // Get the information about the user from the external login provider var info = await SignInManager.GetExternalLoginInfoAsync(); if (info == null) { return(Message( title: "External login", message: "Error loading external login information during confirmation.", type: BootstrapColor.danger)); } var user = UserManager.CreateEmpty(model.Username); user.Email = model.Email; user.RegisterTime = DateTimeOffset.Now; var result = await UserManager.CreateAsync(user); if (result.Succeeded) { result = await UserManager.AddLoginAsync(user, info); } if (result.Succeeded) { await SignInManager.SignInAsync(user, isPersistent : false); await HttpContext.AuditAsync( "registered", user.Id.ToString(), $"at {HttpContext.Connection.RemoteIpAddress} via {info.LoginProvider}"); return(RedirectToLocal(returnUrl)); } else { return(ErrorView(result, model, nameof(ExternalLogin))); } }
public async Task <IActionResult> Add(int kind) { var c = await _store.CreateAndAssignAsync(kind, User); await HttpContext.AuditAsync("added", $"{c.Id}"); return(RedirectToAction("Home", "Jury", new { area = "Contest", cid = c.Id })); }
public async Task <IActionResult> Clarification( string op, AddClarificationModel model, [FromServices] IClarificationStore clars) { var(cid, teamid) = (Contest.ContestId, Team.TeamId); int repl = 0; if (op != "add" && !int.TryParse(op, out repl)) { return(NotFound()); } var replit = await clars.FindAsync(cid, repl); if (repl != 0 && replit == null) { ModelState.AddModelError("xys::replyto", "The clarification replied to is not found."); } if (string.IsNullOrWhiteSpace(model.Body)) { ModelState.AddModelError("xys::empty", "No empty clarification"); } var usage = ClarCategories.SingleOrDefault(cp => model.Type == cp.Item1); if (usage.Item1 == null) { ModelState.AddModelError("xys::error_cate", "The category specified is wrong."); } if (!ModelState.IsValid) { StatusMessage = string.Join('\n', ModelState.Values .SelectMany(m => m.Errors) .Select(e => e.ErrorMessage)); } else { int id = await clars.SendAsync( new Clarification { Body = model.Body, SubmitTime = DateTimeOffset.Now, ContestId = cid, Sender = teamid, ResponseToId = model.ReplyTo, ProblemId = usage.Item3, Category = usage.Item2, }); await HttpContext.AuditAsync("added", $"{id}"); StatusMessage = "Clarification sent to the jury."; } return(RedirectToAction(nameof(Home))); }
public async Task <IActionResult> Edit(string username, IndexViewModel model) { if (!ModelState.IsValid) { return(View(model)); } try { var user = await GetUserAsync(); if (!user.HasUserName(username)) { return(NotFound()); } var email = user.Email; if (model.Email != email) { var setEmailResult = await UserManager.SetEmailAsync(user, model.Email); if (!setEmailResult.Succeeded) { throw new ApplicationException( $"Unexpected error occurred setting email for user with ID '{user.Id}'. " + (setEmailResult.Errors.FirstOrDefault()?.Description ?? "")); } } if (string.IsNullOrEmpty(model.NickName)) { model.NickName = null; } if (string.IsNullOrEmpty(model.Plan)) { model.Plan = null; } user.NickName = model.NickName; user.Plan = model.Plan; user.SubscribeNews = model.SubscribeNews; await UserManager.UpdateAsync(user); await SignInManager.RefreshSignInAsync(user); await HttpContext.AuditAsync("update profile", user.Id.ToString()); StatusMessage = "Your profile has been updated"; } catch (ApplicationException ex) { StatusMessage = ex.Message; } return(RedirectToAction(nameof(Edit))); }
public async Task <IActionResult> LockoutTemporaryConfirmation() { await Context.LockOutTemporaryAsync(UserManager); await HttpContext.AuditAsync("lockout", "temporary accounts"); StatusMessage = "Lockout finished."; return(RedirectToAction(nameof(List))); }
public async Task <IActionResult> Score(int pid, TestcaseScoreModel model) { int cnt = await Store.BatchScoreAsync(pid, model.Lower, model.Upper, model.Score); await HttpContext.AuditAsync("scored", $"{model.Lower} ~ {model.Upper}"); StatusMessage = $"Score set, {cnt} testcases affected."; return(RedirectToAction(nameof(Testcases))); }
public async Task <IActionResult> Export( [FromServices] IExportProvider export) { await HttpContext.AuditAsync("export", $"{Problem.ProblemId}"); var(stream, mimeType, fileName) = await export.ExportAsync(Problem); return(File(stream, mimeType, fileName, false)); }
public async Task <IActionResult> Register(RegisterModel model, string returnUrl = null) { if (await Configurations.GetBooleanAsync("enable_register") == false) { return(RegisterClosed()); } var check = new RegisterNotification(model.UserName); await Mediator.Publish(check); if (check.Failed) { ModelState.AddModelError("xys::custom_rule", "The username is invalid. Please change another one."); } ViewData["ReturnUrl"] = returnUrl; if (!ModelState.IsValid) { return(View(model)); } var user = UserManager.CreateEmpty(model.UserName); user.Email = model.Email; user.RegisterTime = DateTimeOffset.Now; var result = await UserManager.CreateAsync(user, model.Password); if (!result.Succeeded) { return(ErrorView(result, model)); } if (user.Id == 1) { await UserManager.AddToRoleAsync(user, "Administrator"); } var code = await UserManager.GenerateEmailConfirmationTokenAsync(user); var callbackUrl = Url.Action( action: "ConfirmEmail", controller: "Sign", values: new { userId = $"{user.Id}", code, area = "Account" }, protocol: Request.Scheme); await EmailSender.SendEmailConfirmationAsync(model.Email, callbackUrl); await SignInManager.SignInAsync(user, isPersistent : false); await HttpContext.AuditAsync( "registered", user.Id.ToString(), $"at {HttpContext.Connection.RemoteIpAddress}"); return(RedirectToLocal(returnUrl)); }
public async Task <IActionResult> Description(JuryMarkdownModel model) { model.Markdown ??= ""; await Context.SetReadmeAsync(model.Markdown); await HttpContext.AuditAsync("updated", $"{Contest.Id}", "description"); return(View(model)); }
public async Task <IActionResult> RefreshCacheConfirmation() { await Mediator.Publish(new ScoreboardRefreshEvent(Context)); StatusMessage = "Scoreboard cache has been refreshed."; await HttpContext.AuditAsync("refresh scoreboard cache", Contest.Id.ToString()); return(RedirectToAction(nameof(Home))); }
public async Task <IActionResult> RefreshCache() { await Mediator.RefreshScoreboardCache(Contest); StatusMessage = "Scoreboard cache has been refreshed."; await HttpContext.AuditAsync("refresh cache", null); return(RedirectToAction(nameof(Home))); }
public async Task <IActionResult> ResetEventFeed(int cid) { await Notifier.ResetAsync(cid); await HttpContext.AuditAsync("reset event", null); StatusMessage = "Event feed reset."; return(RedirectToAction(nameof(Home))); }
public async Task <IActionResult> Send(AddClarificationModel model) { // validate the model if (string.IsNullOrWhiteSpace(model.Body)) { ModelState.AddModelError("xys::clar_empty", "Clarification body cannot be empty."); } // reply clar Clarification replyTo = null; if (model.ReplyTo.HasValue) { replyTo = await Context.FindClarificationAsync(model.ReplyTo.Value); if (replyTo == null) { ModelState.AddModelError("xys::clar_not_found", "The clarification replied to not found."); } } // determine category var probs = await Context.ListProblemsAsync(); var usage = probs.ClarificationCategories.FirstOrDefault(cp => model.Type == cp.Item1); if (usage.Item1 == null) { ModelState.AddModelError("xys::error_cate", "The category specified is wrong."); } if (!ModelState.IsValid) { return(View(model)); } var clar = await Context.ClarifyAsync( replyTo : replyTo, clar : new Clarification { Body = model.Body, SubmitTime = DateTimeOffset.Now, ContestId = Contest.Id, JuryMember = User.GetUserName(), Sender = null, ResponseToId = model.ReplyTo, Recipient = model.TeamTo == 0 ? default(int?) : model.TeamTo, ProblemId = usage.Item3, Answered = true, Category = usage.Item2, }); await HttpContext.AuditAsync("added", $"{clar.Id}"); StatusMessage = $"Clarification {clar.Id} has been sent."; return(RedirectToAction(nameof(Detail), new { clarid = clar.Id })); }
public async Task <IActionResult> Add(JuryAddTeamModel model) { var users = new HashSet <IUser>(); if (model.UserName != null) { var userNames = model.UserName.Split(',', StringSplitOptions.RemoveEmptyEntries); foreach (var userName in userNames) { var user = await UserManager.FindByNameAsync(userName.Trim()); if (user == null) { ModelState.AddModelError("xys::no_user", $"No such user {userName.Trim()}."); } else if ((await Context.FindMemberByUserAsync(user.Id)) != null) { ModelState.AddModelError("xys::duplicate_user", "Duplicate user."); } else { users.Add(user); } } } var affiliations = await Context.ListAffiliationsAsync(false); if (!affiliations.TryGetValue(model.AffiliationId, out _)) { ModelState.AddModelError("xys::no_aff", "No such affiliation."); } if (!ModelState.IsValid) { return(Window(model)); } var team = await Context.CreateTeamAsync( users : users.Count > 0?users : null, team : new Team { AffiliationId = model.AffiliationId, Status = 1, CategoryId = model.CategoryId, ContestId = Contest.Id, TeamName = model.TeamName, }); await HttpContext.AuditAsync("added", $"{team.TeamId}"); return(Message( title: "Add team", message: $"Team {model.TeamName} (t{team.TeamId}) added.", type: BootstrapColor.success)); }
public async Task <IActionResult> ResetEventFeedConfirmation() { if (!Contest.Settings.EventAvailable || !InAjax) { return(BadRequest()); } await HttpContext.AuditAsync("reset event requested", Contest.Id.ToString()); return(new ResetEventResult()); }