-
Notifications
You must be signed in to change notification settings - Fork 2
Feat/comment controller #55
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
Changes from all commits
8f18a7b
a669f1b
af2c0df
231cdec
355faaa
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,99 @@ | ||||||||||||||||||
| package org.example.vet1177.controllers; | ||||||||||||||||||
|
|
||||||||||||||||||
| import jakarta.validation.Valid; | ||||||||||||||||||
| import org.example.vet1177.dto.request.comment.CreateCommentRequest; | ||||||||||||||||||
| import org.example.vet1177.dto.request.comment.UpdateCommentRequest; | ||||||||||||||||||
| import org.example.vet1177.dto.response.comment.CommentResponse; | ||||||||||||||||||
| import org.example.vet1177.entities.User; | ||||||||||||||||||
| import org.example.vet1177.services.CommentService; | ||||||||||||||||||
| import org.springframework.http.ResponseEntity; | ||||||||||||||||||
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||||||||||||||||||
| import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||||
| import org.springframework.web.bind.annotation.*; | ||||||||||||||||||
|
|
||||||||||||||||||
| import java.util.List; | ||||||||||||||||||
| import java.util.UUID; | ||||||||||||||||||
|
|
||||||||||||||||||
| @RestController | ||||||||||||||||||
| @RequestMapping("/api/comments") | ||||||||||||||||||
| public class CommentController { | ||||||||||||||||||
|
|
||||||||||||||||||
| private final CommentService commentService; | ||||||||||||||||||
|
|
||||||||||||||||||
| public CommentController(CommentService commentService) { | ||||||||||||||||||
| this.commentService = commentService; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // POST /api/comments | ||||||||||||||||||
| @PostMapping | ||||||||||||||||||
| @Transactional | ||||||||||||||||||
| public ResponseEntity<CommentResponse> create( | ||||||||||||||||||
| @Valid @RequestBody CreateCommentRequest request, | ||||||||||||||||||
| @AuthenticationPrincipal User currentUser) { | ||||||||||||||||||
|
|
||||||||||||||||||
|
Comment on lines
+30
to
+33
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 principal/type compatibility and all affected injection points.
# Expected:
# - User entity should implement UserDetails OR controller should consume UserDetails/custom principal.
# - All `@AuthenticationPrincipal` usages should align with configured Authentication principal type.
rg -nP --type=java -C3 'class\s+User\b|implements\s+UserDetails' src/main/java/org/example/vet1177/entities/User.java
rg -nP --type=java -C2 '@AuthenticationPrincipal\s+User\b|@AuthenticationPrincipal\s+.*UserDetails\b' src/main/javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 2439 🏁 Script executed: # Find security configuration files
fd -e java -e yml -e yaml -e properties | xargs grep -l "SecurityConfig\|UserDetailsService\|@EnableWebSecurity\|AuthenticationProvider" 2>/dev/null | head -20Repository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Search for UserDetailsService implementation
rg -n "implements UserDetailsService|class.*UserDetailsService" --type=javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Check if User is registered or used as principal in any configuration
rg -n "User\s*principal|new User|authentication.*User" --type=java -C2 | head -50Repository: ithsjava25/project-backend-org-random-coders Length of output: 601 🏁 Script executed: # Search for any Spring Security configuration (including annotations)
rg -n "@EnableWebSecurity|@Configuration|SecurityFilterChain|WebSecurityConfigurerAdapter" --type=javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Search for authentication/security in application.properties or application.yml
fd -e properties -e yml -e yaml | xargs cat 2>/dev/nullRepository: ithsjava25/project-backend-org-random-coders Length of output: 1150 🏁 Script executed: # Check if there's a custom principal class or custom UserDetails implementation
rg -n "implements UserDetails|extends User|class.*Principal" --type=javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Look for authentication manager or provider configuration
rg -n "AuthenticationManager|AuthenticationProvider|DaoAuthenticationProvider" --type=javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Search more broadly for any Spring Security related code
rg -n "spring.security|@Bean.*SecurityFilterChain|UserDetailsService" --type=javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Check pom.xml or build.gradle for spring-security dependency
fd -e pom.xml -e gradle.build | xargs cat 2>/dev/null | grep -i "spring-security\|security"Repository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # List all Java files in the project to understand structure
find src -name "*.java" -type f | head -30Repository: ithsjava25/project-backend-org-random-coders Length of output: 2143 🏁 Script executed: # Check the entire User entity class definition
cat -n src/main/java/org/example/vet1177/entities/User.javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 4598 🏁 Script executed: # Check if Spring Security is even a dependency - search pom.xml in root
find . -name "pom.xml" -o -name "build.gradle" | head -5Repository: ithsjava25/project-backend-org-random-coders Length of output: 97 🏁 Script executed: # Search for any authentication annotation usage or auth filter
rg -n "@RequestHeader.*Authorization|@CookieValue|HttpServletRequest.*getHeader|Authorization" --type=java | head -20Repository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Check if there's any servlet filter or interceptor for authentication
rg -n "Filter|Interceptor|@Component|@WebFilter" --type=java | grep -i "auth\|security\|filter" | head -20Repository: ithsjava25/project-backend-org-random-coders Length of output: 70 🏁 Script executed: # Look at the main application file to see what's configured
cat -n src/main/java/org/example/vet1177/Vet1177Application.javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 504 🏁 Script executed: # Check pom.xml for dependencies, especially spring-security
cat -n pom.xml | head -100Repository: ithsjava25/project-backend-org-random-coders Length of output: 4027 🏁 Script executed: # Search for any Bean definitions that might handle authentication
rg -n "@Bean" --type=javaRepository: ithsjava25/project-backend-org-random-coders Length of output: 70
Lines 32, 50, 66, and 79 inject Use public ResponseEntity<CommentResponse> create(
`@Valid` `@RequestBody` CreateCommentRequest request,
- `@AuthenticationPrincipal` User currentUser) {
+ `@AuthenticationPrincipal` UserDetails principal) {
+
+ User currentUser = userService.findByEmail(principal.getUsername());Apply the same pattern to getByRecord (line 50), update (line 66), and delete (line 79). 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| return ResponseEntity.ok( | ||||||||||||||||||
| CommentResponse.from( | ||||||||||||||||||
| commentService.create( | ||||||||||||||||||
| request.recordId(), | ||||||||||||||||||
| request.body(), | ||||||||||||||||||
| currentUser | ||||||||||||||||||
| ) | ||||||||||||||||||
| ) | ||||||||||||||||||
| ); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // GET /api/comments/record/{recordId} | ||||||||||||||||||
| @GetMapping("/record/{recordId}") | ||||||||||||||||||
| @Transactional(readOnly = true) | ||||||||||||||||||
| public ResponseEntity<List<CommentResponse>> getByRecord( | ||||||||||||||||||
| @PathVariable UUID recordId, | ||||||||||||||||||
| @AuthenticationPrincipal User currentUser) { | ||||||||||||||||||
|
|
||||||||||||||||||
| return ResponseEntity.ok( | ||||||||||||||||||
| commentService.getByRecord(recordId, currentUser) | ||||||||||||||||||
| .stream() | ||||||||||||||||||
| .map(CommentResponse::from) | ||||||||||||||||||
| .toList() | ||||||||||||||||||
| ); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // PUT /api/comments/{id} | ||||||||||||||||||
| @PutMapping("/{id}") | ||||||||||||||||||
| @Transactional | ||||||||||||||||||
| public ResponseEntity<CommentResponse> update( | ||||||||||||||||||
| @PathVariable UUID id, | ||||||||||||||||||
| @Valid @RequestBody UpdateCommentRequest request, | ||||||||||||||||||
| @AuthenticationPrincipal User currentUser) { | ||||||||||||||||||
|
|
||||||||||||||||||
| return ResponseEntity.ok( | ||||||||||||||||||
| CommentResponse.from( | ||||||||||||||||||
| commentService.update(id, request.body(), currentUser) | ||||||||||||||||||
| ) | ||||||||||||||||||
| ); | ||||||||||||||||||
| } | ||||||||||||||||||
| // DELETE /api/comments/{id} | ||||||||||||||||||
| @DeleteMapping("/{id}") | ||||||||||||||||||
| @Transactional | ||||||||||||||||||
| public ResponseEntity<Void> delete( | ||||||||||||||||||
| @PathVariable UUID id, | ||||||||||||||||||
| @AuthenticationPrincipal User currentUser) { | ||||||||||||||||||
|
|
||||||||||||||||||
| commentService.delete(id, currentUser); | ||||||||||||||||||
| return ResponseEntity.noContent().build(); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // CommentController — lägg till currentUser | ||||||||||||||||||
| @GetMapping("/record/{recordId}/count") | ||||||||||||||||||
| @Transactional(readOnly = true) | ||||||||||||||||||
| public ResponseEntity<Long> countByRecord( | ||||||||||||||||||
| @PathVariable UUID recordId, | ||||||||||||||||||
| @AuthenticationPrincipal User currentUser) { | ||||||||||||||||||
| return ResponseEntity.ok( | ||||||||||||||||||
| commentService.countByRecord(recordId, currentUser) | ||||||||||||||||||
| ); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| } | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,28 @@ | ||||||||||||||||||||
| package org.example.vet1177.security; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| import org.springframework.context.annotation.Bean; | ||||||||||||||||||||
| import org.springframework.context.annotation.Configuration; | ||||||||||||||||||||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||||||||||||||||||||
| import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||||||||||||||||||||
| import org.springframework.security.crypto.password.PasswordEncoder; | ||||||||||||||||||||
| import org.springframework.security.web.SecurityFilterChain; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @Configuration | ||||||||||||||||||||
| public class SecurityConfig { | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @Bean | ||||||||||||||||||||
| public SecurityFilterChain securityFilterChain(HttpSecurity http) | ||||||||||||||||||||
| throws Exception { | ||||||||||||||||||||
| return http | ||||||||||||||||||||
| .csrf(csrf -> csrf.disable()) | ||||||||||||||||||||
| .authorizeHttpRequests(auth -> auth | ||||||||||||||||||||
| .anyRequest().permitAll() // ← temporärt, öppnar allt | ||||||||||||||||||||
| ) | ||||||||||||||||||||
|
Comment on lines
+17
to
+20
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 routing auth rules and principal-based controller usage are aligned.
rg -nP --type=java -C3 'anyRequest\(\)\.permitAll\(|requestMatchers\(.+\)\.authenticated\(' src/main/java/org/example/vet1177
rg -nP --type=java -C2 '@AuthenticationPrincipal\s+User\b' src/main/java/org/example/vet1177/controllersRepository: ithsjava25/project-backend-org-random-coders Length of output: 3625 🏁 Script executed: #!/bin/bash
# Check CommentController's request mapping and all endpoints
rg -nP --type=java -B5 'class CommentController|@RequestMapping|@PostMapping|@GetMapping|@PutMapping|@DeleteMapping' src/main/java/org/example/vet1177/controllers/CommentController.java | head -40
# Check if other controllers also use `@AuthenticationPrincipal`
rg -nP --type=java '@AuthenticationPrincipal\s+User\b' src/main/java/org/example/vet1177/controllers/ | grep -v CommentControllerRepository: ithsjava25/project-backend-org-random-coders Length of output: 1000 🏁 Script executed: #!/bin/bash
# Find all controllers in the codebase
find src/main/java/org/example/vet1177/controllers -name "*.java" -type f
# Check all controllers for authentication requirements
rg -nP --type=java '@RestController|@Controller|@RequestMapping|@AuthenticationPrincipal' src/main/java/org/example/vet1177/controllersRepository: ithsjava25/project-backend-org-random-coders Length of output: 994 Do not ship with global Line 19 of 🔐 Suggested hardening return http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
- .anyRequest().permitAll() // ← temporärt, öppnar allt
+ .requestMatchers("/api/comments/**").authenticated()
+ .anyRequest().permitAll()
)
.build();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
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. This is a temporary security configuration to unblock 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.
Would you like me to open a follow-up issue to track the JWT/security hardening work?
Contributor
Author
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. yes please 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: Length of output: 73
It covers:
|
||||||||||||||||||||
| .build(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @Bean | ||||||||||||||||||||
| public PasswordEncoder passwordEncoder() { | ||||||||||||||||||||
| return new BCryptPasswordEncoder(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
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.
🧩 Analysis chain
🏁 Script executed:
Repository: ithsjava25/project-backend-org-random-coders
Length of output: 70
Add explicit Spring Security configuration to handle API requests properly.
The
spring-boot-starter-securitydependency has been added but noSecurityFilterChainbean exists to configure API-specific security (CSRF handling, authentication endpoints, session policies). Without this configuration, API write operations will return 401/403 errors and may trigger unexpected login redirects.🤖 Prompt for AI Agents