From adb8e06f0a66a36789565ad3cf87c03d121fec83 Mon Sep 17 00:00:00 2001 From: Fabio Formosa Date: Fri, 30 Sep 2022 23:42:30 +0200 Subject: [PATCH] #63 added mvc tests on security --- quartz-manager-frontend/src/app/app.module.ts | 4 +- .../quartz-manager-starter-security/pom.xml | 51 ++++- .../security/WebSecurityConfigJWT.java | 184 +++++++++++++++++ .../configuration/WebSecurityConfigJWT.java | 194 ------------------ .../properties/JwtSecurityProperties.java | 33 --- .../JwtAuthenticationSuccessHandlerImpl.java | 2 +- .../security/helpers/impl/JwtTokenHelper.java | 2 +- .../security/models/Authority.java | 55 ----- .../quartzmanager/security/models/User.java | 132 ------------ .../properties/InMemoryAccountProperties.java | 2 +- .../properties/JwtSecurityProperties.java | 35 ++++ .../main/resources/META-INF/spring.factories | 8 +- .../security/AbstractSecurityLoginTest.java | 29 +++ .../security/SecurityControllerTest.java | 71 +++++++ .../security/SecurityLoginViaCookieTest.java | 40 ++++ .../SecurityLoginViaDefaultStrategyTest.java | 30 +++ ...urityLoginViaHeaderAndLoginFilterTest.java | 38 ++++ .../security/SecurityLoginViaHeaderTest.java | 37 ++++ .../security/SpringApplicationTest.java | 7 + .../security/controllers/TestController.java | 33 +++ .../quartz-manager-web-showcase/pom.xml | 14 +- .../src/main/resources/application.yml | 2 - 22 files changed, 559 insertions(+), 444 deletions(-) create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/WebSecurityConfigJWT.java delete mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/WebSecurityConfigJWT.java delete mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/properties/JwtSecurityProperties.java delete mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/Authority.java delete mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/User.java rename quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/{configuration => }/properties/InMemoryAccountProperties.java (89%) create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/properties/JwtSecurityProperties.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/AbstractSecurityLoginTest.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityControllerTest.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaCookieTest.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaDefaultStrategyTest.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderAndLoginFilterTest.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderTest.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SpringApplicationTest.java create mode 100644 quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/controllers/TestController.java diff --git a/quartz-manager-frontend/src/app/app.module.ts b/quartz-manager-frontend/src/app/app.module.ts index 939bdf1..f0fbfb7 100644 --- a/quartz-manager-frontend/src/app/app.module.ts +++ b/quartz-manager-frontend/src/app/app.module.ts @@ -51,18 +51,17 @@ import { AuthService, UserService, SchedulerService, - JobService, ConfigService, ProgressWebsocketService, LogsWebsocketService, getHtmlBaseUrl, TriggerService } from './services'; -import { ChangePasswordComponent } from './views/change-password/change-password.component'; import { ForbiddenComponent } from './views/forbidden/forbidden.component'; import { APP_BASE_HREF } from '@angular/common'; import { environment } from '../environments/environment'; import {SimpleTriggerConfigComponent} from './components/simple-trigger-config'; +import JobService from './services/job.service'; export function initUserFactory(userService: UserService) { return () => userService.jsessionInitUser(); @@ -116,7 +115,6 @@ export function jwtOptionsFactory(apiService: ApiService) { SchedulerControlComponent, LogsPanelComponent, ProgressPanelComponent, - ChangePasswordComponent, ForbiddenComponent, TriggerListComponent ], diff --git a/quartz-manager-parent/quartz-manager-starter-security/pom.xml b/quartz-manager-parent/quartz-manager-starter-security/pom.xml index 5d80594..bda80c3 100644 --- a/quartz-manager-parent/quartz-manager-starter-security/pom.xml +++ b/quartz-manager-parent/quartz-manager-starter-security/pom.xml @@ -1,16 +1,17 @@ - + 4.0.0 it.fabioformosa.quartz-manager quartz-manager-parent 3.1.1-SNAPSHOT - + quartz-manager-starter-security - + Quartz Manager Starter Security Security Layer for Quartz Manager. Import it in your spring webapp - + https://github.com/fabioformosa/quartz-manager ${basedir}/../.. @@ -18,16 +19,12 @@ UTF-8 1.8 - + org.springframework.boot spring-boot-starter-security - - org.springframework.boot - spring-boot-starter-data-jpa - org.springframework.boot spring-boot-configuration-processor @@ -51,7 +48,39 @@ javax.servlet javax.servlet-api provided - + + + + + org.junit.platform + junit-platform-launcher + test + + + org.springframework.boot + spring-boot-test-autoconfigure + test + + + org.springframework.security + spring-security-test + test + + + org.springframework + spring-test + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + test + - + diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/WebSecurityConfigJWT.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/WebSecurityConfigJWT.java new file mode 100644 index 0000000..80a5631 --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/WebSecurityConfigJWT.java @@ -0,0 +1,184 @@ +package it.fabioformosa.quartzmanager.security; + +import org.apache.commons.lang3.BooleanUtils; +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.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +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.EnableWebSecurity; +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.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.HttpStatusEntryPoint; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import it.fabioformosa.quartzmanager.security.properties.InMemoryAccountProperties; +import it.fabioformosa.quartzmanager.security.properties.JwtSecurityProperties; +import it.fabioformosa.quartzmanager.security.helpers.LoginConfigurer; +import it.fabioformosa.quartzmanager.security.helpers.impl.AuthenticationFailureHandler; +import it.fabioformosa.quartzmanager.security.helpers.impl.AuthenticationSuccessHandler; +import it.fabioformosa.quartzmanager.security.helpers.impl.FormLoginConfig; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtAuthenticationSuccessHandler; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtAuthenticationSuccessHandlerImpl; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenAuthenticationFilter; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenHelper; +import it.fabioformosa.quartzmanager.security.helpers.impl.JwtUsernamePasswordFiterLoginConfig; +import it.fabioformosa.quartzmanager.security.helpers.impl.LogoutSuccess; +import it.fabioformosa.quartzmanager.security.helpers.impl.QuartzManagerHttpSecurity; + +/** + * @author Fabio.Formosa + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter { + + private static final String[] PATTERNS_SWAGGER_UI = {"/swagger-ui.html", "/v3/api-docs/**", "/swagger-resources/**", "/webjars/**"}; + + public static final String QUARTZ_MANAGER_CONTEXT_PATH = "/quartz-manager"; + protected static final String LOGIN_PATH = QUARTZ_MANAGER_CONTEXT_PATH + "/api/login"; + private static final String LOGOUT_PATH = QUARTZ_MANAGER_CONTEXT_PATH + "/api/logout"; + + private static final String WEBJAR_PATH = "/quartz-manager-ui"; + + @Value("${server.servlet.context-path:/}") + private String contextPath; + + @Value("${app.name:quartz-manager}") + private String appName; + + @Value("${quartz-manager.security.login-model.form-login-enabled:true}") + private Boolean formLoginEnabled; + @Value("${quartz-manager.security.login-model.userpwd-filter-enabled:false}") + private Boolean userpwdFilterEnabled; + + @Autowired + private JwtSecurityProperties jwtSecurityProps; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private InMemoryAccountProperties inMemoryAccountProps; + + + @Override + public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { + configureInMemoryAuthentication(authenticationManagerBuilder); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable() // + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() // + .exceptionHandling().authenticationEntryPoint(restAuthEntryPoint()).and() // + .addFilterBefore(jwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class) // + .authorizeRequests().anyRequest().authenticated(); + + QuartzManagerHttpSecurity.from(http).withLoginConfigurer(loginConfigurer(), logoutConfigurer()) // + .login(LOGIN_PATH, authenticationManager()).logout(LOGOUT_PATH); + + // temporary disabled csfr + // http.csrf().ignoringAntMatchers("/api/login", "/api/signup") // + // .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // + } + + @Override + public void configure(WebSecurity web) { + web.ignoring()// + .antMatchers(HttpMethod.GET, PATTERNS_SWAGGER_UI) // + .antMatchers(HttpMethod.GET, WEBJAR_PATH + "/css/**", WEBJAR_PATH + "/js/**", WEBJAR_PATH + "/img/**", WEBJAR_PATH + "/lib/**", WEBJAR_PATH + "/assets/**"); + } + + private void configureInMemoryAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { + PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); + if (inMemoryAccountProps.isEnabled() && inMemoryAccountProps.getUsers() != null && !inMemoryAccountProps.getUsers().isEmpty()) { + InMemoryUserDetailsManagerConfigurer inMemoryAuth = authenticationManagerBuilder.inMemoryAuthentication(); + inMemoryAccountProps.getUsers() + .forEach(u -> inMemoryAuth + .withUser(u.getName()) + .password(encoder.encode(u.getPassword())) + .roles(u.getRoles().toArray(new String[0]))); + } + } + + @Bean + CorsConfigurationSource corsConfigurationSource() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues()); + return source; + } + + public LoginConfigurer formLoginConfigurer() { + JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler = jwtAuthenticationSuccessHandler(); + AuthenticationSuccessHandler authenticationSuccessHandler = new AuthenticationSuccessHandler(jwtAuthenticationSuccessHandler); + AuthenticationFailureHandler authenticationFailureHandler = new AuthenticationFailureHandler(); + LoginConfigurer loginConfigurer = new FormLoginConfig(authenticationSuccessHandler, authenticationFailureHandler); + return loginConfigurer; + } + + @Bean + public JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler() { + JwtTokenHelper jwtTokenHelper = jwtTokenHelper(); + JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler = new JwtAuthenticationSuccessHandlerImpl(contextPath, jwtSecurityProps, jwtTokenHelper, objectMapper); + return jwtAuthenticationSuccessHandler; + } + +// @Bean + public JwtTokenAuthenticationFilter jwtAuthenticationTokenFilter() { + return new JwtTokenAuthenticationFilter(jwtTokenHelper(), userDetailsService); + } + + @Bean + public JwtTokenHelper jwtTokenHelper() { + return new JwtTokenHelper(appName, jwtSecurityProps); + } + + public LoginConfigurer loginConfigurer() { + if (BooleanUtils.isTrue(userpwdFilterEnabled)) + return userpwdFilterLoginConfigurer(); + if (BooleanUtils.isNotFalse(formLoginEnabled)) + return formLoginConfigurer(); + throw new RuntimeException("No login configurer enabled!"); + } + + public LogoutSuccess logoutConfigurer() { + return new LogoutSuccess(objectMapper); + } + + @Bean + public AuthenticationEntryPoint restAuthEntryPoint() { + return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED); + } + + @Bean + @Override + public UserDetailsService userDetailsServiceBean() throws Exception { + return super.userDetailsServiceBean(); + } + + public LoginConfigurer userpwdFilterLoginConfigurer() { + LoginConfigurer loginConfigurer = new JwtUsernamePasswordFiterLoginConfig(jwtAuthenticationSuccessHandler()); + return loginConfigurer; + } + +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/WebSecurityConfigJWT.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/WebSecurityConfigJWT.java deleted file mode 100644 index acd4b43..0000000 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/WebSecurityConfigJWT.java +++ /dev/null @@ -1,194 +0,0 @@ -package it.fabioformosa.quartzmanager.security.configuration; - -import org.apache.commons.lang3.BooleanUtils; -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.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -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.EnableWebSecurity; -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.factory.PasswordEncoderFactories; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.authentication.HttpStatusEntryPoint; -import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import com.fasterxml.jackson.databind.ObjectMapper; - -import it.fabioformosa.quartzmanager.security.configuration.properties.InMemoryAccountProperties; -import it.fabioformosa.quartzmanager.security.configuration.properties.JwtSecurityProperties; -import it.fabioformosa.quartzmanager.security.helpers.LoginConfigurer; -import it.fabioformosa.quartzmanager.security.helpers.impl.AuthenticationFailureHandler; -import it.fabioformosa.quartzmanager.security.helpers.impl.AuthenticationSuccessHandler; -import it.fabioformosa.quartzmanager.security.helpers.impl.FormLoginConfig; -import it.fabioformosa.quartzmanager.security.helpers.impl.JwtAuthenticationSuccessHandler; -import it.fabioformosa.quartzmanager.security.helpers.impl.JwtAuthenticationSuccessHandlerImpl; -import it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenAuthenticationFilter; -import it.fabioformosa.quartzmanager.security.helpers.impl.JwtTokenHelper; -import it.fabioformosa.quartzmanager.security.helpers.impl.JwtUsernamePasswordFiterLoginConfig; -import it.fabioformosa.quartzmanager.security.helpers.impl.LogoutSuccess; -import it.fabioformosa.quartzmanager.security.helpers.impl.QuartzManagerHttpSecurity; - -/** - * - * @author Fabio.Formosa - * - */ -@Configuration -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class WebSecurityConfigJWT extends WebSecurityConfigurerAdapter { - - private static final String[] PATTERNS_SWAGGER_UI = {"/swagger-ui.html", "/v3/api-docs/**", "/swagger-resources/**", "/webjars/**"}; - - private static final String LOGIN_PATH = "/quartz-manager/api/login"; - private static final String LOGOUT_PATH = "/quartz-manager/api/logout"; - - private static final String WEBJAR_PATH = "/quartz-manager-ui"; - - @Value("${server.servlet.context-path:/}") - private String contextPath; - - @Value("${app.name:quartz-manager}") - private String appName; - - @Value("${quartz-manager.security.login-model.form-login-enabled}") - private Boolean formLoginEnabled; - @Value("${quartz-manager.security.login-model.userpwd-filter-enabled}") - private Boolean userpwdFilterEnabled; - - @Autowired - private JwtSecurityProperties jwtSecurityProps; - - @Autowired - private ObjectMapper objectMapper; - - @Autowired - private UserDetailsService userDetailsService; - - @Autowired - private InMemoryAccountProperties inMemoryAccountProps; - - - @Override - public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)throws Exception { - configureInMemoryAuthentication(authenticationManagerBuilder); - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable() // - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() // - .exceptionHandling().authenticationEntryPoint(restAuthEntryPoint()).and() // - .addFilterBefore(jwtAuthenticationTokenFilter(), BasicAuthenticationFilter.class) // - .authorizeRequests().anyRequest().authenticated(); - - QuartzManagerHttpSecurity.from(http).withLoginConfigurer(loginConfigurer(), logoutConfigurer()) // - .login(LOGIN_PATH, authenticationManager()).logout(LOGOUT_PATH); - - // temporary disabled csfr - // http.csrf().ignoringAntMatchers("/api/login", "/api/signup") // - // .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) // - } - - @Override - public void configure(WebSecurity web) { - web.ignoring()// - .antMatchers(HttpMethod.GET, PATTERNS_SWAGGER_UI) // - .antMatchers(HttpMethod.GET, WEBJAR_PATH + "/css/**", WEBJAR_PATH + "/js/**", WEBJAR_PATH + "/img/**", WEBJAR_PATH + "/lib/**", WEBJAR_PATH + "/assets/**"); - } - - private void configureInMemoryAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { - PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); - if(inMemoryAccountProps.isEnabled() && inMemoryAccountProps.getUsers() != null && !inMemoryAccountProps.getUsers().isEmpty()) { - InMemoryUserDetailsManagerConfigurer inMemoryAuth = authenticationManagerBuilder.inMemoryAuthentication(); - inMemoryAccountProps.getUsers() - .forEach(u -> inMemoryAuth - .withUser(u.getName()) - .password(encoder.encode(u.getPassword())) - .roles(u.getRoles().toArray(new String[0]))); - } - } - - @Bean - CorsConfigurationSource corsConfigurationSource() { - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues()); - return source; - } - - @Bean - public LoginConfigurer formLoginConfigurer() { - JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler = jwtAuthenticationSuccessHandler(); - AuthenticationSuccessHandler authenticationSuccessHandler = new AuthenticationSuccessHandler(jwtAuthenticationSuccessHandler); - AuthenticationFailureHandler authenticationFailureHandler = new AuthenticationFailureHandler(); - LoginConfigurer loginConfigurer = new FormLoginConfig(authenticationSuccessHandler, authenticationFailureHandler); - return loginConfigurer; - } - - @Bean - public JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler() { - JwtTokenHelper jwtTokenHelper = jwtTokenHelper(); - JwtAuthenticationSuccessHandler jwtAuthenticationSuccessHandler = new JwtAuthenticationSuccessHandlerImpl(contextPath, jwtSecurityProps, jwtTokenHelper, objectMapper); - return jwtAuthenticationSuccessHandler; - } - - @Bean - public JwtTokenAuthenticationFilter jwtAuthenticationTokenFilter() { - return new JwtTokenAuthenticationFilter(jwtTokenHelper(), userDetailsService); - } - - @Bean - public JwtTokenHelper jwtTokenHelper() { - return new JwtTokenHelper(appName, jwtSecurityProps); - } - - @Bean - public LoginConfigurer loginConfigurer() { - if(BooleanUtils.isTrue(userpwdFilterEnabled)) - return userpwdFilterLoginConfigurer(); - if(BooleanUtils.isNotFalse(formLoginEnabled)) - return formLoginConfigurer(); - throw new RuntimeException("No login configurer enabled!"); - } - - @Bean - public LogoutSuccess logoutConfigurer() { - return new LogoutSuccess(objectMapper); - } - - @Bean - public AuthenticationEntryPoint restAuthEntryPoint() { - return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED); - } - - @Bean - @Override - public UserDetailsService userDetailsServiceBean() throws Exception { - return super.userDetailsServiceBean(); - } - - @Bean - public LoginConfigurer userpwdFilterLoginConfigurer() { - LoginConfigurer loginConfigurer = new JwtUsernamePasswordFiterLoginConfig(jwtAuthenticationSuccessHandler()); - return loginConfigurer; - } - - // @Bean - // public PasswordEncoder passwordEncoder() { - // return new BCryptPasswordEncoder(); - // } - -} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/properties/JwtSecurityProperties.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/properties/JwtSecurityProperties.java deleted file mode 100644 index 1afec00..0000000 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/properties/JwtSecurityProperties.java +++ /dev/null @@ -1,33 +0,0 @@ -package it.fabioformosa.quartzmanager.security.configuration.properties; - -import lombok.Data; -import lombok.Getter; -import lombok.Setter; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - - -@Configuration -@ConfigurationProperties(prefix = "quartz-manager.security.jwt") -@Getter @Setter -public class JwtSecurityProperties { - private boolean enabled; - private String secret; - private long expirationInSec; - - private CookieStrategy cookieStrategy; - private HeaderStrategy headerStrategy; - - @Data - public static class CookieStrategy { - private boolean enabled; - private String cookie; - } - - @Data - public static class HeaderStrategy { - private boolean enabled; - private String header; - } - -} \ No newline at end of file diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandlerImpl.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandlerImpl.java index 8631920..a11fbe8 100644 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandlerImpl.java +++ b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtAuthenticationSuccessHandlerImpl.java @@ -1,7 +1,7 @@ package it.fabioformosa.quartzmanager.security.helpers.impl; import com.fasterxml.jackson.databind.ObjectMapper; -import it.fabioformosa.quartzmanager.security.configuration.properties.JwtSecurityProperties; +import it.fabioformosa.quartzmanager.security.properties.JwtSecurityProperties; import it.fabioformosa.quartzmanager.security.models.UserTokenState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenHelper.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenHelper.java index fdaaf0c..433bf6d 100644 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenHelper.java +++ b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/helpers/impl/JwtTokenHelper.java @@ -3,7 +3,7 @@ package it.fabioformosa.quartzmanager.security.helpers.impl; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; -import it.fabioformosa.quartzmanager.security.configuration.properties.JwtSecurityProperties; +import it.fabioformosa.quartzmanager.security.properties.JwtSecurityProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/Authority.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/Authority.java deleted file mode 100644 index 6638a16..0000000 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/Authority.java +++ /dev/null @@ -1,55 +0,0 @@ -package it.fabioformosa.quartzmanager.security.models; - -import javax.persistence.Column; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -import org.springframework.security.core.GrantedAuthority; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * Temporary enabled only inMemoryAuthentication - * - * @author Fabio.Formosa - * - */ -//@Entity -//@Table(name="Authority") -public class Authority implements GrantedAuthority { - - private static final long serialVersionUID = 1L; - - @Id - @Column(name="id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - Long id; - - @Column(name="name") - String name; - - @Override - public String getAuthority() { - return name; - } - - @JsonIgnore - public Long getId() { - return id; - } - - @JsonIgnore - public String getName() { - return name; - } - - public void setId(Long id) { - this.id = id; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/User.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/User.java deleted file mode 100644 index 622c311..0000000 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/models/User.java +++ /dev/null @@ -1,132 +0,0 @@ -package it.fabioformosa.quartzmanager.security.models; - -import java.io.Serializable; -import java.util.Collection; -import java.util.List; - -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * Temporary enabled only inMemoryAuthentication - * - * @author Fabio.Formosa - * - */ -//@Entity -//@Table(name = "USER") -public class User implements UserDetails, Serializable { - private static final long serialVersionUID = 1L; - - @Id - @Column(name = "id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "username") - private String username; - - @JsonIgnore - @Column(name = "password") - private String password; - - @Column(name = "firstname") - private String firstname; - - @Column(name = "lastname") - private String lastname; - - @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinTable(name = "user_authority", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id")) - private List authorities; - - @Override - public Collection getAuthorities() { - return authorities; - } - - public String getFirstname() { - return firstname; - } - - public Long getId() { - return id; - } - - public String getLastname() { - return lastname; - } - - @Override - public String getPassword() { - return password; - } - - @Override - public String getUsername() { - return username; - } - - // We can add the below fields in the users table. - // For now, they are hardcoded. - @JsonIgnore - @Override - public boolean isAccountNonExpired() { - return true; - } - - @JsonIgnore - @Override - public boolean isAccountNonLocked() { - return true; - } - - @JsonIgnore - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @JsonIgnore - @Override - public boolean isEnabled() { - return true; - } - - public void setAuthorities(List authorities) { - this.authorities = authorities; - } - - public void setFirstname(String firstname) { - this.firstname = firstname; - } - - public void setId(Long id) { - this.id = id; - } - - public void setLastname(String lastname) { - - this.lastname = lastname; - } - - public void setPassword(String password) { - this.password = password; - } - - public void setUsername(String username) { - this.username = username; - } -} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/properties/InMemoryAccountProperties.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/properties/InMemoryAccountProperties.java similarity index 89% rename from quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/properties/InMemoryAccountProperties.java rename to quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/properties/InMemoryAccountProperties.java index 279a079..b6ffdaf 100644 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/configuration/properties/InMemoryAccountProperties.java +++ b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/properties/InMemoryAccountProperties.java @@ -1,4 +1,4 @@ -package it.fabioformosa.quartzmanager.security.configuration.properties; +package it.fabioformosa.quartzmanager.security.properties; import lombok.Getter; import lombok.Setter; diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/properties/JwtSecurityProperties.java b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/properties/JwtSecurityProperties.java new file mode 100644 index 0000000..967f75f --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/main/java/it/fabioformosa/quartzmanager/security/properties/JwtSecurityProperties.java @@ -0,0 +1,35 @@ +package it.fabioformosa.quartzmanager.security.properties; + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + + +@Configuration +@ConfigurationProperties(prefix = "quartz-manager.security.jwt") +@Getter +@Setter +public class JwtSecurityProperties { + private boolean enabled = true; + private String secret = RandomStringUtils.randomAlphabetic(10); + private long expirationInSec = 28800; + + private CookieStrategy cookieStrategy = new CookieStrategy(); + private HeaderStrategy headerStrategy = new HeaderStrategy(); + + @Data + public static class CookieStrategy { + private boolean enabled = false; + private String cookie = "AUTH-TOKEN"; + } + + @Data + public static class HeaderStrategy { + private boolean enabled = true; + private String header = "Authorization"; + } + +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/main/resources/META-INF/spring.factories b/quartz-manager-parent/quartz-manager-starter-security/src/main/resources/META-INF/spring.factories index 9e6be3c..b1e78c3 100644 --- a/quartz-manager-parent/quartz-manager-starter-security/src/main/resources/META-INF/spring.factories +++ b/quartz-manager-parent/quartz-manager-starter-security/src/main/resources/META-INF/spring.factories @@ -1,4 +1,4 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -it.fabioformosa.quartzmanager.security.configuration.WebSecurityConfigJWT,\ -it.fabioformosa.quartzmanager.security.configuration.properties.JwtSecurityProperties,\ -it.fabioformosa.quartzmanager.security.configuration.properties.InMemoryAccountProperties \ No newline at end of file +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +it.fabioformosa.quartzmanager.security.WebSecurityConfigJWT,\ +it.fabioformosa.quartzmanager.security.properties.JwtSecurityProperties,\ +it.fabioformosa.quartzmanager.security.properties.InMemoryAccountProperties diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/AbstractSecurityLoginTest.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/AbstractSecurityLoginTest.java new file mode 100644 index 0000000..315492e --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/AbstractSecurityLoginTest.java @@ -0,0 +1,29 @@ +package it.fabioformosa.quartzmanager.security; + +import it.fabioformosa.quartzmanager.security.models.UserTokenState; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.*; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import static it.fabioformosa.quartzmanager.security.WebSecurityConfigJWT.LOGIN_PATH; + +public class AbstractSecurityLoginTest { + @Autowired + private TestRestTemplate testRestTemplate; + + protected ResponseEntity doLogin() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("username", "foo"); + map.add("password", "bar"); + + HttpEntity> entity = new HttpEntity<>(map, headers); + + ResponseEntity responseEntity = testRestTemplate.exchange(LOGIN_PATH, HttpMethod.POST, entity, UserTokenState.class); + return responseEntity; + } +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityControllerTest.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityControllerTest.java new file mode 100644 index 0000000..0ca06f8 --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityControllerTest.java @@ -0,0 +1,71 @@ +package it.fabioformosa.quartzmanager.security; + +import it.fabioformosa.quartzmanager.security.controllers.TestController; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static it.fabioformosa.quartzmanager.security.WebSecurityConfigJWT.LOGIN_PATH; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@TestPropertySource(properties = { + "quartz-manager.security.jwt.enabled=true", + "quartz-manager.security.jwt.secret=bibidibobidiboo", + "quartz-manager.security.jwt.expiration-in-sec=28800", + "quartz-manager.security.jwt.header-strategy.enabled=false", + "quartz-manager.security.jwt.header-strategy.header=Authorization", + "quartz-manager.security.jwt.cookie-strategy.enabled=true", + "quartz-manager.security.jwt.cookie-strategy.cookie=AUTH-TOKEN", + "quartz-manager.accounts.in-memory.enabled=true", + "quartz-manager.accounts.in-memory.users[0].name=foo", + "quartz-manager.accounts.in-memory.users[0].password=bar", + "quartz-manager.accounts.in-memory.users[0].roles[0]=admin", +}) +public class SecurityControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void givenAnAnonymousUser_whenCalledATestController_thenShouldRaiseForbidden() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/test")) + .andExpect(status().isUnauthorized()); + } + + @Test + void givenAnAnonymousUser_whenCalledATestScheduler_thenShouldRaiseForbidden() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get(TestController.QUARTZ_MANAGER + "/scheduler")) + .andExpect(status().isUnauthorized()); + } + + @Test + void givenAnAnonymousUser_whenRequestedSwaggerResource_thenShouldReturn2xx() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/swagger-ui.html")) + .andExpect(status().isOk()); + } + + @Test + @WithMockUser("admin") + void givenAnUser_whenCalledATestScheduler_thenShouldReturn2xx() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get(TestController.QUARTZ_MANAGER + "/scheduler")) + .andExpect(status().isOk()); + } + + @Test + void givenAnAnonymousUser_whenCalledTheLoginPath_thenShouldReturn2xx() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post(LOGIN_PATH) + .contentType("application/x-www-form-urlencoded") + .accept("application/json") + .param("username", "foo") + .param("password", "bar")) + .andExpect(status().isOk()); + } + +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaCookieTest.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaCookieTest.java new file mode 100644 index 0000000..c04cc9e --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaCookieTest.java @@ -0,0 +1,40 @@ +package it.fabioformosa.quartzmanager.security; + +import it.fabioformosa.quartzmanager.security.models.UserTokenState; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; + + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { + "quartz-manager.security.login-model.form-login-enabled = true", + "quartz-manager.security.login-model.userpwd-filter-enabled = false", + "quartz-manager.security.jwt.enabled=true", + "quartz-manager.security.jwt.secret=bibidibobidiboo", + "quartz-manager.security.jwt.expiration-in-sec=28800", + "quartz-manager.security.jwt.header-strategy.enabled=false", + "quartz-manager.security.jwt.header-strategy.header=Authorization", + "quartz-manager.security.jwt.cookie-strategy.enabled=true", + "quartz-manager.security.jwt.cookie-strategy.cookie=AUTH-TOKEN", + "quartz-manager.accounts.in-memory.enabled=true", + "quartz-manager.accounts.in-memory.users[0].name=foo", + "quartz-manager.accounts.in-memory.users[0].password=bar", + "quartz-manager.accounts.in-memory.users[0].roles[0]=admin", +}) +public class SecurityLoginViaCookieTest extends AbstractSecurityLoginTest { + + @Test + void givenAnAnonymousUser_whenTheLoginIsSubmitted_thenShouldReturn2xx() { + ResponseEntity responseEntity = doLogin(); + Assertions.assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + Assertions.assertThat(responseEntity.getBody().getAccess_token()).isNotEmpty(); + Assertions.assertThat(responseEntity.getBody().getExpires_in_sec()).isNotNull().isPositive(); + Assertions.assertThat(responseEntity.getHeaders().get("set-cookie")).hasSizeGreaterThan(0); + Assertions.assertThat(responseEntity.getHeaders().get("set-cookie").get(0)).startsWith("AUTH-TOKEN"); + } + +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaDefaultStrategyTest.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaDefaultStrategyTest.java new file mode 100644 index 0000000..6f0a6ab --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaDefaultStrategyTest.java @@ -0,0 +1,30 @@ +package it.fabioformosa.quartzmanager.security; + +import it.fabioformosa.quartzmanager.security.models.UserTokenState; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; + + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { + "quartz-manager.accounts.in-memory.enabled=true", + "quartz-manager.accounts.in-memory.users[0].name=foo", + "quartz-manager.accounts.in-memory.users[0].password=bar", + "quartz-manager.accounts.in-memory.users[0].roles[0]=admin", +}) +public class SecurityLoginViaDefaultStrategyTest extends AbstractSecurityLoginTest { + + @Test + void givenAnAnonymousUser_whenTheLoginIsSubmitted_thenShouldReturn2xx() { + ResponseEntity responseEntity = doLogin(); + Assertions.assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + Assertions.assertThat(responseEntity.getBody().getAccess_token()).isNotEmpty(); + Assertions.assertThat(responseEntity.getBody().getExpires_in_sec()).isNotNull().isPositive(); + Assertions.assertThat(responseEntity.getHeaders().get("set-cookie")).isNull(); + } + +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderAndLoginFilterTest.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderAndLoginFilterTest.java new file mode 100644 index 0000000..8ae21b8 --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderAndLoginFilterTest.java @@ -0,0 +1,38 @@ +package it.fabioformosa.quartzmanager.security; + +import it.fabioformosa.quartzmanager.security.models.UserTokenState; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; + + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { + "quartz-manager.security.login-model.form-login-enabled = false", + "quartz-manager.security.login-model.userpwd-filter-enabled = true", + "quartz-manager.security.jwt.enabled=true", + "quartz-manager.security.jwt.secret=bibidibobidiboo", + "quartz-manager.security.jwt.expiration-in-sec=28800", + "quartz-manager.security.jwt.header-strategy.enabled=true", + "quartz-manager.security.jwt.header-strategy.header=Authorization", + "quartz-manager.security.jwt.cookie-strategy.enabled=false", + "quartz-manager.accounts.in-memory.enabled=true", + "quartz-manager.accounts.in-memory.users[0].name=foo", + "quartz-manager.accounts.in-memory.users[0].password=bar", + "quartz-manager.accounts.in-memory.users[0].roles[0]=admin", +}) +public class SecurityLoginViaHeaderAndLoginFilterTest extends AbstractSecurityLoginTest { + + @Test + void givenAnAnonymousUser_whenTheLoginIsSubmitted_thenShouldReturn2xx() { + ResponseEntity responseEntity = doLogin(); + Assertions.assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + Assertions.assertThat(responseEntity.getBody().getAccess_token()).isNotEmpty(); + Assertions.assertThat(responseEntity.getBody().getExpires_in_sec()).isNotNull().isPositive(); + Assertions.assertThat(responseEntity.getHeaders().get("set-cookie")).isNull(); + } + +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderTest.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderTest.java new file mode 100644 index 0000000..38c610e --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SecurityLoginViaHeaderTest.java @@ -0,0 +1,37 @@ +package it.fabioformosa.quartzmanager.security; + +import it.fabioformosa.quartzmanager.security.models.UserTokenState; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.*; +import org.springframework.test.context.TestPropertySource; + + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { + "quartz-manager.security.login-model.form-login-enabled = true", + "quartz-manager.security.login-model.userpwd-filter-enabled = false", + "quartz-manager.security.jwt.enabled=true", + "quartz-manager.security.jwt.secret=bibidibobidiboo", + "quartz-manager.security.jwt.expiration-in-sec=28800", + "quartz-manager.security.jwt.header-strategy.enabled=true", + "quartz-manager.security.jwt.header-strategy.header=Authorization", + "quartz-manager.security.jwt.cookie-strategy.enabled=false", + "quartz-manager.accounts.in-memory.enabled=true", + "quartz-manager.accounts.in-memory.users[0].name=foo", + "quartz-manager.accounts.in-memory.users[0].password=bar", + "quartz-manager.accounts.in-memory.users[0].roles[0]=admin", +}) +public class SecurityLoginViaHeaderTest extends AbstractSecurityLoginTest { + + @Test + void givenAnAnonymousUser_whenTheLoginIsSubmitted_thenShouldReturn2xx() { + ResponseEntity responseEntity = doLogin(); + Assertions.assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); + Assertions.assertThat(responseEntity.getBody().getAccess_token()).isNotEmpty(); + Assertions.assertThat(responseEntity.getBody().getExpires_in_sec()).isNotNull().isPositive(); + Assertions.assertThat(responseEntity.getHeaders().get("set-cookie")).isNull(); + } + +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SpringApplicationTest.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SpringApplicationTest.java new file mode 100644 index 0000000..5472bbf --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/SpringApplicationTest.java @@ -0,0 +1,7 @@ +package it.fabioformosa.quartzmanager.security; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringApplicationTest { +} diff --git a/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/controllers/TestController.java b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/controllers/TestController.java new file mode 100644 index 0000000..a5a8f49 --- /dev/null +++ b/quartz-manager-parent/quartz-manager-starter-security/src/test/java/it/fabioformosa/quartzmanager/security/controllers/TestController.java @@ -0,0 +1,33 @@ +package it.fabioformosa.quartzmanager.security.controllers; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping +@RestController +public class TestController { + + public static final String QUARTZ_MANAGER = "/quartz-manager"; + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/test") + public void getDMZTest(){ + + } + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/swagger-ui.html") + public void getSwaggerUI(){ + + } + + @ResponseStatus(HttpStatus.OK) + @GetMapping(QUARTZ_MANAGER + "/scheduler") + public void getQuartzManagerScheduler(){ + + } + +} diff --git a/quartz-manager-parent/quartz-manager-web-showcase/pom.xml b/quartz-manager-parent/quartz-manager-web-showcase/pom.xml index 85b85d7..abf65c8 100644 --- a/quartz-manager-parent/quartz-manager-web-showcase/pom.xml +++ b/quartz-manager-parent/quartz-manager-web-showcase/pom.xml @@ -9,7 +9,7 @@ quartz-manager-web-showcase - + war Quartz Manager Web Showcase @@ -21,7 +21,7 @@ 2.9.2 1.8 - + it.fabioformosa.quartz-manager @@ -39,7 +39,7 @@ - + org.springframework.boot @@ -68,7 +68,7 @@ spring-boot-starter-test test - + io.jsonwebtoken @@ -118,8 +118,8 @@ test - - + + @@ -146,6 +146,6 @@ - + diff --git a/quartz-manager-parent/quartz-manager-web-showcase/src/main/resources/application.yml b/quartz-manager-parent/quartz-manager-web-showcase/src/main/resources/application.yml index 335fbb2..cd64605 100644 --- a/quartz-manager-parent/quartz-manager-web-showcase/src/main/resources/application.yml +++ b/quartz-manager-parent/quartz-manager-web-showcase/src/main/resources/application.yml @@ -26,8 +26,6 @@ logging: org.quartz: INFO quartz-manager: - trigger: - name: "sampletrigger" persistence: quartz: datasource: