Compare commits

1 Commits

Author SHA1 Message Date
e3bf3c1a25 Matrix app service test 2021-03-29 01:07:36 +02:00
9 changed files with 145 additions and 106 deletions

View File

@@ -1,12 +1,12 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.4.1"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
id("org.springframework.boot") version "2.5.0-M3"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
war
kotlin("jvm") version "1.4.21"
kotlin("plugin.spring") version "1.4.21"
kotlin("plugin.jpa") version "1.4.21"
kotlin("jvm") version "1.4.31"
kotlin("plugin.spring") version "1.4.31"
kotlin("plugin.jpa") version "1.4.31"
}
group = "eu.fosil"
@@ -15,23 +15,33 @@ java.sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
maven { url = uri("https://repo.spring.io/milestone") }
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
implementation("io.github.microutils:kotlin-logging-jvm:2.0.6")
implementation("com.nimbusds:nimbus-jose-jwt:8.20.2")
implementation("com.nimbusds:oauth2-oidc-sdk:8.36.1")
implementation("org.springframework.security:spring-security-oauth2-jose:5.4.5")
// https://mvnrepository.com/artifact/net.folivo/matrix-spring-boot-bot
implementation ("net.folivo:matrix-spring-boot-bot:0.4.6")
// implementation ("net.folivo:matrix-spring-boot-bot:0.4.6")
developmentOnly("org.springframework.boot:spring-boot-devtools")
runtimeOnly("com.h2database:h2")
runtimeOnly("io.r2dbc:r2dbc-h2")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
// runtimeOnly("io.r2dbc:r2dbc-h2")
// providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
}
tasks.withType<KotlinCompile> {

View File

@@ -1 +1,7 @@
rootProject.name = "okupamicoche"
pluginManagement {
repositories {
maven { url = uri("https://repo.spring.io/milestone") }
gradlePluginPortal()
}
}
rootProject . name = "okupamicoche"

View File

@@ -1,13 +1,14 @@
package eu.fosil.okupamicoche.spring
package eu.fosil.okupamicoche
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.runApplication
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.web.reactive.config.EnableWebFlux
@SpringBootApplication
@EnableJpaRepositories("eu.fosil.okupamicoche.*")
@EntityScan("eu.fosil.okupamicoche.*")
//@EnableJpaRepositories("eu.fosil.okupamicoche.*")
//@EntityScan("eu.fosil.okupamicoche.*")
class OkupaMiCocheApplication
fun main(args: Array<String>) {

View File

@@ -9,7 +9,7 @@ class Travel(
@Id @GeneratedValue var id: TravelId? = null,
@ManyToOne
var driver: User,
@ManyToMany
@ManyToMany(fetch = FetchType.EAGER) // https://stackoverflow.com/questions/22821695/how-to-fix-hibernate-lazyinitializationexception-failed-to-lazily-initialize-a
var travelers: MutableList<User>,
var departureDate: String,
var origin: String,

View File

@@ -1,5 +1,6 @@
package eu.fosil.okupamicoche.spring
import eu.fosil.okupamicoche.OkupaMiCocheApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

View File

@@ -1,33 +1,47 @@
package eu.fosil.okupamicoche.spring.conf
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.web.servlet.config.annotation.CorsRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
import org.springframework.security.config.web.server.ServerHttpSecurity
import org.springframework.security.web.server.SecurityWebFilterChain
import org.springframework.web.cors.CorsConfiguration
import org.springframework.web.cors.reactive.CorsWebFilter
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource
import org.springframework.web.reactive.config.CorsRegistry
import org.springframework.web.reactive.config.EnableWebFlux
import org.springframework.web.reactive.config.WebFluxConfigurer
@Configuration
class JWTSecurityConfig : WebSecurityConfigurerAdapter() {
@Throws(Exception::class)
override fun configure(http: HttpSecurity) {//@formatter:off
http.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/user/**").authenticated()
.antMatchers("/api/travel/**").authenticated()
.anyRequest().denyAll()
.and()
.oauth2ResourceServer()
.jwt()
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
class SecurityConfig {
@Bean
fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {//@formatter:off
http
.authorizeExchange { exchanges ->
exchanges
.pathMatchers("/_matrix/**").permitAll()
.pathMatchers("/api/public/**").permitAll()
.pathMatchers("/api/user/**").authenticated()
.pathMatchers("/api/travel/**").authenticated()
.anyExchange().denyAll()
}
.oauth2ResourceServer { oauth2ResourceServer ->
oauth2ResourceServer.jwt { jwt -> jwt }
}
return http.build()
}//@formatter:on
}
@Configuration
class CorsConfigurer : WebMvcConfigurer {
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200")
@EnableWebFlux
class CorsGlobalConfiguration : WebFluxConfigurer {
override fun addCorsMappings(corsRegistry: CorsRegistry) {
corsRegistry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("PUT", "GET", "POST")
.maxAge(3600)
}
}
}

View File

@@ -12,10 +12,13 @@ import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Mono
@RestController
@RequestMapping("/api/public")
@CrossOrigin(origins = ["http://localhost:4200"])
@CrossOrigin(value = [ "http://allowed-origin.com"],
maxAge = 900
)
class PublicRestController(private val travelRepository: TravelRepository) : ApiRestController {
@RequestMapping("/list")
@@ -25,20 +28,20 @@ class PublicRestController(private val travelRepository: TravelRepository) : Api
@RequestParam @Validated sortAscending: Boolean?,
@RequestParam @Validated pageIndex: Int?,
@RequestParam @Validated pageSize: Int?,
): ApiResponse<ListDto<TravelDto>> {
return response {
): Mono<ApiResponse<ListDto<TravelDto>>> {
return Mono.just(response {
val travels =
ListTravels(travelRepository).listTravels(
filter, sortColumn, sortAscending, pageIndex, pageSize
).map { t -> TravelDto(t) }
ListDto(travelRepository.count(), travels)
}
})
}
@RequestMapping("/travel")
suspend fun getTravel(@RequestParam @Validated travelId: TravelId): ApiResponse<TravelDto?> {
return response {
suspend fun getTravel(@RequestParam @Validated travelId: TravelId): Mono<ApiResponse<TravelDto?>> {
return Mono.just(response {
travelRepository.findByIdOrNull(travelId)?.let { TravelDto(it) }
}
})
}
}

View File

@@ -3,30 +3,33 @@ package eu.fosil.okupamicoche.spring.services
import eu.fosil.okupamicoche.entities.User
import eu.fosil.okupamicoche.usecases.matrix.MatrixApi
import mu.KotlinLogging
import net.folivo.matrix.core.model.MatrixId
import net.folivo.matrix.restclient.MatrixClient
//import net.folivo.matrix.core.model.MatrixId
//import net.folivo.matrix.restclient.MatrixClient
import org.springframework.stereotype.Service
import java.util.stream.Collectors
@Service
class MatrixService(private val matrixClient: MatrixClient): MatrixApi {
class MatrixService(
// private val matrixClient: MatrixClient
): MatrixApi {
private val logger = KotlinLogging.logger {}
override suspend fun createRoom(name: String, alias: String, usersToInvite: Set<User>, topic: String?): String {
logger.debug { "Creating room name=$name alias=$alias" }
val usersToInviteId = usersToInvite.stream().map { user -> MatrixId.UserId(user.matrixId) }
val roomId = matrixClient.roomsApi.createRoom(
name = name,
roomAliasId = MatrixId.RoomAliasId("#$alias:synapse"),
// invite = usersToInviteId.collect(Collectors.toSet()),
topic = topic
)
return roomId.full
// val usersToInviteId = usersToInvite.stream().map { user -> MatrixId.UserId(user.matrixId) }
// val roomId = matrixClient.roomsApi.createRoom(
// name = name,
// roomAliasId = MatrixId.RoomAliasId("#$alias:synapse"),
//// invite = usersToInviteId.collect(Collectors.toSet()),
// topic = topic
// )
// return roomId.full
return "0"
}
override suspend fun inviteUser(roomId: String, user: User) {
val matrixUserId = MatrixId.UserId(user.matrixId)
logger.debug { "Invite user $matrixUserId to room $roomId" }
matrixClient.roomsApi.inviteUser(MatrixId.RoomId(roomId), matrixUserId)
// val matrixUserId = MatrixId.UserId(user.matrixId)
// logger.debug { "Invite user $matrixUserId to room $roomId" }
// matrixClient.roomsApi.inviteUser(MatrixId.RoomId(roomId), matrixUserId)
}
}

View File

@@ -18,52 +18,53 @@ spring:
logging:
level:
eu.fosil.okupamicoche: DEBUG
net.folivo.matrix: DEBUG
matrix:
bot:
# The domain-part of matrix-ids. E. g. example.org when your userIds look like @unicorn:example.org
serverName: synapse
# The localpart (username) of the user associated with the application service
# or just the username of your bot.
username: okupamicoche
# (optional) Display name for the bot user.
displayname: Okupa mi coche
# (optional) The mode you want to use to create a bot. Default is CLIENT. The other is APPSERVICE.
mode: APPSERVICE
# (optional) Configure how users managed by your bot do automatically join rooms.
# ENABLED allows automatic joins to every invited room.
# DISABLED disables this feature.
# Default is RESTRICTED, which means, that only automatic joins to serverName are allowed.
autoJoin: DISABLED
# (optional) Configure if ALL membership changes should be tracked/saved with help of MatrixAppserviceRoomService
# or only membership changes of users, which are MANAGED by the bridge. Default is ALL (no tracking/saving).
trackMembership: ALL
# Connection setting to the database for migration purpose only (only jdbc drivers ar supported)
migration:
url: jdbc:h2:file:./matrix
username: sa
password:
# Connection settings to the database (only r2dbc drivers are supported)
database:
url: r2dbc:h2:file:///./matrix
username: sa
password:
client:
homeServer:
# The hostname of your Homeserver.
hostname: synapse
# (optional) The port of your Homeserver. Default is 443.
port: 8008
# (optional) Use http or https. Default is true (so uses https).
secure: false
# The token to authenticate against the Homeserver.
token: "30c05ae90a248a4188e620216fa72e349803310ec83e2a77b34fe90be6081f46"
appservice:
# A unique token for Homeservers to use to authenticate requests to application services.
hsToken: "312df522183efd404ec1cd22d2ffa4bbc76a8c1ccf541dd692eef281356bb74e"
# A list of users, aliases and rooms namespaces that the application service controls.
namespaces:
users: [ ]
aliases:
- localpartRegex: "viaje_.*"
rooms: [ ]
#matrix:
# bot:
# # The domain-part of matrix-ids. E. g. example.org when your userIds look like @unicorn:example.org
# serverName: synapse
# # The localpart (username) of the user associated with the application service
# # or just the username of your bot.
# username: okupamicoche
# # (optional) Display name for the bot user.
# displayname: Okupa mi coche
# # (optional) The mode you want to use to create a bot. Default is CLIENT. The other is APPSERVICE.
# mode: APPSERVICE
# # (optional) Configure how users managed by your bot do automatically join rooms.
# # ENABLED allows automatic joins to every invited room.
# # DISABLED disables this feature.
# # Default is RESTRICTED, which means, that only automatic joins to serverName are allowed.
# autoJoin: DISABLED
# # (optional) Configure if ALL membership changes should be tracked/saved with help of MatrixAppserviceRoomService
# # or only membership changes of users, which are MANAGED by the bridge. Default is ALL (no tracking/saving).
# trackMembership: ALL
# # Connection setting to the database for migration purpose only (only jdbc drivers ar supported)
# migration:
# url: jdbc:h2:file:./matrix
# username: sa
# password:
# # Connection settings to the database (only r2dbc drivers are supported)
# database:
# url: r2dbc:h2:file:///./matrix
# username: sa
# password:
# client:
# homeServer:
# # The hostname of your Homeserver.
# hostname: synapse
# # (optional) The port of your Homeserver. Default is 443.
# port: 8008
# # (optional) Use http or https. Default is true (so uses https).
# secure: false
# # The token to authenticate against the Homeserver.
# token: "30c05ae90a248a4188e620216fa72e349803310ec83e2a77b34fe90be6081f46"
# appservice:
# # A unique token for Homeservers to use to authenticate requests to application services.
# hsToken: "312df522183efd404ec1cd22d2ffa4bbc76a8c1ccf541dd692eef281356bb74e"
# # A list of users, aliases and rooms namespaces that the application service controls.
# namespaces:
# users: [ ]
# aliases:
# - localpartRegex: "viaje_.*"
# rooms: [ ]