From dfbe32bcf3102cb4eeeadaf0afd9714e0dce6028 Mon Sep 17 00:00:00 2001 From: leonardo-pilastri-sonarsource <115481625+leonardo-pilastri-sonarsource@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:03:28 +0200 Subject: [PATCH] SONARJAVA-4680 Add @AuthenticationPrincipal as an exception to the rule (#4503) --- ...PersistentEntityUsedAsRequestParameterCheck.java | 11 +++++++++++ ...PersistentEntityUsedAsRequestParameterCheck.java | 13 ++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/java-checks-test-sources/src/main/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java b/java-checks-test-sources/src/main/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java index 381d782e4ba..75af948c456 100644 --- a/java-checks-test-sources/src/main/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java +++ b/java-checks-test-sources/src/main/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; @@ -50,6 +51,16 @@ public class Baz { @Controller class FooController { + @Entity + abstract class User implements UserDetails { + String username; + // ... + } + @GetMapping("/greet") + public void greet(@org.springframework.security.core.annotation.AuthenticationPrincipal User user) { + // do something with User + } + @RequestMapping(path = "/foo", method = RequestMethod.POST) public void foo1(Foo foo) { // Noncompliant [[sc=26;ec=29]] {{Replace this persistent entity with a simple POJO or DTO object.}} } diff --git a/java-checks/src/main/java/org/sonar/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java b/java-checks/src/main/java/org/sonar/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java index 8c905860d74..d239435ceb8 100644 --- a/java-checks/src/main/java/org/sonar/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java +++ b/java-checks/src/main/java/org/sonar/java/checks/spring/PersistentEntityUsedAsRequestParameterCheck.java @@ -36,6 +36,11 @@ public List nodesToVisit() { return Collections.singletonList(Tree.Kind.METHOD); } + private static final List PARAMETER_ANNOTATION_EXCEPTIONS = List.of( + "org.springframework.web.bind.annotation.PathVariable", + "org.springframework.security.core.annotation.AuthenticationPrincipal" + ); + private static final List REQUEST_ANNOTATIONS = List.of( "org.springframework.web.bind.annotation.RequestMapping", "org.springframework.web.bind.annotation.GetMapping", @@ -51,8 +56,6 @@ public List nodesToVisit() { "org.springframework.data.elasticsearch.annotations.Document" ); - private static final String PATH_VARIABLE_ANNOTATION = "org.springframework.web.bind.annotation.PathVariable"; - private static final String JSON_CREATOR_ANNOTATION = "com.fasterxml.jackson.annotation.JsonCreator"; @Override @@ -62,7 +65,7 @@ public void visitNode(Tree tree) { if (isRequestMappingAnnotated(methodSymbol)) { methodTree.parameters().stream() - .filter(PersistentEntityUsedAsRequestParameterCheck::hasNoPathVariableAnnotation) + .filter(PersistentEntityUsedAsRequestParameterCheck::hasNoAllowedAnnotations) .filter(PersistentEntityUsedAsRequestParameterCheck::isPersistentEntity) .filter(PersistentEntityUsedAsRequestParameterCheck::hasNoCustomSerialization) .forEach(p -> reportIssue(p.simpleName(), "Replace this persistent entity with a simple POJO or DTO object.")); @@ -77,8 +80,8 @@ private static boolean isPersistentEntity(VariableTree variableTree) { return ENTITY_ANNOTATIONS.stream().anyMatch(variableTree.type().symbolType().symbol().metadata()::isAnnotatedWith); } - private static boolean hasNoPathVariableAnnotation(VariableTree variableTree) { - return !variableTree.symbol().metadata().isAnnotatedWith(PATH_VARIABLE_ANNOTATION); + private static boolean hasNoAllowedAnnotations(VariableTree variableTree) { + return PARAMETER_ANNOTATION_EXCEPTIONS.stream().noneMatch(variableTree.symbol().metadata()::isAnnotatedWith); } private static boolean hasNoCustomSerialization(VariableTree variableTree) {