-
Notifications
You must be signed in to change notification settings - Fork 0
Adds logic for role mapping. #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
6a75c32
c2d95a1
9edf28a
d432fca
85dd8f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package org.example.projektarendehantering.presentation.web; | ||
|
|
||
| import jakarta.validation.Valid; | ||
| import org.example.projektarendehantering.application.service.EmployeeService; | ||
| import org.example.projektarendehantering.common.Actor; | ||
| import org.example.projektarendehantering.common.Role; | ||
| import org.example.projektarendehantering.infrastructure.security.SecurityActorAdapter; | ||
| import org.example.projektarendehantering.presentation.dto.EmployeeCreateDTO; | ||
| import org.springframework.security.access.prepost.PreAuthorize; | ||
| import org.springframework.stereotype.Controller; | ||
| import org.springframework.ui.Model; | ||
| import org.springframework.validation.BindingResult; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.ModelAttribute; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
|
|
||
| @Controller | ||
| public class EmployeeUiController { | ||
|
|
||
| private final EmployeeService employeeService; | ||
| private final SecurityActorAdapter securityActorAdapter; | ||
|
|
||
| public EmployeeUiController(EmployeeService employeeService, SecurityActorAdapter securityActorAdapter) { | ||
| this.employeeService = employeeService; | ||
| this.securityActorAdapter = securityActorAdapter; | ||
| } | ||
|
|
||
| @GetMapping("/ui/employees") | ||
| public String listEmployees(Model model) { | ||
| Actor actor = securityActorAdapter.currentUser(); | ||
| model.addAttribute("employees", employeeService.getAllEmployees(actor)); | ||
| return "employees/list"; | ||
| } | ||
|
|
||
| @GetMapping("/ui/employees/new") | ||
| @PreAuthorize("hasRole('MANAGER')") | ||
| public String newEmployee(Model model) { | ||
| model.addAttribute("employeeCreateDTO", new EmployeeCreateDTO()); | ||
| model.addAttribute("roles", Role.values()); | ||
| return "employees/new"; | ||
| } | ||
|
Comment on lines
+35
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify whether endpoint-level restrictions already exist for /ui/employees/new
rg -nP --type=java '(/ui/employees/new|/ui/employees)' -C3
rg -nP --type=java 'requestMatchers\s*\(|antMatchers\s*\(|mvcMatchers\s*\(' -C3
rg -nP --type=java '@EnableMethodSecurity|@EnableGlobalMethodSecurity|@PreAuthorize' -C3Repository: ithsjava25/project-backend-code-trauma-team Length of output: 4676 🏁 Script executed: # Check if method-level security is enabled anywhere
rg -nP --type=java '@EnableMethodSecurity|@EnableGlobalMethodSecurity' -A5 -B2
# Get complete SecurityConfig
fd --type=f -name 'SecurityConfig.java' --exec cat -n {}
# Get complete EmployeeUiController to verify all endpoints
fd --type=f -name 'EmployeeUiController.java' --exec cat -n {}
# Check what imports are already in EmployeeUiController
rg -nP --type=java '^import' src/main/java/org/example/projektarendehantering/presentation/web/EmployeeUiController.javaRepository: ithsjava25/project-backend-code-trauma-team Length of output: 1305 🏁 Script executed: # Check if method-level security is enabled
rg '@EnableMethodSecurity|@EnableGlobalMethodSecurity' --type java -A5 -B2
# Get complete SecurityConfig
cat src/main/java/org/example/projektarendehantering/infrastructure/config/SecurityConfig.java
# Get complete EmployeeUiController
cat src/main/java/org/example/projektarendehantering/presentation/web/EmployeeUiController.javaRepository: ithsjava25/project-backend-code-trauma-team Length of output: 3980 🏁 Script executed: # Find and read EmployeeService
find . -type f -name 'EmployeeService.java' | head -1 | xargs cat
# Also check for any method-level security annotations in the application main class
find . -type f -name '*Application.java' -o -name '*SpringBootApplication.java' | xargs grep -l '@EnableMethodSecurity\|@EnableGlobalMethodSecurity\|@SpringBootApplication'Repository: ithsjava25/project-backend-code-trauma-team Length of output: 2603 🏁 Script executed: # Search for any `@PreAuthorize` usage in the codebase
rg '@PreAuthorize' --type java
# Check the main application class
cat ./src/main/java/org/example/projektarendehantering/ProjektArendehanteringApplication.javaRepository: ithsjava25/project-backend-code-trauma-team Length of output: 457 Add authorization check to GET /ui/employees/new endpoint. The form page is served to any authenticated user without a role check. While unauthenticated access is prevented by servlet-level security, non-managers can still view the form even though POST operations reject them via To implement the suggested fix with Required changes
`@Configuration`
`@EnableWebSecurity`
+@EnableMethodSecurity
public class SecurityConfig {
+import org.springframework.security.access.prepost.PreAuthorize;
- `@GetMapping`("/ui/employees/new")
+ `@PreAuthorize`("hasRole('MANAGER')")
+ `@GetMapping`("/ui/employees/new")
public String newEmployee(Model model) {
model.addAttribute("employeeCreateDTO", new EmployeeCreateDTO());
model.addAttribute("roles", Role.values());
return "employees/new";
}Alternatively, add an authorization check directly in the controller method (without requiring 🤖 Prompt for AI Agents |
||
|
|
||
| @PostMapping("/ui/employees/new") | ||
| public String createEmployee(@Valid @ModelAttribute("employeeCreateDTO") EmployeeCreateDTO dto, BindingResult result, Model model) { | ||
| if (result.hasErrors()) { | ||
| model.addAttribute("roles", Role.values()); | ||
| return "employees/new"; | ||
| } | ||
|
|
||
| Actor actor = securityActorAdapter.currentUser(); | ||
| employeeService.createEmployee(actor, dto); | ||
| return "redirect:/ui/employees"; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing authorization check in
addNoteallows unauthorized note writes.addNoteloads the case and saves a note without validating that the actor may access/modify that case.Proposed fix
`@Transactional` public void addNote(UUID caseId, String content, Actor actor) { + if (actor == null) { + throw new NotAuthorizedException("Not allowed to add note"); + } CaseEntity caseEntity = caseRepository.findById(caseId) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Case not found")); + requireCanRead(actor, caseEntity); CaseNoteEntity note = new CaseNoteEntity(); note.setCaseEntity(caseEntity); note.setContent(content); - if (actor != null) { - note.setAuthorDisplayName(actor.displayName()); - note.setAuthorGithubUsername(actor.githubUsername()); - note.setAuthorRole(actor.role() != null ? actor.role().name() : null); - } + note.setAuthorDisplayName(actor.displayName()); + note.setAuthorGithubUsername(actor.githubUsername()); + note.setAuthorRole(actor.role() != null ? actor.role().name() : null); note.setCreatedAt(Instant.now()); caseNoteRepository.save(note); }🤖 Prompt for AI Agents