Skip to content

Commit

Permalink
Add support for SecurityContexts.
Browse files Browse the repository at this point in the history
Swagger apikey support.
  • Loading branch information
noboomu committed May 22, 2017
1 parent 3a57213 commit b215afc
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 19 deletions.
10 changes: 10 additions & 0 deletions src/main/java/io/sinistral/proteus/modules/ApplicationModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
*/
package io.sinistral.proteus.modules;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

Expand All @@ -25,6 +27,7 @@

import io.sinistral.proteus.server.endpoints.EndpointInfo;
import io.undertow.server.DefaultResponseListener;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.RoutingHandler;

Expand All @@ -39,6 +42,7 @@ public class ApplicationModule extends AbstractModule
protected Set<EndpointInfo> registeredEndpoints = new TreeSet<>();
protected Set<Class<?>> registeredControllers = new HashSet<>();
protected Set<Class<? extends Service>> registeredServices = new HashSet<>();
protected Map<String,HandlerWrapper> registeredHandlerWrappers = new HashMap<>();

protected Config config;

Expand Down Expand Up @@ -85,12 +89,18 @@ protected void configure()
this.bind(new TypeLiteral<Set<Class<?>>>()
{
}).annotatedWith(Names.named("registeredControllers")).toInstance(registeredControllers);

this.bind(new TypeLiteral<Set<EndpointInfo>>()
{
}).annotatedWith(Names.named("registeredEndpoints")).toInstance(registeredEndpoints);

this.bind(new TypeLiteral<Set<Class<? extends Service>>>()
{
}).annotatedWith(Names.named("registeredServices")).toInstance(registeredServices);

this.bind(new TypeLiteral<Map<String,HandlerWrapper>>()
{
}).annotatedWith(Names.named("registeredHandlerWrappers")).toInstance(registeredHandlerWrappers);

this.bind(XmlMapper.class).toInstance(new XmlMapper());

Expand Down
22 changes: 15 additions & 7 deletions src/main/java/io/sinistral/proteus/server/ServerRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import io.sinistral.proteus.server.predicates.ServerPredicates;
import io.undertow.connector.PooledByteBuffer;
import io.undertow.security.api.SecurityContext;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.form.FormData;
import io.undertow.server.handlers.form.FormDataParser;
Expand Down Expand Up @@ -76,17 +77,12 @@ else if ( ServerPredicates.STRING_BODY_PREDICATE.resolve(exchange) )
{
this.extractBytes();
}
}



}
}


public Deque<FormData.FormValue> files(final String name)
{


if (this.form != null)
{
return form.get(name);
Expand Down Expand Up @@ -132,6 +128,14 @@ public Map<String, Deque<String>> getPathParameters()
return exchange.getPathParameters();
}

/**
* @return the security context
* @see io.undertow.server.security.api#getSecurityContext()
*/
public SecurityContext getSecurityContext()
{
return exchange.getSecurityContext();
}


private void extractBytes() throws IOException
Expand Down Expand Up @@ -238,7 +242,11 @@ public String rawPath()
return exchange.getRequestURI();
}


public HttpServerExchange exchange()
{
return exchange;
}

