Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,8 @@ protected Schema _createSchemaForEnum(Class<Enum<?>> enumClass) {

for (Enum<?> en : enumConstants) {
Field enumField = ReflectionUtils.findField(en.name(), enumClass);
if (null != enumField && enumField.isAnnotationPresent(Hidden.class)) {
// Skip enum field if @Hidden is present and ignoreHidden is not enabled
if (null != enumField && enumField.isAnnotationPresent(Hidden.class) && !Boolean.TRUE.equals(configuration.isIgnoreHidden())) {
continue;
}

Expand Down Expand Up @@ -1386,6 +1387,10 @@ protected boolean ignore(final Annotated member, final XmlAccessorType xmlAccess
}

protected boolean hasHiddenAnnotation(Annotated annotated) {
// If ignoreHidden is enabled, always return false (don't hide anything)
if (Boolean.TRUE.equals(configuration.isIgnoreHidden())) {
return false;
}
return annotated.hasAnnotation(Hidden.class) || (
annotated.hasAnnotation(io.swagger.v3.oas.annotations.media.Schema.class) &&
annotated.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class).hidden()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public String toString() {
private String openAPIVersion = "3.0.1";
private GroupsValidationStrategy groupsValidationStrategy = GroupsValidationStrategy.DEFAULT;
private String validatorProcessorClass;
private Boolean ignoreHidden = Boolean.FALSE;

public OpenAPI getOpenAPI() {
return openAPI;
Expand Down Expand Up @@ -161,4 +162,17 @@ public Configuration validatorProcessorClass(String validatorProcessorClass) {
this.validatorProcessorClass = validatorProcessorClass;
return this;
}

public Boolean isIgnoreHidden() {
return ignoreHidden;
}

public void setIgnoreHidden(Boolean ignoreHidden) {
this.ignoreHidden = ignoreHidden;
}

public Configuration ignoreHidden(Boolean ignoreHidden) {
this.ignoreHidden = ignoreHidden;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.core.util.Configuration;
import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.Map;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.*;

public class HiddenFieldTest {

@BeforeMethod
public void resetSingletons() {
// Singletons need to be reset due to configuration changes between tests
ModelConverters.reset();
}

@Test(description = "it should ignore a hidden field")
public void testHiddenField() {
final Map<String, Schema> models = ModelConverters.getInstance().read(ModelWithHiddenFields.class);
Expand Down Expand Up @@ -87,4 +92,49 @@ public String getHidden() {
return hidden;
}
}

@Test(description = "it should include hidden fields when ignoreHidden is true")
public void testIgnoreHiddenConfiguration() {
Configuration configuration = new Configuration()
.ignoreHidden(Boolean.TRUE);

final Map<String, Schema> models = ModelConverters.getInstance(configuration).read(ModelWithHiddenFields.class);

final Schema model = models.get("ModelWithHiddenFields");
assertNotNull(model);
assertEquals(model.getProperties().size(), 3);

final Schema idValue = (Schema) model.getProperties().get("id");
assertTrue(idValue instanceof IntegerSchema);

assertTrue(model.getRequired().contains("id"));

final Schema nameValue = (Schema) model.getProperties().get("name");
assertTrue(nameValue instanceof StringSchema);

// password field should now be included when ignoreHidden is true
final Schema passwordValue = (Schema) model.getProperties().get("password");
assertNotNull(passwordValue);
assertTrue(passwordValue instanceof StringSchema);
}

@Test(description = "it should include hidden fields in @JsonCreator when ignoreHidden is true")
public void testIgnoreHiddenConfigurationWithJsonCreator() {
Configuration configuration = new Configuration()
.ignoreHidden(Boolean.TRUE);

final Map<String, Schema> models = ModelConverters.getInstance(configuration).read(ModelWithHiddenFieldsInJsonCreator.class);

final Schema model = models.get("ModelWithHiddenFieldsInJsonCreator");
assertNotNull(model);
assertEquals(model.getProperties().size(), 2);

final Schema idValue = (Schema) model.getProperties().get("id");
assertTrue(idValue instanceof IntegerSchema);

// hidden field should now be included when ignoreHidden is true
final Schema hiddenValue = (Schema) model.getProperties().get("hidden");
assertNotNull(hiddenValue);
assertTrue(hiddenValue instanceof StringSchema);
}
}
2 changes: 2 additions & 0 deletions modules/swagger-gradle-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Parameter | Description | Required | Default
`openapi31`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |
`schemaResolution`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| DEFAULT |
`openAPIVersion`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| `3.0.1/3.1.0` |
`ignoreHidden`|Include ignored Operations/Parameters in the OpenApi output|false|false

**Note** parameter `openApiFile` corresponds to [config](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties) openAPI. It points to a location of a file in YAML or JSON format representing the input spec that will be merged with the resolved spec. Typically used to add Info section, or any other meta data.
An example of such file:
Expand Down Expand Up @@ -133,3 +134,4 @@ info:
- Since version 2.2.28, `openAPIVersion` parameter is available, allowing to specify the version of the OpenAPI specification to be used for the resolved spec.
- Since version 2.2.29, `groupsValidationStrategy` parameter is available, allowing to specify the strategy for resolving Validation annotations (`never`, `always`, `neverIfNoContext`).
- Since version 2.2.29, `validatorProcessorClass` parameter is available, allowing to specify a custom validator processor class, implementation of `io.swagger.v3.core.util.ValidatorProcessor`.
- Since version 2.2.40, `ignoreHidden` parameter is available, if set to true all ignored Operations/Parameters will be included in the OpenApi document
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ public enum Format {JSON, YAML, JSONANDYAML}
@Optional
public final Property<String> groupsValidationStrategy = getProject().getObjects().property(String.class);

/**
* @since 2.2.40
*/
@Input
@Optional
public final Property<Boolean> ignoreHidden = getProject().getObjects().property(Boolean.class);

public Property<String> getOutputFileName() {
return outputFileName;
}
Expand Down Expand Up @@ -307,6 +314,27 @@ public void setGroupsValidationStrategy(String groupsValidationStrategy) {
this.groupsValidationStrategy.set(groupsValidationStrategy);
}

/**
* @since 2.2.40
*/
public Property<Boolean> getIgnoreHidden() {
return ignoreHidden;
}

/**
* @since 2.2.40
*/
public void setIgnoreHidden(Boolean ignoreHidden) {
this.ignoreHidden.set(ignoreHidden);
}

/**
* @since 2.2.40
*/
public void setIgnoreHidden(@Nullable String ignoreHidden) {
setIgnoreHidden(ignoreHidden == null ? null : Boolean.valueOf(ignoreHidden));
}

public Property<String> getContextId() {
return contextId;
}
Expand Down Expand Up @@ -595,6 +623,11 @@ public void resolve() throws GradleException {
method.invoke(swaggerLoader, openAPIVersion.get());
}

if (ignoreHidden.isPresent()) {
method = swaggerLoaderClass.getDeclaredMethod("setIgnoreHidden", Boolean.class);
method.invoke(swaggerLoader, ignoreHidden.get());
}

method = swaggerLoaderClass.getDeclaredMethod("resolve");
Map<String, String> specs = (Map<String, String>) method.invoke(swaggerLoader);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class SwaggerConfiguration implements OpenAPIConfiguration {

private String validatorProcessorClass;

private Boolean ignoreHidden = Boolean.FALSE;


@Override
public String getDefaultResponseCode() {
Expand Down Expand Up @@ -471,6 +473,29 @@ public SwaggerConfiguration validatorProcessorClass(String validatorProcessorCla
return this;
}

/**
* @since 2.2.40
*/
@Override
public Boolean isIgnoreHidden() {
return ignoreHidden;
}

/**
* @since 2.2.40
*/
public void setIgnoreHidden(Boolean ignoreHidden) {
this.ignoreHidden = ignoreHidden;
}

/**
* @since 2.2.40
*/
public SwaggerConfiguration ignoreHidden(Boolean ignoreHidden) {
this.ignoreHidden = ignoreHidden;
return this;
}

public Configuration toConfiguration() {
Configuration configuration = new Configuration();

Expand All @@ -483,6 +508,7 @@ public Configuration toConfiguration() {
configuration.setOpenAPIVersion(getOpenAPIVersion());
configuration.setGroupsValidationStrategy(getGroupsValidationStrategy());
configuration.setValidatorProcessorClass(getValidatorProcessorClass());
configuration.setIgnoreHidden(isIgnoreHidden());

return configuration;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,9 @@ public interface OpenAPIConfiguration {
* @since 2.2.29
*/
public Configuration toConfiguration();

/**
* @since 2.2.40
*/
Boolean isIgnoreHidden();
}
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ public OpenAPI read(Class<?> cls,
openAPI.setOpenapi("3.1.0");
}

if (hidden != null) { // || (apiPath == null && !isSubresource)) {
// Skip class if @Hidden annotation is present and ignoreHidden is not enabled
if (hidden != null && !Boolean.TRUE.equals(config.isIgnoreHidden())) { // || (apiPath == null && !isSubresource)) {
return openAPI;
}

Expand Down Expand Up @@ -1611,11 +1612,13 @@ private boolean isEmptyComponents(Components components) {

protected boolean isOperationHidden(Method method) {
io.swagger.v3.oas.annotations.Operation apiOperation = ReflectionUtils.getAnnotation(method, io.swagger.v3.oas.annotations.Operation.class);
if (apiOperation != null && apiOperation.hidden()) {
// Check @Operation(hidden=true) - respect ignoreHidden configuration
if (apiOperation != null && apiOperation.hidden() && !Boolean.TRUE.equals(config.isIgnoreHidden())) {
return true;
}
// Check @Hidden annotation - respect ignoreHidden configuration
Hidden hidden = method.getAnnotation(Hidden.class);
if (hidden != null) {
if (hidden != null && !Boolean.TRUE.equals(config.isIgnoreHidden())) {
return true;
}
if (config != null && !Boolean.TRUE.equals(config.isReadAllResources()) && apiOperation == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public class SwaggerLoader {

private String openAPIVersion;

private Boolean ignoreHidden = Boolean.FALSE;

/**
* @since 2.0.6
*/
Expand Down Expand Up @@ -318,6 +320,20 @@ public void setOpenAPIVersion(String openAPIVersion) {
this.openAPIVersion = openAPIVersion;
}

/**
* @since 2.2.40
*/
public Boolean getIgnoreHidden() {
return ignoreHidden;
}

/**
* @since 2.2.40
*/
public void setIgnoreHidden(Boolean ignoreHidden) {
this.ignoreHidden = ignoreHidden;
}

public Map<String, String> resolve() throws Exception{

Set<String> ignoredRoutesSet = null;
Expand Down Expand Up @@ -370,7 +386,8 @@ public Map<String, String> resolve() throws Exception{
.alwaysResolveAppPath(alwaysResolveAppPath)
.skipResolveAppPath(skipResolveAppPath)
.openAPI31(openAPI31)
.convertToOpenAPI31(convertToOpenAPI31);
.convertToOpenAPI31(convertToOpenAPI31)
.ignoreHidden(ignoreHidden);
if (schemaResolution != null) {
config.schemaResolution(Schema.SchemaResolution.valueOf(schemaResolution));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.swagger.v3.jaxrs2.annotations.operations;

import io.swagger.v3.jaxrs2.Reader;
import io.swagger.v3.jaxrs2.annotations.AbstractAnnotationTest;
import io.swagger.v3.jaxrs2.resources.GenericResponsesResource;
import io.swagger.v3.jaxrs2.resources.HiddenAnnotatedUserResource;
Expand All @@ -19,12 +20,16 @@
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.integration.SwaggerConfiguration;
import io.swagger.v3.oas.models.OpenAPI;
import org.testng.annotations.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.POST;
import java.io.IOException;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;

public class AnnotatedOperationMethodTest extends AbstractAnnotationTest {
@Test
Expand Down Expand Up @@ -1557,4 +1562,42 @@ static class DeprecatedSimpleGetOperationTest {
public void simpleGet() {
}
}

@Test(description = "reads hidden operation when ignoreHidden is true")
public void testHiddenUserResourceWithIgnoreHiddenConfiguration() throws IOException {
SwaggerConfiguration config = new SwaggerConfiguration()
.openAPI(new OpenAPI())
.ignoreHidden(Boolean.TRUE);
Reader reader = new Reader(config);
OpenAPI openAPI = reader.read(HiddenUserResource.class);

assertNotNull(openAPI);
assertNotNull(openAPI.getPaths());
assertNotNull(openAPI.getPaths().get("/user"));
assertNotNull(openAPI.getPaths().get("/user").getPost());
assertEquals(openAPI.getPaths().get("/user").getPost().getSummary(), "Create user");
}

@Test(description = "includes operation with @Operation(hidden=true) when ignoreHidden is true")
public void testOperationHiddenTrueWithIgnoreHiddenConfiguration() throws IOException {
SwaggerConfiguration config = new SwaggerConfiguration()
.openAPI(new OpenAPI())
.ignoreHidden(Boolean.TRUE);
Reader reader = new Reader(config);
OpenAPI openAPI = reader.read(ResourceWithHiddenOperation.class);

assertNotNull(openAPI);
assertNotNull(openAPI.getPaths());
assertNotNull(openAPI.getPaths().get("/test"));
assertNotNull(openAPI.getPaths().get("/test").getPost());
assertEquals(openAPI.getPaths().get("/test").getPost().getSummary(), "Hidden operation");
}

@Path("/test")
static class ResourceWithHiddenOperation {
@POST
@Operation(hidden = true, summary = "Hidden operation")
public void hiddenOperation() {
}
}
}
2 changes: 2 additions & 0 deletions modules/swagger-maven-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ Parameter | Description | Required | Default
`openapi31`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| false |
`schemaResolution`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| DEFAULT |
`openAPIVersion`|see [configuration property](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties)| `3.0.1/3.1.0` |
`ignoreHidden`|Include ignored Operations/Parameters in the OpenApi output|false|false

***

Expand All @@ -220,3 +221,4 @@ Since version 2.2.24, `schemaResolution` parameter is available, allowing to spe
Since version 2.2.28, `openAPIVersion` parameter is available, allowing to specify the version of the OpenAPI specification to be used for the resolved spec.
Since version 2.2.29, `groupsValidationStrategy` parameter is available, allowing to specify the strategy for resolving Validation annotations (`never`, `always`, `neverIfNoContext`).
Since version 2.2.29, `validatorProcessorClass` parameter is available, allowing to specify a custom validator processor class, implementation of `io.swagger.v3.core.util.ValidatorProcessor`.
Since version 2.2.40, `ignoreHidden` parameter is available, if set to true all ignored Operations/Parameters will be included in the OpenApi document
Loading