Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ plugins {
id("io.spring.dependency-management")
kotlin("plugin.spring")
}

kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict")
}
}
8 changes: 8 additions & 0 deletions backend/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,15 @@ io-github-numichi-reactive-logger = "6.0.3"
io-projectreactor-reactor-test = "3.6.11"
junit-junit = "4.13.2"
org-testcontainers = "1.20.3"
org-junit-platform = "1.11.4"
org-jetbrains-kotlin = "2.1.0"

[libraries]
org-springframework-boot-spring-boot = { module = "org.springframework.boot:spring-boot", version.ref = "org-springframework-boot-spring-boot" }
org-springframework-boot-spring-boot-starter-webflux = { module = "org.springframework.boot:spring-boot-starter-webflux", version.ref = "org-springframework-boot-spring-boot" }
org-springframework-boot-spring-boot-starter-data-r2dbc = { module = "org.springframework.boot:spring-boot-starter-data-r2dbc", version.ref = "org-springframework-boot-spring-boot" }
org-springframework-boot-spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "org-springframework-boot-spring-boot" }
org-springframework-boot-spring-boot-starter-web-services = { module = "org.springframework.boot:spring-boot-starter-web-services", version.ref = "org-springframework-boot-spring-boot" }
org-springframework-boot-spring-boot-starter-security = { module = "org.springframework.boot:spring-boot-starter-security", version.ref = "org-springframework-boot-spring-boot" }
org-springframework-boot-spring-boot-starter-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator", version.ref = "org-springframework-boot-spring-boot" }
org-springframework-boot-spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test", version.ref = "org-springframework-boot-spring-boot" }
Expand Down Expand Up @@ -84,10 +87,15 @@ io-micrometer-micrometer-registry-prometheus = { module = "io.micrometer:microme
com-github-loki4j-loki-logback-appender = { module = "com.github.loki4j:loki-logback-appender", version.ref = "com-github-loki4j" }
io-github-numichi-reactive-logger = { module = "io.github.numichi:reactive-logger", version.ref = "io-github-numichi-reactive-logger" }

org-jetbrains-kotlin-kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "org-jetbrains-kotlin" }

junit-junit = { module = "junit:junit", version.ref = "junit-junit" }
org-testcontainers-postgresql = { module = "org.testcontainers:postgresql", version.ref = "org-testcontainers" }
org-testcontainers-r2dbc = { module = "org.testcontainers:r2dbc", version.ref = "org-testcontainers" }
org-testcontainers-minio = { module = "org.testcontainers:minio", version.ref = "org-testcontainers" }
org-testcontainers-vault = { module = "org.testcontainers:vault", version.ref = "org-testcontainers" }
org-testcontainers-junit-jupiter = { module = "org.testcontainers:junit-jupiter", version.ref = "org-testcontainers" }
io-projectreactor-reactor-test = { module = "io.projectreactor:reactor-test", version.ref = "io-projectreactor-reactor-test" }
org-jetbrains-kotlin-kotlin-test-junit5 = { module = "org.jetbrains.kotlin:kotlin-test-junit5", version.ref = "org-jetbrains-kotlin" }
org-junit-platform-junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version.ref = "org-junit-platform" }

17 changes: 11 additions & 6 deletions backend/haproxy/config/haproxy.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ frontend internal
bind :8455 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem
bind :8456 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem
bind :8457 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem
bind :8458 ssl crt /usr/local/etc/haproxy/itmo-dating-backend.pem

use_backend vault if { dst_port 8445 }
use_backend consul if { dst_port 8446 }
use_backend grafana if { dst_port 8447 }
use_backend authik if { dst_port 8455 }
use_backend matchmaker if { dst_port 8456 }
use_backend people if { dst_port 8457 }
use_backend vault if { dst_port 8445 }
use_backend consul if { dst_port 8446 }
use_backend grafana if { dst_port 8447 }
use_backend authik if { dst_port 8455 }
use_backend matchmaker if { dst_port 8456 }
use_backend people if { dst_port 8457 }
use_backend matchmaker-soap if { dst_port 8458 }

backend vault
option httpchk GET /v1/sys/health?standbycode=200&sealedcode=200&uninitcode=200&drsecondarycode=200&performancestandbycode=200
Expand Down Expand Up @@ -64,3 +66,6 @@ backend people
option httpchk GET /actuator/health
server people-0 people-0.dating.se.ifmo.ru:8080 check init-addr last,libc,none ssl verify required ca-file /usr/local/etc/haproxy/itmo-dating-backend-ca.crt
server people-1 people-1.dating.se.ifmo.ru:8080 check init-addr last,libc,none ssl verify required ca-file /usr/local/etc/haproxy/itmo-dating-backend-ca.crt

backend matchmaker-soap
server matchmaker-soap matchmaker-soap.dating.se.ifmo.ru:8080 check init-addr last,libc,none ssl verify required ca-file /usr/local/etc/haproxy/itmo-dating-backend-ca.crt
9 changes: 9 additions & 0 deletions backend/matchmaker-soap/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM eclipse-temurin:23-jdk-alpine