public void startAsync(final Executor executor, final Runnable runnable)
{
exchange.dispatch(executor, runnable);
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/io/sinistral/proteus/server/swagger/Reader.java
Original file line number Diff line number Diff line change
Expand Up @@ -1136,14 +1136,15 @@ private List<Parameter> getParameters(Type type, List<Annotation> annotations, j
typesToSkip.add(TypeFactory.defaultInstance().constructType(HttpServerExchange.class));
typesToSkip.add(TypeFactory.defaultInstance().constructType(ServerResponse.class));
typesToSkip.add(TypeFactory.defaultInstance().constructType(HttpHandler.class));
typesToSkip.add(TypeFactory.defaultInstance().constructType(io.undertow.server.session.Session.class));

final SwaggerExtension extension = chain.next();

if (typesToSkip.contains(type)) {
return Collections.emptyList();
}


annotations = new ArrayList<>(annotations);


Expand Down Expand Up @@ -1200,8 +1201,6 @@ else if( methodParameter.getType().getName().indexOf("java.lang") > -1 || method
final List<Parameter> body = new ArrayList<Parameter>();
if (!typesToSkip.contains(type)) {

// LOGGER.debug("getBody Parameters for {}", type);

Parameter param = ParameterProcessor.applyAnnotations(swagger, null, type, annotations);
if (param != null) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ public class ServerParameterExtension extends DefaultParameterExtension

public ServerParameterExtension()
{
super();


super();

}

@Override
Expand All @@ -47,8 +46,13 @@ public List<Parameter> extractParameters(List<Annotation> annotations, Type type
@Override
protected boolean shouldIgnoreType(Type type, Set<Type> typesToSkip)
{

if( type.getTypeName().contains("io.sinistral.proteus.server.ServerRequest") || type.getTypeName().contains("HttpServerExchange") || type.getTypeName().contains("HttpHandler") || type.getTypeName().contains("io.sinistral.proteus.server.ServerResponse"))

if( type.getTypeName().contains("io.sinistral.proteus.server.ServerRequest")
|| type.getTypeName().contains("HttpServerExchange")
|| type.getTypeName().contains("HttpHandler")
|| type.getTypeName().contains("io.sinistral.proteus.server.ServerResponse")
|| type.getTypeName().contains("io.undertow.server.session")
)
{
return true;
}
Expand Down
82 changes: 79 additions & 3 deletions src/main/java/io/sinistral/proteus/services/SwaggerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import java.util.jar.JarFile;
Expand All @@ -33,21 +34,32 @@
import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.typesafe.config.Config;

import com.typesafe.config.ConfigObject;

import io.sinistral.proteus.server.endpoints.EndpointInfo;
import io.sinistral.proteus.server.swagger.ServerParameterExtension;
import io.sinistral.proteus.server.swagger.ServerParameterExtension;
import io.swagger.jaxrs.ext.SwaggerExtension;
import io.swagger.jaxrs.ext.SwaggerExtensions;
import io.swagger.models.Info;
import io.swagger.models.SecurityRequirement;
import io.swagger.models.Swagger;
import io.swagger.models.auth.ApiKeyAuthDefinition;
import io.swagger.models.auth.SecuritySchemeDefinition;
import io.undertow.attribute.ExchangeAttribute;
import io.undertow.attribute.ExchangeAttributes;
import io.undertow.predicate.Predicate;
import io.undertow.predicate.Predicates;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.RoutingHandler;
import io.undertow.server.handlers.PredicateHandler;
import io.undertow.server.handlers.ResponseCodeHandler;
import io.undertow.server.handlers.resource.FileResourceManager;
import io.undertow.server.handlers.resource.ResourceHandler;
import io.undertow.util.CanonicalPathUtils;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
import io.undertow.util.Methods;


Expand Down Expand Up @@ -81,6 +93,10 @@ public class SwaggerService extends BaseService implements Supplier<RoutingHan
@Named("swagger.info")
protected Config swaggerInfo;

@Inject
@Named("swagger.security")
protected Config swaggerSecurity;

@Inject
@Named("swagger.redocPath")
protected String redocPath;
Expand Down Expand Up @@ -111,6 +127,10 @@ public class SwaggerService extends BaseService implements Supplier<RoutingHan
@Inject
@Named("registeredControllers")
protected Set<Class<?>> registeredControllers;

@Inject
@Named("registeredHandlerWrappers")
protected Map<String,HandlerWrapper> registeredHandlerWrappers;

protected ObjectMapper mapper = new ObjectMapper();

Expand Down Expand Up @@ -182,14 +202,70 @@ public void generateSwaggerSpec()
}

swagger.setInfo(info);

if(swaggerSecurity.hasPath("apiKeys"))
{
List<? extends ConfigObject> apiKeys = swaggerSecurity.getObjectList("apiKeys");

for(ConfigObject apiKey : apiKeys)
{
Config apiKeyConfig = apiKey.toConfig();

String key = apiKeyConfig.getString("key");
String name = apiKeyConfig.getString("name");
String value = apiKeyConfig.getString("value");

io.swagger.models.auth.In keyLocation = io.swagger.models.auth.In.valueOf(apiKeyConfig.getString("in"));

final Predicate predicate;

switch( keyLocation )
{
case HEADER:
{
ExchangeAttribute[] attributes = new ExchangeAttribute[]{ExchangeAttributes.requestHeader(HttpString.tryFromString(name)), ExchangeAttributes.constant(value)};
predicate = Predicates.equals( attributes );
break;
}
case QUERY:
{
predicate = Predicates.contains(ExchangeAttributes.queryString(),value);
break;
}
default:
predicate = Predicates.truePredicate();
break;
}

if(predicate != null)
{
log.debug("Adding apiKey handler " + name + " in " + keyLocation + " named " + key);

final HandlerWrapper wrapper = new HandlerWrapper()
{
@Override
public HttpHandler wrap(final HttpHandler handler)
{
return new PredicateHandler( predicate, handler, ResponseCodeHandler.HANDLE_403);
}
};

ApiKeyAuthDefinition keyAuthDefinition = new ApiKeyAuthDefinition(key, keyLocation);
swagger.addSecurityDefinition(name, keyAuthDefinition);

registeredHandlerWrappers.put(name, wrapper);
}
}
}


this.reader = new io.sinistral.proteus.server.swagger.Reader(swagger);

classes.forEach( c -> this.reader.read(c));

this.swagger = this.reader.getSwagger();




try
{
Expand Down
13 changes: 13 additions & 0 deletions src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ swagger {
produces = ["application/json"]
port = ${application.ports.http}

security =
{
apiKeys = [
{
name="defaultApiKey"
in="HEADER",
key="default-api-key"
value="123456789"
}
]
}


}

undertow
Expand Down

0 comments on commit b215afc

Please sign in to comment.