Skip to content

Commit c864f1b

Browse files
committed
refs #2312 - enhance security handling
1 parent 3d7bf36 commit c864f1b

File tree

12 files changed

+288
-105
lines changed

12 files changed

+288
-105
lines changed

modules/swagger-core/src/main/java/io/swagger/jackson/ModelResolver.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ else if(PrimitiveType.fromType(type) != null) {
549549
}
550550
}
551551
JAXBAnnotationsHelper.apply(member, property);
552-
applyBeanValidatorAnnotations(property, annotations);
552+
applyBeanValidatorAnnotations(property, annotations, model);
553553
}
554554
}
555555

@@ -845,21 +845,19 @@ private static Schema process(Schema id, String propertyName, JavaType type,
845845
}
846846
}
847847

848-
protected void applyBeanValidatorAnnotations(Schema property, Annotation[] annotations) {
848+
protected void applyBeanValidatorAnnotations(Schema property, Annotation[] annotations, Schema parent) {
849849
Map<String, Annotation> annos = new HashMap<String, Annotation>();
850850
if (annotations != null) {
851851
for (Annotation anno : annotations) {
852852
annos.put(anno.annotationType().getName(), anno);
853853
}
854854
}
855-
// TODO #2312
856855
if (annos.containsKey("javax.validation.constraints.NotNull")) {
857-
// property.setRequired(true);
856+
parent.addRequiredItem(property.getName());
858857
}
859858
if (annos.containsKey("javax.validation.constraints.Min")) {
860859
if ("integer".equals(property.getType()) || "number". equals(property.getType())) {
861860
Min min = (Min) annos.get("javax.validation.constraints.Min");
862-
// AbstractNumericProperty ap = (AbstractNumericProperty) property;
863861
property.setMinimum(new BigDecimal(min.value()));
864862
}
865863
}

modules/swagger-core/src/main/java/io/swagger/util/DeserializationModule.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import io.swagger.oas.models.media.Schema;
66
import io.swagger.oas.models.parameters.Parameter;
77
import io.swagger.oas.models.responses.ApiResponse;
8-
8+
import io.swagger.oas.models.security.SecurityScheme;
99

1010
public class DeserializationModule extends SimpleModule {
1111

@@ -23,8 +23,7 @@ public DeserializationModule(boolean includePathDeserializer,
2323
this.addDeserializer(Parameter.class, new ParameterDeserializer());
2424
// this.addDeserializer(RequestBody.class, new RequestBodyDeserializer());
2525

26-
// TODO #2312
27-
// this.addDeserializer(SecurityDefinition.class, new SecurityDefinitionDeserializer());
26+
this.addDeserializer(SecurityScheme.class, new SecuritySchemeDeserializer());
2827
}
2928

3029
public DeserializationModule() {

modules/swagger-core/src/main/java/io/swagger/util/SecurityDefinitionDeserializer.java

-35
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package io.swagger.util;
2+
3+
import com.fasterxml.jackson.core.JsonParseException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.core.JsonProcessingException;
6+
import com.fasterxml.jackson.databind.DeserializationContext;
7+
import com.fasterxml.jackson.databind.JsonDeserializer;
8+
import com.fasterxml.jackson.databind.JsonNode;
9+
import io.swagger.oas.models.security.OAuthFlows;
10+
import io.swagger.oas.models.security.SecurityScheme;
11+
12+
import java.io.IOException;
13+
import java.util.Arrays;
14+
15+
public class SecuritySchemeDeserializer extends JsonDeserializer<SecurityScheme> {
16+
@Override
17+
public SecurityScheme deserialize(JsonParser jp, DeserializationContext ctxt)
18+
throws IOException, JsonProcessingException {
19+
SecurityScheme result = null;
20+
21+
22+
JsonNode node = jp.getCodec().readTree(jp);
23+
24+
JsonNode inNode = node.get("type");
25+
26+
if (inNode != null) {
27+
String type = inNode.asText();
28+
if (Arrays.stream(SecurityScheme.Type.values()).noneMatch(t -> t.toString().equals(type))){
29+
// wrong type, throw exception
30+
throw new JsonParseException(jp, String.format("SecurityScheme type %s not allowed", type));
31+
}
32+
result = new SecurityScheme()
33+
.description(getFieldText("description", node));
34+
35+
if ("http".equals(type)) {
36+
result
37+
.type(SecurityScheme.Type.HTTP)
38+
.scheme(getFieldText("scheme", node))
39+
.bearerFormat(getFieldText("bearerFormat", node));
40+
} else if ("apiKey".equals(type)) {
41+
result
42+
.type(SecurityScheme.Type.APIKEY)
43+
.name(getFieldText("name", node))
44+
.in(getIn(getFieldText("in", node)));
45+
} else if ("openIdConnect".equals(type)) {
46+
result
47+
.type(SecurityScheme.Type.OPENIDCONNECT)
48+
.openIdConnectUrl(getFieldText("openIdConnectUrl", node));
49+
} else if ("oauth2".equals(type)) {
50+
result
51+
.type(SecurityScheme.Type.OAUTH2)
52+
.flows(Json.mapper().convertValue(node.get("flows"), OAuthFlows.class));
53+
}
54+
}
55+
56+
return result;
57+
}
58+
59+
private SecurityScheme.In getIn(String value) {
60+
return Arrays.stream(SecurityScheme.In.values()).filter(i -> i.toString().equals(value)).findFirst().orElse(null);
61+
}
62+
63+
private String getFieldText(String fieldName, JsonNode node) {
64+
JsonNode inNode = node.get(fieldName);
65+
if (inNode != null) {
66+
return inNode.asText();
67+
}
68+
return null;
69+
}
70+
}

modules/swagger-core/src/test/java/io/swagger/deserialization/JsonDeserializationTest.java

+56-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.swagger.deserialization;
22

33
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import io.swagger.oas.models.security.SecurityRequirement;
5+
import io.swagger.oas.models.security.SecurityScheme;
46
import io.swagger.util.TestUtils;
57
import io.swagger.oas.models.OpenAPI;
68
import io.swagger.oas.models.PathItem;
@@ -13,6 +15,7 @@
1315
import org.testng.annotations.Test;
1416

1517
import java.io.IOException;
18+
import java.util.List;
1619
import java.util.Map;
1720

1821
import static org.testng.Assert.assertEquals;
@@ -146,42 +149,74 @@ private void assertIsRefResponse(Object response, String expectedRef) {
146149
assertEquals(refResponse.get$ref(), expectedRef);
147150
}
148151

149-
// TODO #2312
150-
/*
151152
@Test
152153
public void testDeserializeSecurity() throws Exception {
153-
final Swagger swagger = TestUtils.deserializeJsonFileFromClasspath("specFiles/securityDefinitions.json", Swagger.class);
154+
final OpenAPI swagger = TestUtils.deserializeJsonFileFromClasspath("specFiles/securityDefinitions.json", OpenAPI.class);
154155

155156
final List<SecurityRequirement> security = swagger.getSecurity();
156-
final List<SecurityRequirement> securityRequirements = swagger.getSecurityRequirement();
157157
assertNotNull(security);
158-
assertEquals(security, securityRequirements);
158+
assertEquals(security.size(), 3);
159159

160-
assertEquals(security.size(), 2);
160+
final Map<String, SecurityScheme> securitySchemes = swagger.getComponents().getSecuritySchemes();
161+
assertNotNull(securitySchemes);
162+
assertEquals(securitySchemes.size(), 4);
163+
164+
{
165+
final SecurityScheme scheme = securitySchemes.get("petstore_auth");
166+
assertNotNull(scheme);
167+
assertEquals(scheme.getType().toString(), "oauth2");
168+
assertEquals(scheme.getFlows().getImplicit().getAuthorizationUrl(), "http://petstore.swagger.io/oauth/dialog");
169+
assertEquals(scheme.getFlows().getImplicit().getScopes().get("write:pets"), "modify pets in your account");
170+
assertEquals(scheme.getFlows().getImplicit().getScopes().get("read:pets"), "read your pets");
171+
}
172+
173+
{
174+
final SecurityScheme scheme = securitySchemes.get("api_key");
175+
assertNotNull(scheme);
176+
assertEquals(scheme.getType().toString(), "apiKey");
177+
assertEquals(scheme.getIn().toString(), "header");
178+
assertEquals(scheme.getName(), "api_key");
179+
}
180+
181+
{
182+
final SecurityScheme scheme = securitySchemes.get("http");
183+
assertNotNull(scheme);
184+
assertEquals(scheme.getType().toString(), "http");
185+
assertEquals(scheme.getScheme(), "basic");
186+
}
187+
188+
{
189+
final SecurityScheme scheme = securitySchemes.get("open_id_connect");
190+
assertNotNull(scheme);
191+
assertEquals(scheme.getType().toString(), "openIdConnect");
192+
assertEquals(scheme.getOpenIdConnectUrl(), "http://petstore.swagger.io/openid");
193+
}
161194

162195
{
163196
final SecurityRequirement securityRequirement = security.get(0);
164-
final Map<String, List<String>> requirements = securityRequirement.getRequirements();
165-
final List<String> basic_auth = requirements.get("basic_auth");
166-
assertNotNull(basic_auth);
167-
assertTrue(basic_auth.isEmpty());
168-
169-
final List<String> api_key = requirements.get("api_key");
170-
assertNotNull(api_key);
171-
assertTrue(api_key.isEmpty());
197+
final List<String> scopes = securityRequirement.get("petstore_auth");
198+
assertNotNull(scopes);
199+
assertEquals(scopes.size(), 2);
200+
assertTrue(scopes.contains("write:pets"));
201+
assertTrue(scopes.contains("read:pets"));
202+
172203
}
173204

174205
{
175206
final SecurityRequirement securityRequirement = security.get(1);
176-
final Map<String, List<String>> requirements = securityRequirement.getRequirements();
177-
final List<String> oauth2 = requirements.get("oauth2");
178-
assertNotNull(oauth2);
179-
assertFalse(oauth2.isEmpty());
207+
final List<String> scopes = securityRequirement.get("api_key");
208+
assertNotNull(scopes);
209+
assertTrue(scopes.isEmpty());
210+
211+
}
212+
213+
{
214+
final SecurityRequirement securityRequirement = security.get(2);
215+
final List<String> scopes = securityRequirement.get("http");
216+
assertNotNull(scopes);
217+
assertTrue(scopes.isEmpty());
180218

181-
assertEquals(oauth2.get(0), "hello");
182-
assertEquals(oauth2.get(1), "world");
183219
}
184220
}
185-
*/
186221

187222
}

modules/swagger-core/src/test/java/io/swagger/resolving/BeanValidatorTest.java

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public void readBeanValidatorTest() {
2121
final Schema model = schemas.get("BeanValidationsModel");
2222
final Map<String, Schema> properties = model.getProperties();
2323

24+
Assert.assertTrue(model.getRequired().contains("id"));
25+
2426
final IntegerSchema age = (IntegerSchema) properties.get("age");
2527
Assert.assertEquals(age.getMinimum(), new BigDecimal(13.0));
2628
Assert.assertEquals(age.getMaximum(), new BigDecimal(99.0));

modules/swagger-core/src/test/java/io/swagger/serialization/JsonSerializationTest.java

-22
Original file line numberDiff line numberDiff line change
@@ -51,26 +51,4 @@ public void testSerializeASpecWithResponseReferences() throws Exception {
5151
assertEquals(rebuilt.getPaths().get("/health").getGet().getResponses().get("200"), expectedResponse);
5252

5353
}
54-
55-
// TODO #2312
56-
/*
57-
@Test
58-
public void testSerializeSecurityRequirement_UsingSpecCompliantMethods() throws Exception {
59-
SecurityRequirement securityRequirement = new SecurityRequirement().requirement("oauth2", Arrays.asList("hello", "world"));
60-
61-
String json = Json.mapper().writeValueAsString(securityRequirement);
62-
assertEquals(json, "{\"oauth2\":[\"hello\",\"world\"]}");
63-
64-
securityRequirement = new SecurityRequirement().requirement("api_key");
65-
66-
json = Json.mapper().writeValueAsString(securityRequirement);
67-
assertEquals(json, "{\"api_key\":[]}");
68-
69-
Swagger swagger = new Swagger()
70-
.security(new SecurityRequirement().requirement("api_key").requirement("basic_auth"))
71-
.security(new SecurityRequirement().requirement("oauth2", Arrays.asList("hello", "world")));
72-
json = Json.mapper().writeValueAsString(swagger);
73-
assertEquals(json, "{\"swagger\":\"2.0\",\"security\":[{\"api_key\":[],\"basic_auth\":[]},{\"oauth2\":[\"hello\",\"world\"]}]}");
74-
}
75-
*/
7654
}

modules/swagger-core/src/test/java/io/swagger/serialization/SecurityDefinitionTest.java

+8
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,20 @@
2323
import io.swagger.oas.models.security.SecurityScheme;
2424
import io.swagger.oas.models.servers.Server;
2525
import io.swagger.util.ResourceUtils;
26+
import io.swagger.util.TestUtils;
2627
import org.testng.annotations.Test;
2728

2829
import java.io.IOException;
2930

3031
public class SecurityDefinitionTest {
3132

33+
@Test(description = "it should serialize correctly security")
34+
public void serializeSecurity() throws IOException {
35+
final OpenAPI oas = TestUtils.deserializeJsonFileFromClasspath("specFiles/securityDefinitions.json", OpenAPI.class);
36+
final String json = ResourceUtils.loadClassResource(getClass(), "specFiles/securityDefinitions.json");
37+
SerializationMatchers.assertEqualsToJson(oas, json);
38+
}
39+
3240
@Test(description = "it should create a model with security requirements")
3341
public void createModelWithSecurityRequirements() throws IOException{
3442
final Schema personModel = ModelConverters.getInstance().read(Person.class).get("Person");
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,59 @@
11
{
2-
"swagger" : "2.0",
3-
"security" : [ {
4-
"basic_auth" : [ ],
5-
"api_key" : [ ]
6-
}, {
7-
"oauth2" : [ "hello", "world" ]
8-
} ]
9-
}
2+
"openapi": "3.0.0",
3+
"info": {
4+
"version": "1.0.0",
5+
"license": {
6+
"name": "MIT"
7+
},
8+
"title": "Swagger Petstore"
9+
},
10+
"servers": [
11+
{
12+
"url": "http://petstore.swagger.io/v1"
13+
}
14+
],
15+
"paths": {},
16+
"security": [
17+
{
18+
"petstore_auth": [
19+
"write:pets",
20+
"read:pets"
21+
]
22+
},
23+
{
24+
"api_key": []
25+
},
26+
{
27+
"http": []
28+
}
29+
],
30+
"components": {
31+
"securitySchemes": {
32+
"petstore_auth": {
33+
"type": "oauth2",
34+
"flows": {
35+
"implicit": {
36+
"authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
37+
"scopes": {
38+
"write:pets": "modify pets in your account",
39+
"read:pets": "read your pets"
40+
}
41+
}
42+
}
43+
},
44+
"api_key": {
45+
"type": "apiKey",
46+
"name": "api_key",
47+
"in": "header"
48+
},
49+
"http": {
50+
"type": "http",
51+
"scheme": "basic"
52+
},
53+
"open_id_connect": {
54+
"type": "openIdConnect",
55+
"openIdConnectUrl": "http://petstore.swagger.io/openid"
56+
}
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)