WORKDIR /matchmaker-soap

COPY ./build/libs/matchmaker-soap-1.0.0.jar ./matchmaker-soap.jar

EXPOSE 8080

CMD ["java", "-jar", "matchmaker-soap.jar"]
68 changes: 68 additions & 0 deletions backend/matchmaker-soap/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import org.openapitools.generator.gradle.plugin.tasks.GenerateTask as OpenAPIGenerateTask

plugins {
id("buildlogic.spring-conventions")
id("com.github.bjornvester.wsdl2java") version "2.0.2"
}

val projectGroup = group

val matchmaker = "matchmaker"
val matchmakerTitle = matchmaker.replaceFirstChar { it.titlecase() }

val clientGeneratedDir = layout.buildDirectory
.dir("generated/client/$matchmaker").get().toString()

tasks.register<OpenAPIGenerateTask>("openApiGenerate${matchmakerTitle}Client") {
generatorName = "kotlin"
inputSpec = rootProject.layout.projectDirectory.asFile
.let { "$it/$matchmaker/src/main/resources/static/openapi/api.yml" }
outputDir = clientGeneratedDir
packageName = "$projectGroup.$matchmaker.client.generated"
modelPackage = "$projectGroup.$matchmaker.client.model.generated"
modelNameSuffix = "Message"
configOptions = mapOf(
"library" to "jvm-spring-restclient",
"useSpringBoot3" to "true",
"serializationLibrary" to "jackson",
)
}

val versionCxf = "4.1.0"

wsdl2java {
wsdlDir = file("$projectDir/src/main/resources/wsdl")
markGenerated = true
cxfVersion = versionCxf
}

sourceSets {
main {
kotlin {
srcDir("$clientGeneratedDir/src/main/kotlin")
}
}
}

tasks.compileKotlin.configure {
dependsOn("openApiGenerate${matchmakerTitle}Client")
dependsOn(tasks.wsdl2java)
}

