From a9ee99a6fef0a12483ee0d6ad3390fa1e8708d35 Mon Sep 17 00:00:00 2001 From: sechmachine <97589681+sechmachine727@users.noreply.github.com> Date: Sat, 15 Aug 2026 00:30:22 +0700 Subject: [PATCH] fix(project): hide mentor-only controls --- .../project/controller/ProjectController.java | 6 ++++- .../project/model/dto/ProjectDetail.java | 3 ++- .../project/service/ProjectQueryService.java | 3 ++- .../templates/projects/leadership.html | 2 +- .../resources/templates/projects/members.html | 2 +- .../controller/ProjectControllerTest.java | 24 ++++++++++++++++--- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/lab/labtimesheet/feature/project/controller/ProjectController.java b/src/main/java/com/lab/labtimesheet/feature/project/controller/ProjectController.java index 16c4758..79cfd10 100644 --- a/src/main/java/com/lab/labtimesheet/feature/project/controller/ProjectController.java +++ b/src/main/java/com/lab/labtimesheet/feature/project/controller/ProjectController.java @@ -1,5 +1,6 @@ package com.lab.labtimesheet.feature.project.controller; +import com.lab.labtimesheet.feature.project.exception.ProjectAccessDeniedException; import com.lab.labtimesheet.feature.project.model.dto.ProjectCreateForm; import com.lab.labtimesheet.feature.project.model.dto.ProjectMemberForm; import com.lab.labtimesheet.feature.project.service.ProjectQueryService; @@ -34,7 +35,10 @@ public class ProjectController { } @GetMapping("/new") - public String createForm(Model model) { + public String createForm(Principal principal, Model model) { + if (!"MENTOR".equals(pages.authenticatedActor(principal.getName()).role())) { + throw new ProjectAccessDeniedException(); + } model.addAttribute("projectForm", new ProjectCreateForm()); return "projects/form"; } diff --git a/src/main/java/com/lab/labtimesheet/feature/project/model/dto/ProjectDetail.java b/src/main/java/com/lab/labtimesheet/feature/project/model/dto/ProjectDetail.java index 4af0e54..72a13a0 100644 --- a/src/main/java/com/lab/labtimesheet/feature/project/model/dto/ProjectDetail.java +++ b/src/main/java/com/lab/labtimesheet/feature/project/model/dto/ProjectDetail.java @@ -10,5 +10,6 @@ public record ProjectDetail( LocalDate startDate, LocalDate endDate, String mentorName, - String leaderName) { + String leaderName, + boolean canManage) { } diff --git a/src/main/java/com/lab/labtimesheet/feature/project/service/ProjectQueryService.java b/src/main/java/com/lab/labtimesheet/feature/project/service/ProjectQueryService.java index eadff93..593bfc9 100644 --- a/src/main/java/com/lab/labtimesheet/feature/project/service/ProjectQueryService.java +++ b/src/main/java/com/lab/labtimesheet/feature/project/service/ProjectQueryService.java @@ -64,7 +64,8 @@ public class ProjectQueryService { project.startDate(), project.endDate(), displayName(project.mentorUserId()), - displayName(project.currentLeader().internUserId())); + displayName(project.currentLeader().internUserId()), + project.mentorUserId() == actorUserId); } @Transactional(readOnly = true) diff --git a/src/main/resources/templates/projects/leadership.html b/src/main/resources/templates/projects/leadership.html index 378a69c..abe41e9 100644 --- a/src/main/resources/templates/projects/leadership.html +++ b/src/main/resources/templates/projects/leadership.html @@ -7,7 +7,7 @@
Leadership history
LeaderStartedEnded
-
+
diff --git a/src/main/resources/templates/projects/members.html b/src/main/resources/templates/projects/members.html index e0238eb..8ee0e9f 100644 --- a/src/main/resources/templates/projects/members.html +++ b/src/main/resources/templates/projects/members.html @@ -7,7 +7,7 @@
Membership history
InternJoinedLeftRole
-
+
diff --git a/src/test/java/com/lab/labtimesheet/feature/project/controller/ProjectControllerTest.java b/src/test/java/com/lab/labtimesheet/feature/project/controller/ProjectControllerTest.java index ed3ef9f..4a13cec 100644 --- a/src/test/java/com/lab/labtimesheet/feature/project/controller/ProjectControllerTest.java +++ b/src/test/java/com/lab/labtimesheet/feature/project/controller/ProjectControllerTest.java @@ -3,6 +3,8 @@ package com.lab.labtimesheet.feature.project.controller; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -13,6 +15,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import com.lab.labtimesheet.feature.project.exception.ProjectAccessDeniedException; import com.lab.labtimesheet.feature.project.model.dto.ProjectCreateCommand; +import com.lab.labtimesheet.feature.project.model.dto.ProjectActorView; import com.lab.labtimesheet.feature.project.model.dto.ProjectDetail; import com.lab.labtimesheet.feature.project.model.dto.ProjectSummary; import com.lab.labtimesheet.feature.project.service.ProjectQueryService; @@ -79,16 +82,31 @@ class ProjectControllerTest { LocalDate.of(2026, 8, 15), LocalDate.of(2026, 9, 30), "Mentor", - "Leader")); + "Leader", + false)); when(pages.members(20L, 30L)).thenReturn(List.of()); when(pages.leadership(20L, 30L)).thenReturn(List.of()); mvc.perform(get("/projects/30/members")) .andExpect(status().isOk()) - .andExpect(view().name("projects/members")); + .andExpect(view().name("projects/members")) + .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.content() + .string(not(containsString("Add member")))); mvc.perform(get("/projects/30/leadership")) .andExpect(status().isOk()) - .andExpect(view().name("projects/leadership")); + .andExpect(view().name("projects/leadership")) + .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.content() + .string(not(containsString("Change Leader")))); + } + + @Test + @WithMockUser(username = "member@example.test") + void nonMentorCannotOpenProjectCreationForm() throws Exception { + when(pages.authenticatedActor("member@example.test")) + .thenReturn(new ProjectActorView(20L, "INTERN")); + + mvc.perform(get("/projects/new")) + .andExpect(status().isNotFound()); } @Test