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
16 changes: 12 additions & 4 deletions x-auth-security/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.0.RC3</version>
<version>1.0.0.RC5</version>
</parent>
<properties>
<spring-security.version>3.2.1.RELEASE</spring-security.version>
<start-class>example.Application</start-class>
<spring.version>4.0.2.RELEASE</spring.version>
<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
<java.version>1.7</java.version>
</properties>
<dependencyManagement>
<dependencies>
Expand All @@ -41,11 +42,9 @@
<artifactId>angularjs</artifactId>
<version>1.2.13</version>
</dependency>

</dependencies>
</dependencyManagement>
<dependencies>

<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
Expand All @@ -66,7 +65,16 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>com.mangofactory</groupId>
<artifactId>swagger-springmvc</artifactId>
<version>0.8.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.3.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down
21 changes: 18 additions & 3 deletions x-auth-security/src/main/java/example/Application.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package example;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiModel;
import com.wordnik.swagger.annotations.ApiModelProperty;
import com.wordnik.swagger.annotations.ApiOperation;
import example.xauth.XAuthTokenConfigurer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
Expand All @@ -23,6 +27,8 @@
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

Expand Down Expand Up @@ -159,33 +165,39 @@ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundEx
}

@RestController
@Api(value = "news", description = "News API")
class NewsController {

Map<Long, NewsEntry> entries = new ConcurrentHashMap<Long, NewsEntry>();

@RequestMapping("/news")
@RequestMapping(value = "/news", method = RequestMethod.GET)
@ApiOperation(value = "Get News", notes = "Returns news items")
Collection<NewsEntry> entries() {
return this.entries.values();
}

@RequestMapping(value = "/news/{id}", method = RequestMethod.DELETE)
@ApiOperation(value = "Delete News item", notes = "Deletes news item by id")
NewsEntry remove(@PathVariable Long id) {
return this.entries.remove(id);
}

@RequestMapping(value = "/news/{id}", method = RequestMethod.GET)
@ApiOperation(value = "Get a news item", notes = "Returns a news item")
NewsEntry entry(@PathVariable Long id) {
return this.entries.get(id);
}

@RequestMapping(value = "/news/{id}", method = RequestMethod.POST)
NewsEntry update(@RequestBody NewsEntry news) {
@ApiOperation(value = "Update News", notes = "Updates a news item")
NewsEntry update(@Valid @RequestBody NewsEntry news) {
this.entries.put(news.getId(), news);
return news;
}

@RequestMapping(value = "/news", method = RequestMethod.POST)
NewsEntry add(@RequestBody NewsEntry news) {
@ApiOperation(value = "Create News", notes = "Creates a news item")
NewsEntry add(@Valid @RequestBody NewsEntry news) {
long id = 10 + new Random().nextInt(99);
news.setId(id);
this.entries.put(id, news);
Expand All @@ -197,8 +209,11 @@ NewsEntry add(@RequestBody NewsEntry news) {
this.entries.put(i, new NewsEntry(i, "Title #" + i));
}

@ApiModel("News Entry")
public static class NewsEntry {
@ApiModelProperty(value = "the id of the item", required = true)
private long id;
@NotNull
private String content;

public NewsEntry() {}
Expand Down
50 changes: 50 additions & 0 deletions x-auth-security/src/main/java/example/config/ApiPathProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package example.config;

import com.mangofactory.swagger.core.SwaggerPathProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.ServletContext;

public class ApiPathProvider implements SwaggerPathProvider {
private SwaggerPathProvider defaultSwaggerPathProvider;
@Autowired
private ServletContext servletContext;

private String docsLocation;

public ApiPathProvider(String docsLocation) {
this.docsLocation = docsLocation;
}

@Override
public String getApiResourcePrefix() {
return defaultSwaggerPathProvider.getApiResourcePrefix();
}

public String getAppBasePath() {
return UriComponentsBuilder
.fromHttpUrl(docsLocation)
.path(servletContext.getContextPath())
.build()
.toString();
}

@Override
public String getSwaggerDocumentationBasePath() {
return UriComponentsBuilder
.fromHttpUrl(getAppBasePath())
.pathSegment("api-docs/")
.build()
.toString();
}

@Override
public String getRequestMappingEndpoint(String requestMappingPattern) {
return defaultSwaggerPathProvider.getRequestMappingEndpoint(requestMappingPattern);
}

public void setDefaultSwaggerPathProvider(SwaggerPathProvider defaultSwaggerPathProvider) {
this.defaultSwaggerPathProvider = defaultSwaggerPathProvider;
}
}
180 changes: 180 additions & 0 deletions x-auth-security/src/main/java/example/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package example.config;

import com.mangofactory.swagger.configuration.JacksonScalaSupport;
import com.mangofactory.swagger.configuration.SpringSwaggerConfig;
import com.mangofactory.swagger.configuration.SpringSwaggerModelConfig;
import com.mangofactory.swagger.configuration.SwaggerGlobalSettings;
import com.mangofactory.swagger.core.DefaultSwaggerPathProvider;
import com.mangofactory.swagger.core.SwaggerApiResourceListing;
import com.mangofactory.swagger.core.SwaggerPathProvider;
import com.mangofactory.swagger.scanners.ApiListingReferenceScanner;
import com.wordnik.swagger.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;

@Configuration
@ComponentScan(basePackages = "com.mangofactory.swagger")
public class SwaggerConfig {

public static final List<String> DEFAULT_INCLUDE_PATTERNS = Arrays.asList("/.*");
public static final String SWAGGER_GROUP = "mobile-api";

@Value("${app.docs}")
private String docsLocation;

@Autowired
private SpringSwaggerConfig springSwaggerConfig;
@Autowired
private SpringSwaggerModelConfig springSwaggerModelConfig;

/**
* Adds the jackson scala module to the MappingJackson2HttpMessageConverter registered with spring
* Swagger core models are scala so we need to be able to convert to JSON
* Also registers some custom serializers needed to transform swagger models to swagger-ui required json format
*/
@Bean
public JacksonScalaSupport jacksonScalaSupport() {
JacksonScalaSupport jacksonScalaSupport = new JacksonScalaSupport();
//Set to false to disable
jacksonScalaSupport.setRegisterScalaModule(true);
return jacksonScalaSupport;
}


/**
* Global swagger settings
*/
@Bean
public SwaggerGlobalSettings swaggerGlobalSettings() {
SwaggerGlobalSettings swaggerGlobalSettings = new SwaggerGlobalSettings();
swaggerGlobalSettings.setGlobalResponseMessages(springSwaggerConfig.defaultResponseMessages());
swaggerGlobalSettings.setIgnorableParameterTypes(springSwaggerConfig.defaultIgnorableParameterTypes());
swaggerGlobalSettings.setParameterDataTypes(springSwaggerModelConfig.defaultParameterDataTypes());
return swaggerGlobalSettings;
}

/**
* API Info as it appears on the swagger-ui page
*/
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo(
"News API",
"Mobile applications and beyond!",
"https://helloreverb.com/terms/",
"matt@raibledesigns.com",
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0.html"
);
return apiInfo;
}

/**
* Configure a SwaggerApiResourceListing for each swagger instance within your app. e.g. 1. private 2. external apis
* Required to be a spring bean as spring will call the postConstruct method to bootstrap swagger scanning.
*
* @return
*/
@Bean
public SwaggerApiResourceListing swaggerApiResourceListing() {
//The group name is important and should match the group set on ApiListingReferenceScanner
//Note that swaggerCache() is by DefaultSwaggerController to serve the swagger json
SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(springSwaggerConfig.swaggerCache(), SWAGGER_GROUP);

//Set the required swagger settings
swaggerApiResourceListing.setSwaggerGlobalSettings(swaggerGlobalSettings());

//Use a custom path provider or springSwaggerConfig.defaultSwaggerPathProvider()
swaggerApiResourceListing.setSwaggerPathProvider(apiPathProvider());

//Supply the API Info as it should appear on swagger-ui web page
swaggerApiResourceListing.setApiInfo(apiInfo());

//Global authorization - see the swagger documentation
swaggerApiResourceListing.setAuthorizationTypes(authorizationTypes());

//Every SwaggerApiResourceListing needs an ApiListingReferenceScanner to scan the spring request mappings
swaggerApiResourceListing.setApiListingReferenceScanner(apiListingReferenceScanner());
return swaggerApiResourceListing;
}

@Bean
/**
* The ApiListingReferenceScanner does most of the work.
* Scans the appropriate spring RequestMappingHandlerMappings
* Applies the correct absolute paths to the generated swagger resources
*/
public ApiListingReferenceScanner apiListingReferenceScanner() {
ApiListingReferenceScanner apiListingReferenceScanner = new ApiListingReferenceScanner();

//Picks up all of the registered spring RequestMappingHandlerMappings for scanning
apiListingReferenceScanner.setRequestMappingHandlerMapping(springSwaggerConfig.swaggerRequestMappingHandlerMappings());

//Excludes any controllers with the supplied annotations
apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig.defaultExcludeAnnotations());

//
apiListingReferenceScanner.setResourceGroupingStrategy(springSwaggerConfig.defaultResourceGroupingStrategy());

//Path provider used to generate the appropriate uri's
apiListingReferenceScanner.setSwaggerPathProvider(apiPathProvider());

//Must match the swagger group set on the SwaggerApiResourceListing
apiListingReferenceScanner.setSwaggerGroup(SWAGGER_GROUP);

//Only include paths that match the supplied regular expressions
apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);

return apiListingReferenceScanner;
}

/**
* Example of a custom path provider
*/
@Bean
public ApiPathProvider apiPathProvider() {
ApiPathProvider apiPathProvider = new ApiPathProvider(docsLocation);
apiPathProvider.setDefaultSwaggerPathProvider(springSwaggerConfig.defaultSwaggerPathProvider());
return apiPathProvider;
}


private List<AuthorizationType> authorizationTypes() {
ArrayList<AuthorizationType> authorizationTypes = new ArrayList<>();

List<AuthorizationScope> authorizationScopeList = newArrayList();
authorizationScopeList.add(new AuthorizationScope("global", "access all"));

List<GrantType> grantTypes = newArrayList();

LoginEndpoint loginEndpoint = new LoginEndpoint(apiPathProvider().getAppBasePath() + "/user/authenticate");
grantTypes.add(new ImplicitGrant(loginEndpoint, "access_token"));

return authorizationTypes;
}

@Bean
public SwaggerPathProvider relativeSwaggerPathProvider() {
return new ApiRelativeSwaggerPathProvider();
}

private class ApiRelativeSwaggerPathProvider extends DefaultSwaggerPathProvider {
@Override
public String getAppBasePath() {
return "/";
}

@Override
public String getSwaggerDocumentationBasePath() {
return "/api-docs";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
Expand All @@ -25,6 +27,7 @@
* @author Josh Long (josh@joshlong.com)
*/
@RestController
@Api("user")
public class UserXAuthTokenController {

private final TokenUtils tokenUtils = new TokenUtils();
Expand All @@ -38,6 +41,7 @@ public UserXAuthTokenController(AuthenticationManager am, UserDetailsService use
}

@RequestMapping(value = "/authenticate", method = { RequestMethod.POST })
@ApiOperation(value = "authenticate")
public UserTransfer authorize(@RequestParam String username, @RequestParam String password) {

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Expand Down
3 changes: 2 additions & 1 deletion x-auth-security/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
secret=secret
secret=secret
app.docs=http://localhost:8080
Loading