dependencies {
api(project(":starter-tls"))

implementation(libs.org.springframework.boot.spring.boot.starter.web)
implementation(libs.org.springframework.boot.spring.boot.starter.web.services)

implementation(libs.com.fasterxml.jackson.module.jackson.module.kotlin)
implementation(libs.org.jetbrains.kotlin.kotlin.reflect)

implementation("org.springframework.ws:spring-ws-core:4.0.11")
implementation("org.apache.cxf:cxf-spring-boot-starter-jaxws:$versionCxf")

testImplementation(libs.org.springframework.boot.spring.boot.starter.test)
testImplementation(libs.org.jetbrains.kotlin.kotlin.reflect)
testImplementation(libs.org.jetbrains.kotlin.kotlin.test.junit5)
testRuntimeOnly(libs.org.junit.platform.junit.platform.launcher)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.ifmo.se.dating.matchmaker.soap

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.ComponentScan

@SpringBootApplication
@ComponentScan(basePackages = ["ru.ifmo.se.dating"])
class Application

fun main(args: Array<String>) {
runApplication<Application>(args = args)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ru.ifmo.se.dating.matchmaker.soap

import ru.ifmo.se.dating.matchmaker.*
import ru.ifmo.se.dating.matchmaker.client.model.generated.AttitudeKindMessage
import ru.ifmo.se.dating.matchmaker.client.model.generated.PersonStatusMessage
import ru.ifmo.se.dating.matchmaker.client.model.generated.PersonUpdateMessage
import ru.ifmo.se.dating.matchmaker.client.model.generated.StatisticsAttitudesGet200ResponseInnerMessage

fun List<Long>.toSuggestionsSoap(): GetSuggestionsResponse =
GetSuggestionsResponse().apply {
personId.addAll(this@toSuggestionsSoap.map { it.toInt() })
}

fun AttitudeKind.toRest(): AttitudeKindMessage =
when (this) {
AttitudeKind.LIKE -> AttitudeKindMessage.like
AttitudeKind.SKIP -> AttitudeKindMessage.skip
}

fun List<StatisticsAttitudesGet200ResponseInnerMessage>.toSoap(): GetAttitudesStatisticsResponse =
GetAttitudesStatisticsResponse().apply {
statistics.addAll(this@toSoap.map { it.toSoap() })
}

fun StatisticsAttitudesGet200ResponseInnerMessage.toSoap() =
GetAttitudesStatisticsResponse.Statistics().apply {
personId = this@toSoap.personId.toInt()
likes = this@toSoap.likes
skips = this@toSoap.skips
}

fun List<Long>.toMatchesSoap(): GetMatchesResponse =
GetMatchesResponse().apply {
personId.addAll(this@toMatchesSoap.map { it.toInt() })
}

fun PersonUpdate.toRest(): PersonUpdateMessage =
PersonUpdateMessage(
status = this.status.toRest(),
version = this.version,
)

fun PersonStatus.toRest(): PersonStatusMessage =
when (this) {
PersonStatus.HIDDEN -> PersonStatusMessage.hidden
PersonStatus.ACTIVE -> PersonStatusMessage.active
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.ifmo.se.dating.matchmaker.soap

import org.springframework.web.client.RestClient
import ru.ifmo.se.dating.matchmaker.client.generated.apis.PeopleApi
import ru.ifmo.se.dating.matchmaker.client.generated.apis.StatisticsApi
import ru.ifmo.se.dating.matchmaker.client.generated.apis.SuggestionsApi

class MatchmakerRestClient(private val client: RestClient) {
fun people(authorization: String? = null) =
PeopleApi(clientWithHeaders(authorization))

fun statistics(authorization: String? = null) =
StatisticsApi(clientWithHeaders(authorization))

fun suggestions(authorization: String? = null) =
SuggestionsApi(clientWithHeaders(authorization))

private fun clientWithHeaders(authorization: String? = null) =
client.mutate()
.apply { client ->
authorization?.let {
client.defaultHeader("Authorization", "Bearer $it")
}
}
.build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package ru.ifmo.se.dating.matchmaker.soap

import org.springframework.stereotype.Controller
import ru.ifmo.se.dating.matchmaker.*

@Controller
class MatchmakerSoapService(
private val rest: MatchmakerRestClient,
) : ITMODatingMatchmakerPortType {
override fun getSuggestions(
authorization: String,
parameters: GetSuggestionsRequest,
): GetSuggestionsResponse =
rest.suggestions(authorization = authorization)
.suggestionsGet(limit = parameters.limit.toLong())
.toSuggestionsSoap()

override fun likeSkip(
authorization: String,
parameters: LikeSkipRequest,
): LikeSkipResponse =
rest.suggestions(authorization = authorization)
.peoplePersonIdAttitudesIncomingAttitudeKindPost(
personId = parameters.personId.toLong(),
attitudeKind = parameters.attitudeKind.toRest(),
)
.let { LikeSkipResponse() }

override fun getAttitudesStatistics(parameters: Any): GetAttitudesStatisticsResponse =
rest.statistics()
.statisticsAttitudesGet()
.toSoap()

override fun getMatches(
authorization: String,
parameters: GetMatchesRequest,
): GetMatchesResponse =
rest.suggestions(authorization)
.peoplePersonIdMatchesGet(personId = parameters.personId.toLong())
.toMatchesSoap()

override fun updatePerson(parameters: UpdatePersonRequest): UpdatePersonResponse =
rest.people()
.peoplePersonIdPut(
personId = parameters.personId.toLong(),
personUpdateMessage = parameters.personUpdate.toRest(),
)
.let { UpdatePersonResponse() }

override fun resetAttitudes(
authorization: String,
parameters: ResetAttitudesRequest,
): ResetAttitudesResponse =
rest.suggestions(authorization)
.attitudesDelete(sourceId = parameters.sourceId.toLong())
.let { ResetAttitudesResponse() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ru.ifmo.se.dating.matchmaker.soap

import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.web.client.RestClientSsl
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.client.RestClient

@Configuration
class RestClientConfiguration {
@Bean
fun matchmakerRestClient(
@Value("\${itmo-dating.matchmaker.url}")
baseUrl: String,

ssl: RestClientSsl,
): MatchmakerRestClient = RestClient.builder()
.baseUrl("$baseUrl/api")
.messageConverters { it.add(MappingJackson2HttpMessageConverter()) }
.apply(ssl.fromBundle("internal"))
.build()
.let { MatchmakerRestClient(it) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.ifmo.se.dating.matchmaker.soap

import jakarta.xml.ws.Endpoint
import org.apache.cxf.Bus
import org.apache.cxf.bus.spring.SpringBus
import org.apache.cxf.jaxws.EndpointImpl
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import ru.ifmo.se.dating.matchmaker.ITMODatingMatchmakerPortType

@Configuration
class WebServiceConfiguration {
@Bean(Bus.DEFAULT_BUS_ID)
fun springBus(): SpringBus =
SpringBus()

@Bean
fun matchmakerEndpoint(
bus: Bus,
service: ITMODatingMatchmakerPortType,
): Endpoint {
val endpoint = EndpointImpl(bus, service)
endpoint.publish("/matchmaker")
return endpoint
}
}
20 changes: 20 additions & 0 deletions backend/matchmaker-soap/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
spring:
config:
import: application-tls.yml
application:
name: matchmaker-soap
ssl:
bundle:
jks:
internal:
keystore:
type: PKCS12
location: classpath:keystore/itmo-dating-backend.p12
password: ${ITMO_DATING_KEY_STORE_PASSWORD}
truststore:
type: PKCS12
location: classpath:keystore/itmo-dating-backend.p12
password: ${ITMO_DATING_KEY_STORE_PASSWORD}
itmo-dating:
matchmaker:
url: https://matchmaker-0.dating.se.ifmo.ru:8080
Loading
Loading