fr.example.springboot.Application.java Source code

Java tutorial

Introduction

Here is the source code for fr.example.springboot.Application.java

Source

package fr.example.springboot;

import static com.google.common.base.Predicates.or;
import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.builders.PathSelectors.regex;

import java.time.LocalDateTime;
import java.util.ArrayList;

import javax.inject.Inject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.orm.jpa.EntityScan;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.web.config.EnableSpringDataWebSupport;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.base.Predicate;

import fr.example.springboot.domain.User;
import fr.example.springboot.repository.UserRepository;
import fr.example.springboot.security.SecurityUtil;
import fr.example.springboot.security.UserDetailsServiceImpl;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.AuthorizationScopeBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.BasicAuth;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author Nour Labihi
 *
 */

@SpringBootApplication
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
@EntityScan(basePackageClasses = { User.class, Jsr310JpaConverters.class })
@EnableSpringDataWebSupport()
@EnableJpaAuditing(auditorAwareRef = "auditor")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    /**
     * renvoie l'utilisateur courant
     * @return
     */
    @Bean
    public AuditorAware<User> auditor() {
        return () -> SecurityUtil.currentUser();
    }

    /**
     * configure le mapper builder de Jackson
     * @return
     */
    @Bean
    public Jackson2ObjectMapperBuilder objectMapperBuilder() {

        Jackson2ObjectMapperBuilder mapperBuilder = new Jackson2ObjectMapperBuilder();
        mapperBuilder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
        mapperBuilder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
                DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,
                DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapperBuilder.featuresToEnable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);

        return mapperBuilder;
    }

    /**
     * Congifuration de documentation d'API
     * 
     * @author Nour LABIHI
     */
    @Configuration
    @EnableSwagger2
    @Profile(value = { "dev", "test", "staging" })
    public static class SwaggerConfig {

        @Bean
        public Docket userApi() {
            AuthorizationScope[] authScopes = new AuthorizationScope[1];
            authScopes[0] = new AuthorizationScopeBuilder().scope("read").description("read access").build();
            SecurityReference securityReference = SecurityReference.builder().reference("test").scopes(authScopes)
                    .build();

            ArrayList<SecurityContext> securityContexts = newArrayList(
                    SecurityContext.builder().securityReferences(newArrayList(securityReference)).build());
            return new Docket(DocumentationType.SWAGGER_2).directModelSubstitute(LocalDateTime.class, String.class)
                    .ignoredParameterTypes(User.class).securitySchemes(newArrayList(new BasicAuth("test")))
                    .securityContexts(securityContexts).apiInfo(apiInfo()).select().paths(apiPaths()).build();
        }

        @SuppressWarnings("unchecked")
        private Predicate<String> apiPaths() {
            return or(regex("/api/.*"));
        }

        private ApiInfo apiInfo() {
            return new ApiInfoBuilder().title("Exemple de template en utilisant AngularJs et Spring")
                    .description("documentation d'api ").termsOfServiceUrl("www.github.com/noure")
                    .contact("Nour LABIHI").license("Apache License Version 2.0")
                    .licenseUrl("https://github.com/springfox/springfox/blob/master/LICENSE").version("2.0")
                    .build();
        }

    }

    /**
     * Configuration de Spring Security
     * 
     * @author Nour LABIHI
     */

    @Configuration
    @Order(-10)
    public static class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Inject
        private UserRepository userRepository;

        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/**/*.html", //
                    "/css/**", //
                    "/js/**", //
                    "/i18n/**", // 
                    "/libs/**", //
                    "/img/**", //
                    "/webjars/**", //
                    "/ico/**");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.authorizeRequests().antMatchers("/api/signup", "/api/users/username-check").permitAll().and()
                    .authorizeRequests().regexMatchers(HttpMethod.GET, "^/api/users/[\\d]*(\\/)?$").authenticated()
                    .regexMatchers(HttpMethod.GET, "^/api/users(\\/)?(\\?.+)?$").hasRole("ADMIN")
                    .regexMatchers(HttpMethod.DELETE, "^/api/users/[\\d]*(\\/)?$").hasRole("ADMIN")
                    .regexMatchers(HttpMethod.POST, "^/api/users(\\/)?$").hasRole("ADMIN").and().authorizeRequests()
                    .antMatchers("/api/**").authenticated().and().authorizeRequests().anyRequest().permitAll().and()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().httpBasic()
                    .and().csrf().disable();
        }

        @Override
        protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder.userDetailsService(new UserDetailsServiceImpl(userRepository))
                    .passwordEncoder(passwordEncoder());
        }

        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Bean
        @Override
        public UserDetailsService userDetailsServiceBean() throws Exception {
            return super.userDetailsServiceBean();
        }

        @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            return passwordEncoder;
        }

    }
}