diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle index 60a6ea0..7411fe3 100644 Binary files a/src/main/bundles/prod.bundle and b/src/main/bundles/prod.bundle differ diff --git a/src/main/java/com/primefactorsolutions/model/Submission.java b/src/main/java/com/primefactorsolutions/model/Submission.java index 67b151b..2102dd3 100644 --- a/src/main/java/com/primefactorsolutions/model/Submission.java +++ b/src/main/java/com/primefactorsolutions/model/Submission.java @@ -1,7 +1,5 @@ package com.primefactorsolutions.model; -import io.hypersistence.utils.hibernate.type.json.JsonType; -import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Lob; import jakarta.persistence.ManyToOne; @@ -9,9 +7,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.hibernate.annotations.Type; - -import java.util.Map; @Entity @Data @@ -25,9 +20,7 @@ public class Submission extends BaseEntity { @Lob private String text; - @Type(JsonType.class) - @Column(columnDefinition = "json") - private Map results; + private String output; private SubmissionStatus submissionStatus; diff --git a/src/main/java/com/primefactorsolutions/service/ExamService.java b/src/main/java/com/primefactorsolutions/service/ExamService.java index d0f4a84..731f144 100644 --- a/src/main/java/com/primefactorsolutions/service/ExamService.java +++ b/src/main/java/com/primefactorsolutions/service/ExamService.java @@ -12,7 +12,6 @@ import org.springframework.stereotype.Service; import java.time.Instant; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.stream.Collectors; @@ -32,7 +31,7 @@ public class ExamService { public void sendEmail(final Exam exam) { try { - final String evaluationLink = String.format("https://careers.primefactorsolutions.com/evaluation/%s", + final String evaluationLink = String.format("https://careers.primefactorsolutions.com/candidate-exam/%s", exam.getId()); final SimpleMailMessage message = new SimpleMailMessage(); message.setFrom("no-reply@primefactorsolutions.com"); @@ -95,7 +94,7 @@ public class ExamService { .findFirst(); if (submissionToReturn.isEmpty()) { - final Submission result = new Submission(firstQuestion, firstQuestion.getContent(), Map.of(), + final Submission result = new Submission(firstQuestion, firstQuestion.getContent(), null, SubmissionStatus.FAIL, exam); exam.getSubmissions().add(result); } @@ -125,7 +124,7 @@ public class ExamService { .findFirst(); if (submissionToReturn.isEmpty()) { - final Submission result = new Submission(nextQuestion, nextQuestion.getContent(), Map.of(), + final Submission result = new Submission(nextQuestion, nextQuestion.getContent(), null, SubmissionStatus.FAIL, exam); exam.getSubmissions().add(result); } diff --git a/src/main/java/com/primefactorsolutions/views/EvaluationView.java b/src/main/java/com/primefactorsolutions/views/CandidateExamView.java similarity index 98% rename from src/main/java/com/primefactorsolutions/views/EvaluationView.java rename to src/main/java/com/primefactorsolutions/views/CandidateExamView.java index 9e60275..2d88173 100644 --- a/src/main/java/com/primefactorsolutions/views/EvaluationView.java +++ b/src/main/java/com/primefactorsolutions/views/CandidateExamView.java @@ -54,10 +54,10 @@ import java.util.stream.Collectors; @PageTitle("Evaluacion") @SpringComponent @Scope("prototype") -@Route(value = "/evaluation", layout = MainLayout.class) +@Route(value = "/candidate-exam", layout = MainLayout.class) @AnonymousAllowed @Slf4j -public class EvaluationView extends Main implements HasUrlParameter { +public class CandidateExamView extends Main implements HasUrlParameter { private final CompilerService compilerService; private final ExamService examService; @@ -83,7 +83,7 @@ public class EvaluationView extends Main implements HasUrlParameter { private H3 questionTitle = null; private Text questionDescription = null; - public EvaluationView(final CompilerService compilerService, final ExamService examService) { + public CandidateExamView(final CompilerService compilerService, final ExamService examService) { this.compilerService = compilerService; this.examService = examService; diff --git a/src/main/java/com/primefactorsolutions/views/MainLayout.java b/src/main/java/com/primefactorsolutions/views/MainLayout.java index b6f0ea4..a759368 100644 --- a/src/main/java/com/primefactorsolutions/views/MainLayout.java +++ b/src/main/java/com/primefactorsolutions/views/MainLayout.java @@ -11,6 +11,7 @@ import com.primefactorsolutions.views.timeoff.TimeOffRequestsListView; import com.primefactorsolutions.views.timeoff.TimeOffSummaryListView; import com.primefactorsolutions.views.timesheet.TimesheetListView; import com.primefactorsolutions.views.timesheet.TimesheetReportView; +import com.primefactorsolutions.views.util.AuthUtils; import com.vaadin.flow.component.Component; import com.vaadin.flow.component.Text; import com.vaadin.flow.component.applayout.AppLayout; @@ -39,8 +40,6 @@ import org.vaadin.lineawesome.LineAwesomeIcon; import java.util.UUID; -import static com.primefactorsolutions.views.util.AuthUtils.isAdmin; - /** * The main view is a top-level placeholder for other views. */ @@ -137,60 +136,63 @@ public class MainLayout extends AppLayout { private SideNav createNavigation() { final SideNav nav = new SideNav(); - nav.addItem(new SideNavItem("Home", MainView.class, LineAwesomeIcon.HOME_SOLID.create())); - if (isAdmin(authContext)) { - SideNavItem admin = new SideNavItem("Admin"); - admin.setPrefixComponent(LineAwesomeIcon.BUILDING.create()); - admin.addItem(new SideNavItem("Calendario", TimeOffListView.class, - LineAwesomeIcon.CALENDAR.create())); - nav.addItem(admin); + if (AuthUtils.isUser(authContext)) { + nav.addItem(new SideNavItem("Home", MainView.class, LineAwesomeIcon.HOME_SOLID.create())); - SideNavItem recruiting = new SideNavItem("Recruiting"); - recruiting.setPrefixComponent(LineAwesomeIcon.BUSINESS_TIME_SOLID.create()); - recruiting.addItem(new SideNavItem("Exams", ExamsListView.class, - LineAwesomeIcon.RIBBON_SOLID.create())); - recruiting.addItem(new SideNavItem("Candidates", CandidatesListView.class, - LineAwesomeIcon.USER.create())); - recruiting.addItem(new SideNavItem("Questions", QuestionsListView.class, - LineAwesomeIcon.QUESTION_SOLID.create())); - nav.addItem(recruiting); - } + if (AuthUtils.isAdmin(authContext)) { + SideNavItem admin = new SideNavItem("Admin"); + admin.setPrefixComponent(LineAwesomeIcon.BUILDING.create()); + admin.addItem(new SideNavItem("Calendario", TimeOffListView.class, + LineAwesomeIcon.CALENDAR.create())); + nav.addItem(admin); - final SideNavItem timeOff = new SideNavItem("Time-off"); - timeOff.setPrefixComponent(LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create()); - timeOff.addItem(new SideNavItem("Vacations", TimeOffSummaryListView.class, - LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create())); - timeOff.addItem(new SideNavItem("Requests", TimeOffRequestsListView.class, - LineAwesomeIcon.LIST_ALT.create())); + SideNavItem recruiting = new SideNavItem("Recruiting"); + recruiting.setPrefixComponent(LineAwesomeIcon.BUSINESS_TIME_SOLID.create()); + recruiting.addItem(new SideNavItem("Exams", ExamsListView.class, + LineAwesomeIcon.RIBBON_SOLID.create())); + recruiting.addItem(new SideNavItem("Candidates", CandidatesListView.class, + LineAwesomeIcon.USER.create())); + recruiting.addItem(new SideNavItem("Questions", QuestionsListView.class, + LineAwesomeIcon.QUESTION_SOLID.create())); + nav.addItem(recruiting); + } - final SideNavItem timesheet = new SideNavItem("Timesheet"); - timesheet.setPrefixComponent(LineAwesomeIcon.HOURGLASS_START_SOLID.create()); - timesheet.addItem(new SideNavItem("Registro de Horas Trabajadas", TimesheetListView.class, - LineAwesomeIcon.ID_CARD_SOLID.create())); + final SideNavItem timeOff = new SideNavItem("Time-off"); + timeOff.setPrefixComponent(LineAwesomeIcon.PLANE_DEPARTURE_SOLID.create()); + timeOff.addItem(new SideNavItem("Vacations", TimeOffSummaryListView.class, + LineAwesomeIcon.UMBRELLA_BEACH_SOLID.create())); + timeOff.addItem(new SideNavItem("Requests", TimeOffRequestsListView.class, + LineAwesomeIcon.LIST_ALT.create())); - if (isAdmin(authContext)) { - timesheet.addItem(new SideNavItem("Reporte Horas Trabajadas", TimesheetReportView.class, + final SideNavItem timesheet = new SideNavItem("Timesheet"); + timesheet.setPrefixComponent(LineAwesomeIcon.HOURGLASS_START_SOLID.create()); + timesheet.addItem(new SideNavItem("Registro de Horas Trabajadas", TimesheetListView.class, LineAwesomeIcon.ID_CARD_SOLID.create())); + + if (AuthUtils.isAdmin(authContext)) { + timesheet.addItem(new SideNavItem("Reporte Horas Trabajadas", TimesheetReportView.class, + LineAwesomeIcon.ID_CARD_SOLID.create())); + } + + final SideNavItem profile = new SideNavItem("Employee"); + profile.setPrefixComponent(LineAwesomeIcon.USER_TIE_SOLID.create()); + + if (AuthUtils.isAdmin(authContext)) { + profile.addItem(new SideNavItem("Profiles", EmployeesListView.class, + LineAwesomeIcon.USER_FRIENDS_SOLID.create())); + } + + profile.addItem(new SideNavItem("My Profile", "/employees/me", + LineAwesomeIcon.USER_EDIT_SOLID.create())); + profile.addItem(new SideNavItem("Documents", DocumentsListView.class, + LineAwesomeIcon.FILE_ALT_SOLID.create())); + + nav.addItem(profile); + nav.addItem(timesheet); + nav.addItem(timeOff); } - final SideNavItem profile = new SideNavItem("Employee"); - profile.setPrefixComponent(LineAwesomeIcon.USER_TIE_SOLID.create()); - - if (isAdmin(authContext)) { - profile.addItem(new SideNavItem("Profiles", EmployeesListView.class, - LineAwesomeIcon.USER_FRIENDS_SOLID.create())); - } - - profile.addItem(new SideNavItem("My Profile", "/employees/me", - LineAwesomeIcon.USER_EDIT_SOLID.create())); - profile.addItem(new SideNavItem("Documents", DocumentsListView.class, - LineAwesomeIcon.FILE_ALT_SOLID.create())); - - nav.addItem(profile); - nav.addItem(timesheet); - nav.addItem(timeOff); - return nav; } diff --git a/src/main/java/com/primefactorsolutions/views/SubmissionView.java b/src/main/java/com/primefactorsolutions/views/SubmissionView.java index 315e554..ab73cf5 100644 --- a/src/main/java/com/primefactorsolutions/views/SubmissionView.java +++ b/src/main/java/com/primefactorsolutions/views/SubmissionView.java @@ -20,9 +20,9 @@ import com.vaadin.flow.component.menubar.MenuBarVariant; import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.*; -import com.vaadin.flow.server.auth.AnonymousAllowed; import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.theme.lumo.LumoUtility.*; +import jakarta.annotation.security.RolesAllowed; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.context.annotation.Scope; @@ -37,8 +37,8 @@ import java.util.stream.Collectors; @PageTitle("Evaluacion") @SpringComponent @Scope("prototype") -@Route(value = "/submission", layout = MainLayout.class) -@AnonymousAllowed +@RolesAllowed("ROLE_ADMIN") +@Route(value = "/submissions", layout = MainLayout.class) @Slf4j public class SubmissionView extends Main implements HasUrlParameter { diff --git a/src/main/java/com/primefactorsolutions/views/assessment/CandidateView.java b/src/main/java/com/primefactorsolutions/views/assessment/CandidateView.java index c30625e..45a0c32 100644 --- a/src/main/java/com/primefactorsolutions/views/assessment/CandidateView.java +++ b/src/main/java/com/primefactorsolutions/views/assessment/CandidateView.java @@ -12,7 +12,7 @@ import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.security.AuthenticationContext; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Scope; @@ -23,7 +23,7 @@ import java.util.UUID; @Scope("prototype") @PageTitle("Candidates") @Route(value = "/candidates", layout = MainLayout.class) -@PermitAll +@RolesAllowed("ROLE_ADMIN") public class CandidateView extends BaseEntityForm implements HasUrlParameter { private final CandidateService candidateService; diff --git a/src/main/java/com/primefactorsolutions/views/assessment/CandidatesListView.java b/src/main/java/com/primefactorsolutions/views/assessment/CandidatesListView.java index d44ba31..83207ad 100644 --- a/src/main/java/com/primefactorsolutions/views/assessment/CandidatesListView.java +++ b/src/main/java/com/primefactorsolutions/views/assessment/CandidatesListView.java @@ -16,7 +16,7 @@ import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.security.AuthenticationContext; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Scope; import org.vaadin.firitin.components.grid.VGrid; @@ -27,7 +27,7 @@ import java.util.Map; @Scope("prototype") @PageTitle("Candidates") @Route(value = "/candidates", layout = MainLayout.class) -@PermitAll +@RolesAllowed("ROLE_ADMIN") public class CandidatesListView extends BaseView { public CandidatesListView(final AuthenticationContext authenticationContext, diff --git a/src/main/java/com/primefactorsolutions/views/assessment/ExamView.java b/src/main/java/com/primefactorsolutions/views/assessment/ExamView.java index eda8721..5c95604 100644 --- a/src/main/java/com/primefactorsolutions/views/assessment/ExamView.java +++ b/src/main/java/com/primefactorsolutions/views/assessment/ExamView.java @@ -16,7 +16,7 @@ import com.vaadin.flow.router.HasUrlParameter; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Scope; import org.vaadin.firitin.fields.SubListSelector; @@ -26,7 +26,7 @@ import java.util.List; import java.util.UUID; @SpringComponent -@PermitAll +@RolesAllowed("ROLE_ADMIN") @Scope("prototype") @PageTitle("Exams") @Route(value = "/exams", layout = MainLayout.class) diff --git a/src/main/java/com/primefactorsolutions/views/assessment/ExamsListView.java b/src/main/java/com/primefactorsolutions/views/assessment/ExamsListView.java index 7720ed2..c3c4bc2 100644 --- a/src/main/java/com/primefactorsolutions/views/assessment/ExamsListView.java +++ b/src/main/java/com/primefactorsolutions/views/assessment/ExamsListView.java @@ -17,7 +17,7 @@ import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.security.AuthenticationContext; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Scope; import org.vaadin.addon.stefan.clipboard.ClientsideClipboard; @@ -27,7 +27,7 @@ import org.vaadin.firitin.components.grid.VGrid; @Scope("prototype") @PageTitle("Exams") @Route(value = "/exams", layout = MainLayout.class) -@PermitAll +@RolesAllowed("ROLE_ADMIN") public class ExamsListView extends BaseView { public ExamsListView(final AuthenticationContext authenticationContext, @@ -53,7 +53,8 @@ public class ExamsListView extends BaseView { getUI().flatMap(ui -> ui.navigate(SubmissionView.class, exam.getId().toString()))), Pair.of("Copy", __ -> ClientsideClipboard.writeToClipboard( - String.format("email: %s link: https://intra.primefactorsolutions.com/evaluation/%s", + String.format("email: %s link: " + + "https://intra.primefactorsolutions.com/candidate-exam/%s", exam.getCandidate().getEmail(), exam.getId()))), Pair.of("Email", __ -> { diff --git a/src/main/java/com/primefactorsolutions/views/assessment/QuestionView.java b/src/main/java/com/primefactorsolutions/views/assessment/QuestionView.java index aa5c22f..0e8664e 100644 --- a/src/main/java/com/primefactorsolutions/views/assessment/QuestionView.java +++ b/src/main/java/com/primefactorsolutions/views/assessment/QuestionView.java @@ -11,7 +11,7 @@ import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.router.*; import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.security.AuthenticationContext; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Scope; @@ -22,7 +22,7 @@ import java.util.UUID; @Scope("prototype") @PageTitle("Questions") @Route(value = "/questions", layout = MainLayout.class) -@PermitAll +@RolesAllowed("ROLE_ADMIN") public class QuestionView extends BaseEntityForm implements HasUrlParameter { private final QuestionService questionService; diff --git a/src/main/java/com/primefactorsolutions/views/assessment/QuestionsListView.java b/src/main/java/com/primefactorsolutions/views/assessment/QuestionsListView.java index 02cb957..f150edd 100644 --- a/src/main/java/com/primefactorsolutions/views/assessment/QuestionsListView.java +++ b/src/main/java/com/primefactorsolutions/views/assessment/QuestionsListView.java @@ -15,7 +15,7 @@ import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; import com.vaadin.flow.spring.security.AuthenticationContext; -import jakarta.annotation.security.PermitAll; +import jakarta.annotation.security.RolesAllowed; import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Scope; import org.vaadin.firitin.components.grid.VGrid; @@ -24,7 +24,7 @@ import org.vaadin.firitin.components.grid.VGrid; @Scope("prototype") @PageTitle("Questions") @Route(value = "/questions", layout = MainLayout.class) -@PermitAll +@RolesAllowed("ROLE_ADMIN") public class QuestionsListView extends BaseView { public QuestionsListView(final AuthenticationContext authenticationContext, final QuestionService questionService) { diff --git a/src/main/java/com/primefactorsolutions/views/util/AuthUtils.java b/src/main/java/com/primefactorsolutions/views/util/AuthUtils.java index 42272e7..4701fa0 100644 --- a/src/main/java/com/primefactorsolutions/views/util/AuthUtils.java +++ b/src/main/java/com/primefactorsolutions/views/util/AuthUtils.java @@ -11,6 +11,10 @@ import java.util.UUID; @UtilityClass public class AuthUtils { + public static boolean isUser(final AuthenticationContext authenticationContext) { + return authenticationContext.getAuthenticatedUser(UserDetails.class).isPresent(); + } + public static boolean isAdmin(final AuthenticationContext authenticationContext) { return authenticationContext.getAuthenticatedUser(UserDetails.class) .map(u -> diff --git a/src/test/java/com/primefactorsolutions/views/AbstractAppTests.java b/src/test/java/com/primefactorsolutions/views/AbstractAppTests.java index d51af1f..cb16bd6 100644 --- a/src/test/java/com/primefactorsolutions/views/AbstractAppTests.java +++ b/src/test/java/com/primefactorsolutions/views/AbstractAppTests.java @@ -35,7 +35,7 @@ public class AbstractAppTests { protected void login(String user, String pass, final List roles) { final List authorities = - roles.stream().map(it -> new SimpleGrantedAuthority("ROLE_" + it)).collect(Collectors.toList()); + roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(new User(user, pass, authorities), pass, authorities); SecurityContext sc = SecurityContextHolder.getContext(); diff --git a/src/test/java/com/primefactorsolutions/views/CandidateViewTests.java b/src/test/java/com/primefactorsolutions/views/CandidateViewTests.java index b3d16a8..8c6d489 100644 --- a/src/test/java/com/primefactorsolutions/views/CandidateViewTests.java +++ b/src/test/java/com/primefactorsolutions/views/CandidateViewTests.java @@ -14,7 +14,7 @@ import static com.github.mvysny.kaributesting.v10.LocatorJ.*; public class CandidateViewTests extends AbstractAppTests { @BeforeEach public void login() { - login("user", "user", List.of("user")); + login("user", "user", List.of("ROLE_ADMIN")); } @Test