package org.iatoki.judgels.uriel.controllers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.iatoki.judgels.jophiel.Jophiel;
import org.iatoki.judgels.play.InternalLink;
import org.iatoki.judgels.play.LazyHtml;
import org.iatoki.judgels.play.Page;
import org.iatoki.judgels.play.controllers.AbstractJudgelsController;
import org.iatoki.judgels.play.views.html.layouts.heading3Layout;
import org.iatoki.judgels.uriel.Contest;
import org.iatoki.judgels.uriel.ContestNotFoundException;
import org.iatoki.judgels.uriel.ContestPermission;
import org.iatoki.judgels.uriel.ContestPermissions;
import org.iatoki.judgels.uriel.ContestSupervisor;
import org.iatoki.judgels.uriel.ContestSupervisorNotFoundException;
import org.iatoki.judgels.uriel.controllers.securities.Authenticated;
import org.iatoki.judgels.uriel.controllers.securities.HasRole;
import org.iatoki.judgels.uriel.controllers.securities.LoggedIn;
import org.iatoki.judgels.uriel.forms.ContestSupervisorCreateForm;
import org.iatoki.judgels.uriel.forms.ContestSupervisorUpdateForm;
import org.iatoki.judgels.uriel.services.ContestService;
import org.iatoki.judgels.uriel.services.ContestSupervisorService;
import org.iatoki.judgels.uriel.services.UserService;
import org.iatoki.judgels.uriel.views.html.contest.supervisor.listCreateSupervisorsView;
import org.iatoki.judgels.uriel.views.html.contest.supervisor.updateSupervisorView;
import play.data.Form;
import play.db.jpa.Transactional;
import play.filters.csrf.AddCSRFToken;
import play.filters.csrf.RequireCSRFCheck;
import play.i18n.Messages;
import play.mvc.Http;
import play.mvc.Result;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Collectors;
@Authenticated(value = {LoggedIn.class, HasRole.class})
@Singleton
@Named
public class ContestSupervisorController extends AbstractJudgelsController {
private static final long PAGE_SIZE = 20;
private final Jophiel jophiel;
private final ContestService contestService;
private final ContestSupervisorService contestSupervisorService;
private final UserService userRoleService;
@Inject
public ContestSupervisorController(Jophiel jophiel, ContestService contestService, ContestSupervisorService contestSupervisorService, UserService userRoleService) {
this.jophiel = jophiel;
this.contestService = contestService;
this.contestSupervisorService = contestSupervisorService;
this.userRoleService = userRoleService;
}
@Transactional(readOnly = true)
@AddCSRFToken
public Result viewSupervisors(long contestId) throws ContestNotFoundException {
return listCreateSupervisors(contestId, 0, "id", "asc", "");
}
@Transactional(readOnly = true)
@AddCSRFToken
public Result listCreateSupervisors(long contestId, long pageIndex, String orderBy, String orderDir, String filterString) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (ContestControllerUtils.getInstance().isSupervisorOrAbove(contest)) {
Page<ContestSupervisor> contestSupervisorPage = contestSupervisorService.pageContestSupervisorsByContestJid(contest.getJid(), pageIndex, PAGE_SIZE, orderBy, orderDir, filterString);
boolean canUpdate = isAllowedToManageSupervisors(contest);
ContestSupervisorCreateForm contestSupervisorCreateForm = new ContestSupervisorCreateForm();
contestSupervisorCreateForm.isAllowedAll = true;
contestSupervisorCreateForm.allowedPermissions = Lists.newArrayList(ContestPermissions.values()).stream().collect(Collectors.toMap(p -> p.name(), p -> p.name()));
Form<ContestSupervisorCreateForm> form = Form.form(ContestSupervisorCreateForm.class).fill(contestSupervisorCreateForm);
return showListCreateSupervisor(contestSupervisorPage, pageIndex, orderBy, orderDir, filterString, canUpdate, form, contest);
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional
@RequireCSRFCheck
public Result postCreateSupervisor(long contestId, long pageIndex, String orderBy, String orderDir, String filterString) throws ContestNotFoundException {
Contest contest = contestService.findContestById(contestId);
if (isAllowedToManageSupervisors(contest)) {
Form<ContestSupervisorCreateForm> form = Form.form(ContestSupervisorCreateForm.class).bindFromRequest();
if (form.hasErrors() || form.hasGlobalErrors()) {
Page<ContestSupervisor> contestSupervisorPage = contestSupervisorService.pageContestSupervisorsByContestJid(contest.getJid(), pageIndex, PAGE_SIZE, orderBy, orderDir, filterString);
boolean canUpdate = isAllowedToManageSupervisors(contest);
return showListCreateSupervisor(contestSupervisorPage, pageIndex, orderBy, orderDir, filterString, canUpdate, form, contest);
} else {
ContestSupervisorCreateForm contestSupervisorCreateForm = form.get();
try {
String userJid = jophiel.verifyUsername(contestSupervisorCreateForm.username);
if ((userJid != null) && (!contestSupervisorService.isContestSupervisorInContestByUserJid(contest.getJid(), userJid))) {
userRoleService.upsertUserFromJophielUserJid(userJid);
ContestPermission contestPermission;
if (contestSupervisorCreateForm.allowedPermissions != null) {
contestPermission = new ContestPermission(ImmutableSet.of(), contestSupervisorCreateForm.isAllowedAll);
} else {
contestPermission = new ContestPermission(contestSupervisorCreateForm.allowedPermissions.keySet(), contestSupervisorCreateForm.isAllowedAll);
}
contestSupervisorService.createContestSupervisor(contest.getId(), userJid, contestPermission);
ControllerUtils.getInstance().addActivityLog("Add " + contestSupervisorCreateForm.username + " as supervisor in contest " + contest.getName() + ".");
return redirect(routes.ContestSupervisorController.viewSupervisors(contest.getId()));
} else {
form.reject("error.supervisor.create.userJid.invalid");
Page<ContestSupervisor> contestSupervisorPage = contestSupervisorService.pageContestSupervisorsByContestJid(contest.getJid(), pageIndex, PAGE_SIZE, orderBy, orderDir, filterString);
boolean canUpdate = isAllowedToManageSupervisors(contest);
return showListCreateSupervisor(contestSupervisorPage, pageIndex, orderBy, orderDir, filterString, canUpdate, form, contest);
}
} catch (IOException e) {
form.reject("error.supervisor.create.userJid.invalid");
Page<ContestSupervisor> contestSupervisorPage = contestSupervisorService.pageContestSupervisorsByContestJid(contest.getJid(), pageIndex, PAGE_SIZE, orderBy, orderDir, filterString);
boolean canUpdate = isAllowedToManageSupervisors(contest);
return showListCreateSupervisor(contestSupervisorPage, pageIndex, orderBy, orderDir, filterString, canUpdate, form, contest);
}
}
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional(readOnly = true)
@AddCSRFToken
public Result updateSupervisor(long contestId, long contestSupervisorId) throws ContestNotFoundException, ContestSupervisorNotFoundException {
Contest contest = contestService.findContestById(contestId);
ContestSupervisor contestSupervisor = contestSupervisorService.findContestSupervisorByContestSupervisorId(contestSupervisorId);
if (isAllowedToManageSupervisors(contest) && contestSupervisor.getContestJid().equals(contest.getJid())) {
ContestSupervisorUpdateForm contestSupervisorUpdateForm = new ContestSupervisorUpdateForm();
contestSupervisorUpdateForm.isAllowedAll = contestSupervisor.getContestPermission().isAllowedAll();
contestSupervisorUpdateForm.allowedPermissions = contestSupervisor.getContestPermission().getAllowedPermissions().stream().collect(Collectors.toMap(p -> p, p -> p));
Form<ContestSupervisorUpdateForm> form = Form.form(ContestSupervisorUpdateForm.class).fill(contestSupervisorUpdateForm);
ControllerUtils.getInstance().addActivityLog("Try to update supervisor " + contestSupervisor.getUserJid() + " in contest " + contest.getName() + " <a href=\"" + "http://" + Http.Context.current().request().host() + Http.Context.current().request().uri() + "\">link</a>.");
return showUpdateSupervisor(form, contest, contestSupervisor);
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
@Transactional
@RequireCSRFCheck
public Result postUpdateSupervisor(long contestId, long contestSupervisorId) throws ContestNotFoundException, ContestSupervisorNotFoundException {
Contest contest = contestService.findContestById(contestId);
ContestSupervisor contestSupervisor = contestSupervisorService.findContestSupervisorByContestSupervisorId(contestSupervisorId);
if (isAllowedToManageSupervisors(contest) && contestSupervisor.getContestJid().equals(contest.getJid())) {
Form<ContestSupervisorUpdateForm> form = Form.form(ContestSupervisorUpdateForm.class).bindFromRequest();
if (form.hasErrors() || form.hasGlobalErrors()) {
return showUpdateSupervisor(form, contest, contestSupervisor);
} else {
ContestSupervisorUpdateForm contestSupervisorUpdateForm = form.get();
ContestPermission contestPermission;
if (contestSupervisorUpdateForm.allowedPermissions == null) {
contestPermission = new ContestPermission(ImmutableSet.of(), contestSupervisorUpdateForm.isAllowedAll);
} else {
contestPermission = new ContestPermission(contestSupervisorUpdateForm.allowedPermissions.keySet(), contestSupervisorUpdateForm.isAllowedAll);
}
contestSupervisorService.updateContestSupervisor(contestSupervisor.getId(), contestPermission);
ControllerUtils.getInstance().addActivityLog("Update supervisor " + contestSupervisor.getUserJid() + " in contest " + contest.getName() + ".");
return redirect(routes.ContestSupervisorController.viewSupervisors(contest.getId()));
}
} else {
return ContestControllerUtils.getInstance().tryEnteringContest(contest);
}
}
private Result showListCreateSupervisor(Page<ContestSupervisor> contestSupervisorPage, long pageIndex, String orderBy, String orderDir, String filterString, boolean canUpdate, Form<ContestSupervisorCreateForm> form, Contest contest){
LazyHtml content = new LazyHtml(listCreateSupervisorsView.render(contest.getId(), contestSupervisorPage, pageIndex, orderBy, orderDir, filterString, canUpdate, form, jophiel.getAutoCompleteEndPoint()));
content.appendLayout(c -> heading3Layout.render(Messages.get("supervisor.list"), c));
ContestControllerUtils.getInstance().appendTabsLayout(content, contest);
ControllerUtils.getInstance().appendSidebarLayout(content);
appendBreadcrumbsLayout(content, contest,
new InternalLink(Messages.get("supervisor.list"), routes.ContestSupervisorController.viewSupervisors(contest.getId()))
);
ControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Supervisors");
ControllerUtils.getInstance().addActivityLog("List all supervisors in contest " + contest.getName() + " <a href=\"" + "http://" + Http.Context.current().request().host() + Http.Context.current().request().uri() + "\">link</a>.");
return ControllerUtils.getInstance().lazyOk(content);
}
private Result showUpdateSupervisor(Form<ContestSupervisorUpdateForm> form, Contest contest, ContestSupervisor contestSupervisor){
LazyHtml content = new LazyHtml(updateSupervisorView.render(contest.getId(), contestSupervisor.getId(), form));
content.appendLayout(c -> heading3Layout.render(Messages.get("supervisor.update"), c));
ContestControllerUtils.getInstance().appendTabsLayout(content, contest);
ControllerUtils.getInstance(). appendSidebarLayout(content);
appendBreadcrumbsLayout(content, contest,
new InternalLink(Messages.get("supervisor.update"), routes.ContestSupervisorController.updateSupervisor(contest.getId(), contestSupervisor.getId()))
);
ControllerUtils.getInstance().appendTemplateLayout(content, "Contest - Supervisor - Update");
return ControllerUtils.getInstance().lazyOk(content);
}
private void appendBreadcrumbsLayout(LazyHtml content, Contest contest, InternalLink... lastLinks) {
ControllerUtils.getInstance().appendBreadcrumbsLayout(content,
ContestControllerUtils.getInstance().getContestBreadcrumbsBuilder(contest)
.add(new InternalLink(Messages.get("supervisor.supervisors"), routes.ContestController.jumpToSupervisors(contest.getId())))
.addAll(Arrays.asList(lastLinks))
.build()
);
}
private boolean isAllowedToManageSupervisors(Contest contest) {
return ControllerUtils.getInstance().isAdmin() || ContestControllerUtils.getInstance().isManager(contest);
}
}