fix: Add missing classes
This commit is contained in:
parent
b1439615bc
commit
06ce3e34b0
|
@ -0,0 +1,12 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="MainApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
||||
<envs>
|
||||
<env name="CLIENT_SECRET" value="GQNAuOqPjtXUGBuu1rEbNrWYdnoAzFwM" />
|
||||
</envs>
|
||||
<module name="routing.server.main" />
|
||||
<option name="SPRING_BOOT_MAIN_CLASS" value="de.hbt.routing.MainApplication" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
|
@ -0,0 +1,38 @@
|
|||
plugins {
|
||||
id("hbt.jib")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":server"))
|
||||
}
|
||||
|
||||
jib {
|
||||
from {
|
||||
image = "amazoncorretto:" + properties["projectSourceCompatibility"] + "-alpine"
|
||||
platforms {
|
||||
platform {
|
||||
architecture = "amd64"
|
||||
os = "linux"
|
||||
}
|
||||
platform {
|
||||
architecture = "arm64"
|
||||
os = "linux"
|
||||
}
|
||||
}
|
||||
}
|
||||
to {
|
||||
image = "hbt/routing"
|
||||
tags = setOf(
|
||||
"latest",
|
||||
properties["version"].toString().replace("+", "-"))
|
||||
auth {
|
||||
username = System.getenv("USERNAME")
|
||||
password = System.getenv("PASSWORD")
|
||||
}
|
||||
}
|
||||
container {
|
||||
mainClass = "de.hbt.routing.MainApplicationKt"
|
||||
jvmFlags = listOf("-XX:+UseContainerSupport",
|
||||
"-XX:MaxRAMPercentage=75.0")
|
||||
}
|
||||
}
|
|
@ -2,10 +2,8 @@ package de.hbt.routing
|
|||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
import org.springframework.data.mongodb.config.EnableMongoAuditing
|
||||
import org.springframework.scheduling.annotation.EnableScheduling
|
||||
|
||||
@EnableMongoAuditing
|
||||
@EnableScheduling
|
||||
@SpringBootApplication(scanBasePackages = ["de.hbt.support", "de.hbt.routing"])
|
||||
open class MainApplication
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package de.hbt.routing.configuration
|
||||
|
||||
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType
|
||||
import io.swagger.v3.oas.annotations.security.OAuthFlow
|
||||
import io.swagger.v3.oas.annotations.security.OAuthFlows
|
||||
import io.swagger.v3.oas.annotations.security.SecurityScheme
|
||||
import io.swagger.v3.oas.models.OpenAPI
|
||||
import io.swagger.v3.oas.models.info.Info
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@SecurityScheme(name = "bearerAuth", type = SecuritySchemeType.HTTP, scheme = "bearer", bearerFormat = "JWT")
|
||||
@SecurityScheme(
|
||||
name = "oauth2",
|
||||
type = SecuritySchemeType.OAUTH2,
|
||||
flows = OAuthFlows(
|
||||
implicit = OAuthFlow(
|
||||
authorizationUrl = "https://id.2martens.de/realms/2martens/protocol/openid-connect/auth",
|
||||
tokenUrl = "https://id.2martens.de/realms/2martens/protocol/openid-connect/token"
|
||||
)
|
||||
)
|
||||
)
|
||||
@Configuration
|
||||
open class OpenApiConfiguration {
|
||||
@Bean
|
||||
open fun customOpenAPI(
|
||||
@Value("\${openapi.description}") apiDescription: String,
|
||||
@Value("\${openapi.version}") apiVersion: String, @Value("\${openapi.title}") apiTitle: String
|
||||
): OpenAPI {
|
||||
return OpenAPI()
|
||||
.info(
|
||||
Info()
|
||||
.title(apiTitle)
|
||||
.version(apiVersion)
|
||||
.description(apiDescription)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package de.hbt.routing.configuration
|
||||
|
||||
import de.hbt.routing.property.ServiceProperties
|
||||
import de.hbt.support.property.HealthCheckProperties
|
||||
import de.hbt.support.property.RestTemplateTimeoutProperties
|
||||
import de.hbt.support.property.StatusProbeProperties
|
||||
import de.hbt.support.property.TimeProperties
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(RestTemplateTimeoutProperties::class,
|
||||
StatusProbeProperties::class, TimeProperties::class,
|
||||
HealthCheckProperties::class, ServiceProperties::class)
|
||||
open class PropertyConfiguration
|
|
@ -0,0 +1,29 @@
|
|||
package de.hbt.routing.configuration
|
||||
|
||||
import de.hbt.support.interceptor.HeaderInterceptorRest
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.http.HttpMethod
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
|
||||
@Configuration
|
||||
open class WebConfiguration(private val headerInterceptorRest: HeaderInterceptorRest) : WebMvcConfigurer {
|
||||
override fun addInterceptors(registry: InterceptorRegistry) {
|
||||
registry.addInterceptor(headerInterceptorRest)
|
||||
}
|
||||
|
||||
override fun addCorsMappings(registry: CorsRegistry) {
|
||||
val registration = registry.addMapping("/**")
|
||||
registration.allowedMethods(
|
||||
HttpMethod.GET.name(), HttpMethod.POST.name(),
|
||||
HttpMethod.PUT.name(), HttpMethod.HEAD.name(),
|
||||
HttpMethod.DELETE.name()
|
||||
)
|
||||
registration.allowCredentials(true)
|
||||
registration.allowedOrigins(
|
||||
"http://localhost:4200",
|
||||
"https://timetable.2martens.de"
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package de.hbt.routing.configuration
|
||||
|
||||
import de.hbt.support.security.SpringPolicyEnforcerFilter
|
||||
import org.keycloak.adapters.authorization.spi.ConfigurationResolver
|
||||
import org.keycloak.adapters.authorization.spi.HttpRequest
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig
|
||||
import org.keycloak.util.JsonSerialization
|
||||
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.security.config.Customizer
|
||||
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.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder
|
||||
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import java.io.IOException
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
open class WebSecurityConfiguration {
|
||||
@Value("\${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
|
||||
private lateinit var jwkSetUri: String
|
||||
|
||||
@Value("#{environment.CLIENT_SECRET}")
|
||||
private lateinit var clientSecret: String
|
||||
|
||||
@Bean
|
||||
@Throws(Exception::class)
|
||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http
|
||||
.csrf { it.disable() }
|
||||
.authorizeHttpRequests { it.requestMatchers(*PERMITTED_PATHS.toTypedArray<String>()).permitAll() }
|
||||
.authorizeHttpRequests { it.requestMatchers(HttpMethod.OPTIONS).permitAll() }
|
||||
.authorizeHttpRequests { it.anyRequest().authenticated() }
|
||||
.oauth2ResourceServer { obj: OAuth2ResourceServerConfigurer<HttpSecurity?> -> obj.jwt(Customizer.withDefaults()) }
|
||||
.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter::class.java)
|
||||
return http.build()
|
||||
}
|
||||
|
||||
@Bean
|
||||
open fun jwtDecoder(): JwtDecoder {
|
||||
return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build()
|
||||
}
|
||||
|
||||
private fun createPolicyEnforcerFilter(): SpringPolicyEnforcerFilter {
|
||||
return SpringPolicyEnforcerFilter(object : ConfigurationResolver {
|
||||
override fun resolve(request: HttpRequest): PolicyEnforcerConfig {
|
||||
return try {
|
||||
val policyEnforcerConfig = JsonSerialization.readValue(
|
||||
javaClass.getResourceAsStream("/policy-enforcer.json"), PolicyEnforcerConfig::class.java
|
||||
)
|
||||
policyEnforcerConfig.credentials = mapOf(Pair("secret", clientSecret))
|
||||
if (request.method == HttpMethod.OPTIONS.name()) {
|
||||
// always allow options request
|
||||
policyEnforcerConfig.enforcementMode = EnforcementMode.DISABLED
|
||||
} else {
|
||||
policyEnforcerConfig.paths = PATHS
|
||||
}
|
||||
policyEnforcerConfig
|
||||
} catch (e: IOException) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val PERMITTED_PATHS: Collection<String> = listOf(
|
||||
"/routing/healthCheck",
|
||||
"/actuator/**",
|
||||
"/doc/v1/routing/**",
|
||||
"/api-docs/v1/routing/**",
|
||||
"/error",
|
||||
"/routing/version",
|
||||
)
|
||||
private val PATHS = buildPathConfigs()
|
||||
|
||||
private fun buildPathConfigs(): List<PathConfig> {
|
||||
val paths: MutableList<PathConfig> = mutableListOf()
|
||||
for (path in PERMITTED_PATHS) {
|
||||
val pathConfig = PathConfig()
|
||||
pathConfig.path = path.replace("**", "*")
|
||||
pathConfig.enforcementMode = EnforcementMode.DISABLED
|
||||
paths.add(pathConfig)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package de.hbt.routing.property
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "de.hbt.routing")
|
||||
@Schema(description = "Properties, to configure this Application")
|
||||
class ServiceProperties {
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
spring:
|
||||
config:
|
||||
import:
|
||||
- "classpath:config/routing.yaml"
|
||||
- "optional:configserver:${CONFIGSERVER_SCHEME:http}://${CONFIGSERVER_HOST:localhost}:${CONFIGSERVER_PORT:8888}${CONFIGSERVER_PREFIX:/config}"
|
|
@ -26,6 +26,9 @@ management:
|
|||
http.server.requests: true
|
||||
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
name: routing
|
||||
main:
|
||||
banner-mode: off
|
||||
profiles:
|
||||
|
@ -33,14 +36,13 @@ spring:
|
|||
# data.mongodb:
|
||||
# uri: ${MONGODB_CONNECTION_STRING}
|
||||
# auto-index-creation: true
|
||||
# security:
|
||||
# oauth2:
|
||||
# resourceserver:
|
||||
# jwt:
|
||||
# jwk-set-uri: ${KEYCLOAK_URL:https://id.2martens.de}/realms/${KEYCLOAK_REALM:2martens}/protocol/openid-connect/certs
|
||||
# application:
|
||||
# name: timetable
|
||||
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
jwk-set-uri: ${KEYCLOAK_URL:https://id.2martens.de}/realms/${KEYCLOAK_REALM:2martens}/protocol/openid-connect/certs
|
||||
application:
|
||||
name: routing
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
display-request-duration: true
|
||||
|
@ -74,7 +76,6 @@ resttemplate:
|
|||
readTimeoutRestTemplateInMillis: 5000
|
||||
connectionRestTemplateTimeoutInMillis: 5000
|
||||
|
||||
de.hbt.routing:
|
||||
de.hbt.support.health.greeting: "Good morning"
|
||||
|
||||
time:
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
de.hbt.support.health:
|
||||
greeting: "Moin %s, you are test"
|
|
@ -0,0 +1,7 @@
|
|||
de.hbt.routing:
|
||||
statusprobe:
|
||||
scheduleDuration: 60
|
||||
maxKafkaFailureDuration: 5
|
||||
maxBlobFailureCount: 5
|
||||
maxFailurePercent: 50
|
||||
de.hbt.support.health.greeting: "Hello %s, on millenium"
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"realm": "2martens",
|
||||
"auth-server-url": "https://id.2martens.de",
|
||||
"resource": "routing",
|
||||
"http-method-as-scope": true
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<th:block th:insert="~{errorIncludes :: head}"/>
|
||||
<body>
|
||||
<th:block th:insert="~{errorIncludes :: mainText}"/>
|
||||
<th:block th:insert="~{errorIncludes :: footer}"/>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<th:block th:insert="~{errorIncludes :: head}" />
|
||||
<body>
|
||||
<th:block th:insert="~{errorIncludes :: mainText}" />
|
||||
<p>The requested URL <code th:text="${path}"></code> was not found on this server.</p>
|
||||
<th:block th:insert="~{errorIncludes :: footer}" />
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head th:fragment="head">
|
||||
<title>Error <th:block th:text="${status}"/> (<th:block th:text="${error}"/>)</title>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html{background:#000000;color:#ffffff;font:15px/22px arial,sans-serif}
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
html{background:#ffffff;color:#000000;font:15px/22px arial,sans-serif}
|
||||
}
|
||||
body{margin:50px}
|
||||
h1,footer{margin:20px 0}
|
||||
p{margin:0}
|
||||
code{font-family: monospace,monospace}
|
||||
.foot{color:#777777;font-size:80%}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<th:block th:fragment="mainText">
|
||||
<h1>TSW Timetable</h1>
|
||||
<p>
|
||||
<b th:text="${status}"></b> <th:block th:text="${error}" />
|
||||
</p>
|
||||
</th:block>
|
||||
<footer class="foot" th:fragment="footer"><th:block th:text="${footerString}" /></footer>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
|
||||
<head th:fragment="head">
|
||||
<title th:text="${version}"></title>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html{background:#000000;color:#ffffff;font:15px/22px arial,sans-serif}
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
html{background:#ffffff;color:#000000;font:15px/22px arial,sans-serif}
|
||||
}
|
||||
body{margin:50px}
|
||||
h1,footer{margin:20px 0}
|
||||
p{margin:0}
|
||||
code{font-family: monospace,monospace}
|
||||
.foot{color:#777777;font-size:80%}
|
||||
</style>
|
||||
</head>
|
||||
<body style="font-family:sans-serif; line-height: 1.4em;">
|
||||
<h2>
|
||||
<th:block th:text="${version}"/>
|
||||
</h2>
|
||||
<p>
|
||||
Hostname:
|
||||
<th:block th:text="${hostname}"/>
|
||||
</p>
|
||||
<p>
|
||||
<th:block th:each="item : ${manifest}">
|
||||
<th:block th:text="${item}"/>
|
||||
<br/>
|
||||
</th:block>
|
||||
</p>
|
||||
<footer class="foot" th:fragment="footer">
|
||||
<th:block th:text="${footerString}"/>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RequestMapping
|
|||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = ["/timetable"])
|
||||
@RequestMapping(value = ["/routing"])
|
||||
class HealthCheckController(private val properties: HealthCheckProperties) {
|
||||
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ class RestHealthIndicator(
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val URL_PATH = "/timetable/healthCheck"
|
||||
private const val URL_PATH = "/routing/healthCheck"
|
||||
private const val GET_PARAMETER = "message="
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ package de.hbt.support.property
|
|||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.boot.context.properties.bind.ConstructorBinding
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope
|
||||
import java.time.ZoneId
|
||||
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "time")
|
||||
@Schema(description = "Properties to configure time")
|
||||
data class TimeProperties @ConstructorBinding constructor(
|
||||
|
|
|
@ -10,4 +10,5 @@ dependencies {
|
|||
implementation(libs.spring.openapi)
|
||||
|
||||
implementation(libs.bundles.spring.boot.security)
|
||||
implementation(libs.spring.cloud.starter.config)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
val projectname: String = providers.gradleProperty("projectname").get()
|
||||
rootProject.name = projectname
|
||||
|
||||
include("deploy")
|
||||
include("support")
|
||||
include("server")
|
||||
|
||||
|
|
Loading…
Reference in New Issue