diff --git a/.idea/modules/sporttag-psa_main.iml b/.idea/modules/sporttag-psa_main.iml
index 264083fa..86d56ac7 100644
--- a/.idea/modules/sporttag-psa_main.iml
+++ b/.idea/modules/sporttag-psa_main.iml
@@ -75,6 +75,8 @@
+
+
@@ -93,7 +95,6 @@
-
@@ -130,6 +131,8 @@
+
+
@@ -159,7 +162,7 @@
-
+
@@ -168,11 +171,9 @@
-
-
@@ -181,7 +182,6 @@
-
diff --git a/.idea/modules/sporttag-psa_test.iml b/.idea/modules/sporttag-psa_test.iml
index 00aeb860..84fe3d5a 100644
--- a/.idea/modules/sporttag-psa_test.iml
+++ b/.idea/modules/sporttag-psa_test.iml
@@ -72,6 +72,8 @@
+
+
@@ -83,8 +85,8 @@
-
+
@@ -96,7 +98,6 @@
-
@@ -136,6 +137,8 @@
+
+
@@ -176,7 +179,7 @@
-
+
@@ -187,11 +190,9 @@
-
-
@@ -201,7 +202,6 @@
-
diff --git a/build.gradle b/build.gradle
index fffab544..10637e03 100644
--- a/build.gradle
+++ b/build.gradle
@@ -124,6 +124,9 @@ dependencies {
// https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-oauth2
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-oauth2', version: '2.0.0.RELEASE'
+ // https://mvnrepository.com/artifact/org.springframework.security/spring-security-jwt
+ compile group: 'org.springframework.security', name: 'spring-security-jwt', version: '1.0.9.RELEASE'
+
// https://mvnrepository.com/artifact/org.passay/passay
compile group: 'org.passay', name: 'passay', version: '1.3.1'
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/AuthorizationServerConfig.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/AuthorizationServerConfig.kt
index 0b1fb466..fe3c63f3 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/AuthorizationServerConfig.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/AuthorizationServerConfig.kt
@@ -36,8 +36,11 @@
package ch.schulealtendorf.sporttagpsa.controller.config
+import ch.schulealtendorf.sporttagpsa.business.setup.SetupManager
import org.springframework.beans.factory.annotation.Qualifier
+import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.Primary
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer
@@ -45,8 +48,10 @@ import org.springframework.security.oauth2.config.annotation.web.configuration.A
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices
import org.springframework.security.oauth2.provider.token.TokenStore
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore
+import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
/**
* Configures OAuth 2 authorization server.
@@ -58,7 +63,8 @@ import org.springframework.security.oauth2.provider.token.store.InMemoryTokenSto
@EnableAuthorizationServer
class AuthorizationServerConfig(
@Qualifier("authenticationManagerBean")
- private val authenticationManager: AuthenticationManager
+ private val authenticationManager: AuthenticationManager,
+ private val setupManager: SetupManager
): AuthorizationServerConfigurerAdapter() {
override fun configure(security: AuthorizationServerSecurityConfigurer?) {
@@ -96,11 +102,25 @@ class AuthorizationServerConfig(
endpoints
?.tokenStore(tokenStore())
+ ?.accessTokenConverter(tokenConverter())
?.authenticationManager(authenticationManager)
}
+ @Bean
fun tokenStore(): TokenStore = InMemoryTokenStore()
+ @Bean
+ fun tokenConverter() = JwtAccessTokenConverter().apply { setSigningKey(setupManager.jwtSecret) }
+
+ @Bean
+ @Primary
+ fun tokenService(): DefaultTokenServices {
+ return DefaultTokenServices().apply {
+ setTokenStore(tokenStore())
+ setSupportRefreshToken(true)
+ }
+ }
+
private fun > ClientDetailsServiceBuilder.ClientBuilder.scopes(vararg values: PSAScope): ClientDetailsServiceBuilder.ClientBuilder {
return scopes(*values.map { it.value }.toTypedArray())
}
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTAuthenticationFilter.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTAuthenticationFilter.kt
deleted file mode 100644
index 6ae35202..00000000
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTAuthenticationFilter.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2018 by Nicolas Märchy
- *
- * This file is part of Sporttag PSA.
- *
- * Sporttag PSA is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Sporttag PSA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Sporttag PSA. If not, see .
- *
- * Diese Datei ist Teil von Sporttag PSA.
- *
- * Sporttag PSA ist Freie Software: Sie können es unter den Bedingungen
- * der GNU General Public License, wie von der Free Software Foundation,
- * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
- * veröffentlichten Version, weiterverbreiten und/oder modifizieren.
- *
- * Sporttag PSA wird in der Hoffnung, dass es nützlich sein wird, aber
- * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
- * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
- * Siehe die GNU General Public License für weitere Details.
- *
- * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
- * Programm erhalten haben. Wenn nicht, siehe .
- *
- *
- */
-
-package ch.schulealtendorf.sporttagpsa.controller.config
-
-import ch.schulealtendorf.sporttagpsa.business.user.UserLogin
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
-import com.fasterxml.jackson.module.kotlin.readValue
-import io.jsonwebtoken.Jwts
-import io.jsonwebtoken.SignatureAlgorithm
-import org.joda.time.DateTime
-import org.springframework.security.authentication.AuthenticationManager
-import org.springframework.security.authentication.AuthenticationServiceException
-import org.springframework.security.authentication.BadCredentialsException
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
-import org.springframework.security.core.Authentication
-import org.springframework.security.core.AuthenticationException
-import org.springframework.security.core.userdetails.User
-import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
-import org.springframework.stereotype.Component
-import java.io.InputStream
-import javax.servlet.FilterChain
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletResponse
-
-/**
- * @author nmaerchy
- * @since 0.0.1
- */
-class JWTAuthenticationFilter(
- authManager: AuthenticationManager
-): UsernamePasswordAuthenticationFilter() {
-
- init {
- authenticationManager = authManager
- }
-
- companion object {
- const val SECRET = "MySecret"
- const val EXPIRATION_TIME = 43200 // 12 hours
- }
-
- override fun attemptAuthentication(request: HttpServletRequest?, response: HttpServletResponse?): Authentication {
-
- val body: InputStream = request?.inputStream?: throw BadCredentialsException("Username or password is invalid")
-
- val user = jacksonObjectMapper().readValue(body)
-
- return authenticationManager.authenticate(
- UsernamePasswordAuthenticationToken(
- user.username,
- user.password,
- listOf()
- )
- )
- }
-
- override fun successfulAuthentication(request: HttpServletRequest?, response: HttpServletResponse?, chain: FilterChain?, authResult: Authentication?) {
-
- val token: String = Jwts.builder()
- .setSubject((authResult?.principal as User).username)
- .setExpiration(DateTime.now().plusSeconds(EXPIRATION_TIME).toDate())
- .signWith(SignatureAlgorithm.HS512, SECRET)
- .compact()
-
- response?.addHeader("Authorization", "Bearer $token")
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTAuthorizationFilter.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTAuthorizationFilter.kt
deleted file mode 100644
index 88bd8e5a..00000000
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTAuthorizationFilter.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2018 by Nicolas Märchy
- *
- * This file is part of Sporttag PSA.
- *
- * Sporttag PSA is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Sporttag PSA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Sporttag PSA. If not, see .
- *
- * Diese Datei ist Teil von Sporttag PSA.
- *
- * Sporttag PSA ist Freie Software: Sie können es unter den Bedingungen
- * der GNU General Public License, wie von der Free Software Foundation,
- * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
- * veröffentlichten Version, weiterverbreiten und/oder modifizieren.
- *
- * Sporttag PSA wird in der Hoffnung, dass es nützlich sein wird, aber
- * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
- * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
- * Siehe die GNU General Public License für weitere Details.
- *
- * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
- * Programm erhalten haben. Wenn nicht, siehe .
- *
- *
- */
-
-package ch.schulealtendorf.sporttagpsa.controller.config
-
-import io.jsonwebtoken.Jwts
-import org.springframework.security.authentication.AuthenticationManager
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
-import org.springframework.security.core.context.SecurityContextHolder
-import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
-import org.springframework.stereotype.Component
-import java.util.*
-import javax.servlet.FilterChain
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletResponse
-
-/**
- * @author nmaerchy
- * @since 0.0.1
- */
-class JWTAuthorizationFilter(
- authManager: AuthenticationManager
-): BasicAuthenticationFilter(authManager) {
-
- override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain) {
-
- val token: String? = request.getHeader("Authorization")
-
- if (token == null || !token.startsWith("Bearer ")) {
- chain.doFilter(request, response)
- return
- }
-
- SecurityContextHolder.getContext().authentication = getAuthentication(token).orElseGet { null }
- chain.doFilter(request, response)
- }
-
- private fun getAuthentication(token: String): Optional {
-
- val username: String = Jwts.parser()
- ?.setSigningKey("MySecret")
- ?.parseClaimsJws(token.replace("Bearer ", ""))
- ?.body
- ?.subject ?: return Optional.empty()
-
- return Optional.of(UsernamePasswordAuthenticationToken(username, null, listOf()))
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTHelper.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTHelper.kt
deleted file mode 100644
index f79b4b44..00000000
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/JWTHelper.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2018 by Nicolas Märchy
- *
- * This file is part of Sporttag PSA.
- *
- * Sporttag PSA is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Sporttag PSA is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Sporttag PSA. If not, see .
- *
- * Diese Datei ist Teil von Sporttag PSA.
- *
- * Sporttag PSA ist Freie Software: Sie können es unter den Bedingungen
- * der GNU General Public License, wie von der Free Software Foundation,
- * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
- * veröffentlichten Version, weiterverbreiten und/oder modifizieren.
- *
- * Sporttag PSA wird in der Hoffnung, dass es nützlich sein wird, aber
- * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
- * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
- * Siehe die GNU General Public License für weitere Details.
- *
- * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
- * Programm erhalten haben. Wenn nicht, siehe .
- *
- *
- */
-
-package ch.schulealtendorf.sporttagpsa.controller.config
-
-import io.jsonwebtoken.Claims
-import io.jsonwebtoken.Jws
-import io.jsonwebtoken.Jwts
-import io.jsonwebtoken.SignatureAlgorithm
-import org.joda.time.DateTime
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
-import javax.servlet.http.HttpServletRequest
-
-const val TOKEN_PREFIX: String = "Bearer "
-
-fun createJWT(request: HttpServletRequest, authentication: UsernamePasswordAuthenticationToken, secret: String): String {
-
- // help for the different claims: https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25#section-4
- return Jwts.builder()
- .setIssuer(request.host())
- .setSubject(authentication.name)
- .setAudience(request.getHeader("User-Agent"))
- .claim("roles", authentication.authorities.map { it.authority })
- .setExpiration(DateTime.now().plusSeconds(JWTAuthenticationFilter.EXPIRATION_TIME).toDate())
- .signWith(SignatureAlgorithm.HS512, secret)
- .compact()
-}
-
-fun decodeJWT(request: HttpServletRequest, token: String, secret: String): Jws {
-
- return Jwts.parser()
- ?.setSigningKey(secret)
- ?.requireIssuer(request.host())
- ?.requireAudience(request.getHeader("User-Agent"))
- ?.parseClaimsJws(token)!!
-}
-
-private fun HttpServletRequest.host(): String {
- return "$scheme://$serverName:$serverPort"
-}
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/OAuth2ScopeConfig.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/OauthScopeConfig.kt
similarity index 94%
rename from src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/OAuth2ScopeConfig.kt
rename to src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/OauthScopeConfig.kt
index 84c31e37..7072bea0 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/OAuth2ScopeConfig.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/OauthScopeConfig.kt
@@ -43,14 +43,14 @@ import org.springframework.security.config.annotation.method.configuration.Globa
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler
/**
- * Configures method scope annotations.
+ * Configuration which enables method expression for oauth 2 scopes.
*
* @author nmaerchy
* @since 2.0.0
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
-class OAuth2ScopeConfig: GlobalMethodSecurityConfiguration() {
+class OauthScopeConfig: GlobalMethodSecurityConfiguration() {
override fun createExpressionHandler(): MethodSecurityExpressionHandler {
return OAuth2MethodSecurityExpressionHandler()
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/ResourceServerConfig.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/ResourceServerConfig.kt
index d0703195..a2ba5b54 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/ResourceServerConfig.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/ResourceServerConfig.kt
@@ -36,67 +36,56 @@
package ch.schulealtendorf.sporttagpsa.controller.config
-import ch.schulealtendorf.sporttagpsa.business.setup.SetupManager
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.beans.factory.annotation.Qualifier
-import org.springframework.boot.autoconfigure.security.servlet.PathRequest
-import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
-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.configuration.EnableWebSecurity
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
-import org.springframework.security.core.userdetails.UserDetailsService
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
-import org.springframework.security.crypto.password.PasswordEncoder
-import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
-
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices
/**
- * Security Configuration for the resource server resources and the authorization server resources.
+ * Configures the resource server.
*
- * @author nmaerchy
- * @since 1.0.0
+ * @author nmaerchy
+ * @since 2.0.0
*/
@Configuration
-@EnableWebSecurity
+@EnableResourceServer
class ResourceServerConfig(
- @Qualifier("psa-user-service")
- private val userDetailsService: UserDetailsService,
- private val setupManager: SetupManager
-): WebSecurityConfigurerAdapter() {
-
- @Autowired
- fun configureGlobal(auth: AuthenticationManagerBuilder) {
- auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder())
- }
+ private val tokenServices: DefaultTokenServices
+): ResourceServerConfigurerAdapter() {
override fun configure(http: HttpSecurity?) {
http
- ?.csrf()?.disable()
- ?.cors()
-
- ?.and()
+ ?.antMatcher("/api/**")
?.authorizeRequests()
- ?.requestMatchers(PathRequest.toStaticResources().atCommonLocations())?.permitAll()
- ?.antMatchers("/login", "/webjars/**", "/setup")?.permitAll()
- ?.anyRequest()?.authenticated()
- ?.and()
- ?.formLogin()?.loginPage("/login")?.permitAll()
+ ?.antMatchers(
+ "/api/groups",
+ "/api/participation",
+ "/api/competitors",
+ "/api/competitor/**",
+ "/api/sports",
+ "/api/disciplines"
+ )?.hasRole("USER")
+
+ ?.antMatchers(
+ "/api/group/**",
+ "/api/participant/**",
+ "/api/participants",
+ "/api/users",
+ "/api/user/**"
+ )?.hasRole("ADMIN")
+
+ ?.anyRequest()?.authenticated()
?.and()
- ?.addFilterBefore(SetupAuthorizationFilter(setupManager), BasicAuthenticationFilter::class.java)
+ ?.csrf()?.disable()
+ ?.cors()
}
- @Bean
- @Qualifier("authenticationManagerBean")
- override fun authenticationManager(): AuthenticationManager {
- return super.authenticationManager()
+ override fun configure(resources: ResourceServerSecurityConfigurer?) {
+ resources?.tokenServices(tokenServices)
}
-
- @Bean
- fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder(4)
}
\ No newline at end of file
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/SecurityConfig.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/SecurityConfig.kt
new file mode 100644
index 00000000..b6551b4f
--- /dev/null
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/config/SecurityConfig.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018 by Nicolas Märchy
+ *
+ * This file is part of Sporttag PSA.
+ *
+ * Sporttag PSA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Sporttag PSA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Sporttag PSA. If not, see .
+ *
+ * Diese Datei ist Teil von Sporttag PSA.
+ *
+ * Sporttag PSA ist Freie Software: Sie können es unter den Bedingungen
+ * der GNU General Public License, wie von der Free Software Foundation,
+ * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
+ * veröffentlichten Version, weiterverbreiten und/oder modifizieren.
+ *
+ * Sporttag PSA wird in der Hoffnung, dass es nützlich sein wird, aber
+ * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
+ * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
+ * Siehe die GNU General Public License für weitere Details.
+ *
+ * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
+ * Programm erhalten haben. Wenn nicht, siehe .
+ *
+ *
+ */
+
+package ch.schulealtendorf.sporttagpsa.controller.config
+
+import ch.schulealtendorf.sporttagpsa.business.setup.SetupManager
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Qualifier
+import org.springframework.boot.autoconfigure.security.servlet.PathRequest
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+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.configuration.EnableWebSecurity
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
+import org.springframework.security.core.userdetails.UserDetailsService
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
+import org.springframework.security.crypto.password.PasswordEncoder
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
+
+
+/**
+ * Security Configuration for the resource server resources and the authorization server resources.
+ *
+ * @author nmaerchy
+ * @since 1.0.0
+ */
+@Configuration
+@EnableWebSecurity
+class SecurityConfig(
+ @Qualifier("psa-user-service")
+ private val userDetailsService: UserDetailsService,
+ private val setupManager: SetupManager
+): WebSecurityConfigurerAdapter() {
+
+ @Autowired
+ fun configureGlobal(auth: AuthenticationManagerBuilder) {
+ auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder())
+ }
+
+ override fun configure(http: HttpSecurity?) {
+
+ http
+ ?.authorizeRequests()
+ ?.requestMatchers(PathRequest.toStaticResources().atCommonLocations())?.permitAll()
+ ?.antMatchers("/login", "/webjars/**", "/setup")?.permitAll()
+ ?.anyRequest()?.authenticated()
+
+ ?.and()
+ ?.formLogin()?.loginPage("/login")?.permitAll()
+
+ ?.and()
+ ?.addFilterBefore(SetupAuthorizationFilter(setupManager), BasicAuthenticationFilter::class.java)
+ }
+
+ @Bean
+ @Qualifier("authenticationManagerBean")
+ override fun authenticationManager(): AuthenticationManager {
+ return super.authenticationManager()
+ }
+
+ @Bean
+ fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder(4)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/competitor/CompetitorController.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/competitor/CompetitorController.kt
index af655ceb..020be329 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/competitor/CompetitorController.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/competitor/CompetitorController.kt
@@ -54,6 +54,7 @@ import java.util.*
* @since 0.0.1
*/
@RestController
+@RequestMapping("/api")
class CompetitorController(
private val competitorManager: CompetitorManager,
private val resultCalculator: ResultCalculator
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/discipline/DisciplineController.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/discipline/DisciplineController.kt
index 9a36aa0b..fa2801ef 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/discipline/DisciplineController.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/discipline/DisciplineController.kt
@@ -40,6 +40,7 @@ import ch.schulealtendorf.sporttagpsa.business.athletics.DisciplineManager
import ch.schulealtendorf.sporttagpsa.model.Discipline
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
/**
@@ -47,6 +48,7 @@ import org.springframework.web.bind.annotation.RestController
* @since 2.0.0
*/
@RestController
+@RequestMapping("/api")
class DisciplineController(
private val disciplineManager: DisciplineManager
) {
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/group/GroupController.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/group/GroupController.kt
index bed3587b..00245469 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/group/GroupController.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/group/GroupController.kt
@@ -42,10 +42,7 @@ import ch.schulealtendorf.sporttagpsa.controller.rest.NotFoundException
import ch.schulealtendorf.sporttagpsa.model.Group
import org.springframework.http.MediaType
import org.springframework.security.access.prepost.PreAuthorize
-import org.springframework.web.bind.annotation.GetMapping
-import org.springframework.web.bind.annotation.PathVariable
-import org.springframework.web.bind.annotation.RequestParam
-import org.springframework.web.bind.annotation.RestController
+import org.springframework.web.bind.annotation.*
/**
* Rest controller for {@link Group}.
@@ -54,6 +51,7 @@ import org.springframework.web.bind.annotation.RestController
* @since 2.0.0
*/
@RestController
+@RequestMapping("/api")
class GroupController(
private val groupManager: GroupManager
) {
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participant/ParticipantController.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participant/ParticipantController.kt
index d0b2a255..95f074a8 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participant/ParticipantController.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participant/ParticipantController.kt
@@ -53,6 +53,7 @@ import javax.validation.Valid
* @since 2.0.0
*/
@RestController
+@RequestMapping("/api")
class ParticipantController(
private val participantManager: ParticipantManager,
private val participationManager: ParticipationManager,
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participation/ParticipationController.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participation/ParticipationController.kt
index 39a02440..1908ac90 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participation/ParticipationController.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/participation/ParticipationController.kt
@@ -43,16 +43,14 @@ import ch.schulealtendorf.sporttagpsa.controller.rest.json
import ch.schulealtendorf.sporttagpsa.model.ParticipationStatus
import org.springframework.http.MediaType
import org.springframework.security.access.prepost.PreAuthorize
-import org.springframework.web.bind.annotation.GetMapping
-import org.springframework.web.bind.annotation.PatchMapping
-import org.springframework.web.bind.annotation.RequestBody
-import org.springframework.web.bind.annotation.RestController
+import org.springframework.web.bind.annotation.*
/**
* @author nmaerchy
* @since 2.0.0
*/
@RestController
+@RequestMapping("/api")
class ParticipationController(
private val participationManager: ParticipationManager
) {
@@ -64,7 +62,7 @@ class ParticipationController(
return json(status)
}
- @PreAuthorize("#oauth2.hasScope('participation')")
+ @PreAuthorize("#oauth2.hasScope('participation') and hasAuthority('ADMIN')")
@PatchMapping("/participation")
fun updateParticipation(@RequestBody participation: RestParticipationStatus) {
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/sport/SportController.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/sport/SportController.kt
index 538133e9..576eefbc 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/sport/SportController.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/rest/sport/SportController.kt
@@ -41,6 +41,7 @@ import ch.schulealtendorf.sporttagpsa.model.Sport
import org.springframework.http.MediaType
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
/**
@@ -48,6 +49,7 @@ import org.springframework.web.bind.annotation.RestController
* @since 2.0.0
*/
@RestController
+@RequestMapping("/api")
class SportController(
private val sportManager: SportManager
) {
diff --git a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/web/groupimport/GroupImportController.kt b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/web/groupimport/GroupImportController.kt
index 3623ddfc..88690f95 100644
--- a/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/web/groupimport/GroupImportController.kt
+++ b/src/main/kotlin/ch/schulealtendorf/sporttagpsa/controller/web/groupimport/GroupImportController.kt
@@ -51,6 +51,7 @@ import org.springframework.web.multipart.MultipartFile
* @since 2.0.0
*/
@Controller
+@RequestMapping("/api")
class GroupImportController(
private val fileParser: GroupFileParser,
private val groupManager: GroupManager