diff --git a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java index 95dcedbb..83db0b98 100644 --- a/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java +++ b/src/main/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheck.java @@ -1,22 +1,31 @@ package apiaddicts.sonar.openapi.checks.operations; +import apiaddicts.sonar.openapi.checks.BaseCheck; import com.google.common.collect.ImmutableSet; import com.sonar.sslr.api.AstNodeType; -import org.sonar.check.Rule; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Stream; import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar; import org.apiaddicts.apitools.dosonarapi.api.v3.OpenApi3Grammar; import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar; -import apiaddicts.sonar.openapi.checks.BaseCheck; import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; - -import java.util.Set; -import java.util.stream.Stream; +import org.sonar.check.Rule; +import org.sonar.check.RuleProperty; @Rule(key = OAR017ResourcePathCheck.KEY) public class OAR017ResourcePathCheck extends BaseCheck { public static final String KEY = "OAR017"; private static final String MESSAGE = "OAR017.error"; + private static final String MESSAGE_PATTERN = "OAR017.error-patterns"; + public static final String EXCLUDE_PATTERNS = "get,me,search"; + + @RuleProperty( + key = "exclude_patterns", + description = "List of exlude pattenrs separated by coma.", + defaultValue = EXCLUDE_PATTERNS) + public String patternsString = EXCLUDE_PATTERNS; @Override public Set subscribedKinds() { @@ -30,11 +39,12 @@ public void visitNode(JsonNode node) { private void visitV2Node(JsonNode node) { String path = node.key().getTokenValue(); - if (!isCorrect(path)) addIssue(KEY, translate(MESSAGE), node.key()); + if (!isCorrect(path,node)) addIssue(KEY, translate(MESSAGE), node.key()); } - private boolean isCorrect(String path) { + private boolean isCorrect(String path, JsonNode node) { String[] parts = Stream.of(path.split("/")).filter(p -> !p.trim().isEmpty()).toArray(String[]::new); + String[] patterns = Stream.of(patternsString.split(",")).toArray(String[]::new); if (parts.length == 0) return true; boolean previousWasVariable = false; @@ -43,6 +53,10 @@ private boolean isCorrect(String path) { for (int i = 0; i < parts.length; i++) { boolean currentIsVariable = isVariable(parts[i]); + if(!currentIsVariable && Arrays.asList(patterns).contains(parts[i])){ + issuePatterns(parts[i],node); + } + if (previousWasVariable && currentIsVariable) { twoOrMoreVariablesInARow = true; break; @@ -57,4 +71,8 @@ private boolean isCorrect(String path) { private boolean isVariable(String part) { return '{' == part.charAt(0) && '}' == part.charAt(part.length() - 1); } + + private void issuePatterns(String pattern,JsonNode node){ + addIssue(KEY, translate(MESSAGE_PATTERN,pattern), node.key()); + } } \ No newline at end of file diff --git a/src/main/resources/messages/errors.properties b/src/main/resources/messages/errors.properties index 88e94070..b1294d7d 100644 --- a/src/main/resources/messages/errors.properties +++ b/src/main/resources/messages/errors.properties @@ -14,6 +14,7 @@ OAR012.error=Path params names, query params names, object names and property na OAR013.error=Default response is required OAR016.error=Numeric types requires a valid format OAR017.error=Resource path should alternate static and parametrized parts +OAR017.error-patterns=Pattern ''{0}'' not allowed OAR018.error=Operation not recommended for resource path: {0} OAR019.error={0} must be defined as a parameter in this operation OAR020.error={0} must be defined as a parameter in this operation diff --git a/src/main/resources/messages/errors_es.properties b/src/main/resources/messages/errors_es.properties index f79e9056..29f1000a 100644 --- a/src/main/resources/messages/errors_es.properties +++ b/src/main/resources/messages/errors_es.properties @@ -14,6 +14,7 @@ OAR012.error=Los nombres de parámetros de ruta, parámetros de consulta, objeto OAR013.error=La respuesta por defecto es obligatoria OAR016.error=Tipos numéricos requieren un formato válido OAR017.error=El path del recurso debe de alternar entre partes estáticas y parametrizadas +OAR017.error-patterns=Patrón ''{0}'' no permitido OAR018.error=Acción no recomendada para la ruta de recursos: {0} OAR019.error={0} debe ser definido como un parámetro en esta operación OAR020.error={0} debe ser definido como un parámetro en esta operación diff --git a/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java b/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java index 27b3f326..95db735d 100644 --- a/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java +++ b/src/test/java/apiaddicts/sonar/openapi/checks/operations/OAR017ResourcePathCheckTest.java @@ -1,12 +1,11 @@ package apiaddicts.sonar.openapi.checks.operations; +import apiaddicts.sonar.openapi.BaseCheckTest; import org.junit.Before; import org.junit.Test; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RuleType; -import apiaddicts.sonar.openapi.BaseCheckTest; - -import apiaddicts.sonar.openapi.checks.operations.OAR017ResourcePathCheck; +import org.sonar.api.server.rule.RuleParamType; public class OAR017ResourcePathCheckTest extends BaseCheckTest { @@ -33,4 +32,10 @@ public void verifyRule() { assertRuleProperties("OAR017 - ResourcePath - Resource path should alternate static and parametrized parts", RuleType.BUG, Severity.MAJOR, tags("operations")); } + @Override + public void verifyParameters() { + assertNumberOfParameters(1); + assertParameterProperties("exclude_patterns", "get,me,search", RuleParamType.STRING); + } + } \ No newline at end of file diff --git a/src/test/resources/checks/v3/operations/OAR017/plain.json b/src/test/resources/checks/v3/operations/OAR017/plain.json index 23133f76..1c9602cb 100644 --- a/src/test/resources/checks/v3/operations/OAR017/plain.json +++ b/src/test/resources/checks/v3/operations/OAR017/plain.json @@ -5,7 +5,7 @@ "title" : "Swagger Petstore" }, "paths" : { - "/one" : { + "/one/me" : { # Noncompliant {{OAR017: Pattern 'me' not allowed}} "get" : { "responses" : { "200" : { diff --git a/src/test/resources/checks/v3/operations/OAR017/plain.yaml b/src/test/resources/checks/v3/operations/OAR017/plain.yaml index c06718b5..e1d0c120 100644 --- a/src/test/resources/checks/v3/operations/OAR017/plain.yaml +++ b/src/test/resources/checks/v3/operations/OAR017/plain.yaml @@ -3,7 +3,7 @@ info: version: 1.0.0 title: Swagger Petstore paths: - /one: + /one/me: # Noncompliant {{OAR017: Pattern 'me' not allowed}} get: responses: 200: