New Kotlin style guide applied

This commit is contained in:
2021-03-31 12:06:32 +02:00
parent 9c7f30f477
commit dab3b59ef0
20 changed files with 188 additions and 177 deletions

View File

@@ -1,7 +1,6 @@
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
@@ -12,5 +11,5 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories
class OkupaMiCocheApplication
fun main(args: Array<String>) {
runApplication<OkupaMiCocheApplication>(*args)
runApplication<OkupaMiCocheApplication>(*args)
}

View File

@@ -3,27 +3,27 @@ package eu.fosil.okupamicoche.dto
import eu.fosil.okupamicoche.entities.User
class CreateUserDto(
private val id: String,
private val username: String,
private val matrixId: String,
private val name: String,
private val email: String?
private val id: String,
private val username: String,
private val matrixId: String,
private val name: String,
private val email: String?
) {
constructor(user: User) : this(
user.id,
user.username,
user.matrixId,
user.name,
user.email
user.id,
user.username,
user.matrixId,
user.name,
user.email
)
fun toUser(): User {
return User(
id = id,
username = username,
matrixId = matrixId,
name = name,
email = email
id = id,
username = username,
matrixId = matrixId,
name = name,
email = email
)
}
}

View File

@@ -1,5 +1,6 @@
package eu.fosil.okupamicoche.dto
import com.fasterxml.jackson.annotation.JsonFormat
import eu.fosil.okupamicoche.entities.Travel
import eu.fosil.okupamicoche.entities.TravelId
import eu.fosil.okupamicoche.entities.UserIdNotFoundException
@@ -9,44 +10,45 @@ import org.springframework.data.repository.findByIdOrNull
import java.time.LocalDateTime
class TravelDto(
// Los campos deben ser públicos para que aparezcan en el JSON
val id: TravelId? = null,
var driverInfo: UserInfoDto? = null,
val travelersInfo: List<UserInfoDto> = emptyList(),
val departureDate: LocalDateTime = LocalDateTime.MIN,
val origin: String = "",
val destination: String = "",
val places: Int = 0,
var description: String? = null,
val matrixRoomId: String = ""
// Los campos deben ser públicos para que aparezcan en el JSON
val id: TravelId? = null,
var driverInfo: UserInfoDto? = null,
val travelersInfo: List<UserInfoDto> = emptyList(),
@JsonFormat(shape = JsonFormat.Shape.STRING)
val departureDate: LocalDateTime = LocalDateTime.MIN,
val origin: String = "",
val destination: String = "",
val places: Int = 0,
var description: String? = null,
val matrixRoomId: String = ""
) {
constructor(travel: Travel) : this(
travel.id,
UserInfoDto(travel.driver),
travel.travelers.map { traveler -> UserInfoDto(traveler) },
travel.departureDate,
travel.origin,
travel.destination,
travel.places,
travel.description,
travel.matrixRoomId
travel.id,
UserInfoDto(travel.driver),
travel.travelers.map { traveler -> UserInfoDto(traveler) },
travel.departureDate,
travel.origin,
travel.destination,
travel.places,
travel.description,
travel.matrixRoomId
)
fun toTravel(userRepository: UserRepository): Travel {
driverInfo?.let { driverInfo ->
val driver = userRepository.findByIdOrNull(driverInfo.id) ?: throw UserIdNotFoundException()
val travelers = travelersInfo.mapNotNull { t -> userRepository.findByIdOrNull(t.id) }
.toMutableList()
.toMutableList()
return Travel(
id,
driver,
travelers,
departureDate,
origin,
destination,
places,
description,
matrixRoomId
id,
driver,
travelers,
departureDate,
origin,
destination,
places,
description,
matrixRoomId
)
}
throw UserNotSpecifiedException()

View File

@@ -5,34 +5,34 @@ import eu.fosil.okupamicoche.entities.UserId
import eu.fosil.okupamicoche.repositories.UserRepository
class UserDto(
// Los campos deben ser públicos para que aparezcan en el JSON
val id: UserId,
val username: String,
val matrixId: String,
val name: String,
val email: String?,
val travelsAsDriver: List<TravelDto> = emptyList(),
val travelsAsTraveler: List<TravelDto> = emptyList()
// Los campos deben ser públicos para que aparezcan en el JSON
val id: UserId,
val username: String,
val matrixId: String,
val name: String,
val email: String?,
val travelsAsDriver: List<TravelDto> = emptyList(),
val travelsAsTraveler: List<TravelDto> = emptyList()
) {
constructor(user: User) : this(
user.id,
user.username,
user.matrixId,
user.name,
user.email,
user.travelsAsDriver.map { t -> TravelDto(t) },
user.travelsAsTraveler.map { t -> TravelDto(t) }
user.id,
user.username,
user.matrixId,
user.name,
user.email,
user.travelsAsDriver.map { t -> TravelDto(t) },
user.travelsAsTraveler.map { t -> TravelDto(t) }
)
fun toUser(userRepository: UserRepository): User {
return User(
id,
username,
matrixId,
name,
email,
travelsAsDriver.map { t -> t.toTravel(userRepository) },
travelsAsTraveler.map { t -> t.toTravel(userRepository) }
id,
username,
matrixId,
name,
email,
travelsAsDriver.map { t -> t.toTravel(userRepository) },
travelsAsTraveler.map { t -> t.toTravel(userRepository) }
)
}
}

View File

@@ -4,25 +4,25 @@ import eu.fosil.okupamicoche.entities.User
import eu.fosil.okupamicoche.entities.UserId
class UserInfoDto(
// Los campos deben ser públicos para que aparezcan en el JSON
val id: UserId,
val username: String,
val matrixId: String,
val name: String
// Los campos deben ser públicos para que aparezcan en el JSON
val id: UserId,
val username: String,
val matrixId: String,
val name: String
) {
constructor(user: User) : this(
user.id,
user.username,
user.matrixId,
user.name
user.id,
user.username,
user.matrixId,
user.name
)
fun toUser(): User {
return User(
id,
username,
matrixId,
name
id,
username,
matrixId,
name
)
}
}

View File

@@ -9,19 +9,19 @@ typealias TravelId = Long
@Entity
class Travel(
@Id @GeneratedValue var id: TravelId? = null,
@ManyToOne
@LazyCollection(LazyCollectionOption.FALSE)
var driver: User,
@ManyToMany
@LazyCollection(LazyCollectionOption.FALSE)
var travelers: MutableList<User>,
var departureDate: LocalDateTime,
var origin: String,
var destination: String,
var places: Int,
var description: String? = null,
var matrixRoomId: String
@Id @GeneratedValue var id: TravelId? = null,
@ManyToOne
@LazyCollection(LazyCollectionOption.FALSE)
var driver: User,
@ManyToMany
@LazyCollection(LazyCollectionOption.FALSE)
var travelers: MutableList<User>,
var departureDate: LocalDateTime,
var origin: String,
var destination: String,
var places: Int,
var description: String? = null,
var matrixRoomId: String
) {
fun users(): Set<User> {
val allUsers = mutableSetOf(driver)

View File

@@ -2,7 +2,10 @@ package eu.fosil.okupamicoche.entities
import org.hibernate.annotations.LazyCollection
import org.hibernate.annotations.LazyCollectionOption
import javax.persistence.*
import javax.persistence.Entity
import javax.persistence.Id
import javax.persistence.ManyToMany
import javax.persistence.OneToMany
typealias UserId = String
@@ -16,6 +19,6 @@ class User(
@OneToMany
@LazyCollection(LazyCollectionOption.FALSE)
var travelsAsDriver: List<Travel> = emptyList(),
@ManyToMany@LazyCollection(LazyCollectionOption.FALSE)
@ManyToMany @LazyCollection(LazyCollectionOption.FALSE)
var travelsAsTraveler: List<Travel> = emptyList()
)

View File

@@ -1,31 +1,31 @@
package eu.fosil.okupamicoche.entities
class UserKeycloak(
val id: UserId,
val username: String,
val admin: Boolean,
val name: String,
val email: String
val id: UserId,
val username: String,
val admin: Boolean,
val name: String,
val email: String
) {
constructor(claims: Map<String, Any>) : this(
claims["sub"].toString(),
claims["preferred_username"].toString(),
try {
claims["admin"] as Boolean
} catch (e: Exception) {
false
},
claims["name"].toString(),
claims["email"].toString()
claims["sub"].toString(),
claims["preferred_username"].toString(),
try {
claims["admin"] as Boolean
} catch (e: Exception) {
false
},
claims["name"].toString(),
claims["email"].toString()
)
fun toUser(): User {
return User(
id,
username,
"@$username:synapse",
name,
email
id,
username,
"@$username:synapse",
name,
email
)
}
}

View File

@@ -12,15 +12,17 @@ import org.springframework.data.repository.query.Param
interface TravelRepository : PagingAndSortingRepository<Travel, TravelId> {
@Query("SELECT t FROM Travel t WHERE t.driver.id = :userId")
fun findUserTravelsAsDriver(@Param("userId") userId: UserId): List<Travel>
@Query("SELECT count(t) FROM Travel t WHERE t.driver.id = :userId")
fun countUserTravelsAsDriver(@Param("userId") userId: UserId): Long
@Query("SELECT t FROM Travel t JOIN t.travelers u WHERE u.id = :userId")
fun findUserTravelsAsTraveler(@Param("userId") userId: UserId): List<Travel>
@Query("SELECT count(t) FROM Travel t JOIN t.travelers u WHERE u.id = :userId")
fun countUserTravelsAsTraveler(@Param("userId") userId: UserId): Long
fun findByOriginContainingOrDestinationContainingAllIgnoreCase(
filter: String, filter2: String, pageable: Pageable
filter: String, filter2: String, pageable: Pageable
): Page<Travel>
}

View File

@@ -12,16 +12,19 @@ import eu.fosil.okupamicoche.usecases.travel.*
import mu.KotlinLogging
import org.springframework.data.repository.findByIdOrNull
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.security.Principal
@RestController
@RequestMapping("/api/travel")
class PrivateTravelRestController(
private val authService: AuthService,
private val userRepository: UserRepository,
private val travelRepository: TravelRepository,
private val useCaseService: UseCaseService
private val authService: AuthService,
private val userRepository: UserRepository,
private val travelRepository: TravelRepository,
private val useCaseService: UseCaseService
) : ApiRestController {
private val logger = KotlinLogging.logger {}
@@ -29,7 +32,7 @@ class PrivateTravelRestController(
suspend fun createTravel(@RequestBody @Validated travel: TravelDto, principal: Principal): ApiResponse<Unit> {
return response {
val driver = userRepository.findByIdOrNull(authService.currentUser(principal).id)
?: throw UserIdNotFoundException("Current user not found.")
?: throw UserIdNotFoundException("Current user not found.")
if (travel.id != null && (travelRepository.findByIdOrNull(travel.id) != null))
throw CannotDuplicateIdException("Travel id already exists.")
travel.driverInfo = UserInfoDto(driver)
@@ -91,21 +94,21 @@ class PrivateTravelRestController(
@RequestMapping("/addtraveler")
suspend fun addTraveler(
@RequestParam @Validated travelId: TravelId,
@RequestParam @Validated userId: UserId,
principal: Principal
@RequestParam @Validated travelId: TravelId,
@RequestParam @Validated userId: UserId,
principal: Principal
): ApiResponse<Unit> {
return response {
throwErrorIfCannotEditTravel(travelId,principal)
throwErrorIfCannotEditTravel(travelId, principal)
AddTraveler(userRepository, travelRepository).addTraveler(travelId, userId)
}
}
@RequestMapping("/removetraveler")
suspend fun removeTraveler(
@RequestParam @Validated travelId: TravelId,
@RequestParam @Validated userId: UserId,
principal: Principal
@RequestParam @Validated travelId: TravelId,
@RequestParam @Validated userId: UserId,
principal: Principal
): ApiResponse<Unit> {
return response {
throwErrorIfCannotEditTravel(travelId, principal)
@@ -114,9 +117,9 @@ class PrivateTravelRestController(
}
private fun throwErrorIfCannotEditTravel(
travelId: TravelId?,
principal: Principal,
message: String = "Only admins and travel driver can modify this travel."
travelId: TravelId?,
principal: Principal,
message: String = "Only admins and travel driver can modify this travel."
) {
if (!authService.canEditTravel(travelId, principal))
throw InsufficientPermissions(message)

View File

@@ -18,8 +18,8 @@ import java.security.Principal
@RestController
@RequestMapping("/api/user")
class PrivateUserRestController(
private val authService: AuthService,
private val userRepository: UserRepository
private val authService: AuthService,
private val userRepository: UserRepository
) : ApiRestController {
@RequestMapping("/user")
@@ -39,8 +39,8 @@ class PrivateUserRestController(
@RequestMapping("/create")
suspend fun createUser(
@RequestBody @Validated createUserDto: CreateUserDto,
principal: Principal
@RequestBody @Validated createUserDto: CreateUserDto,
principal: Principal
): ApiResponse<Unit> {
return response {
if (!authService.isAdmin(principal))
@@ -80,9 +80,9 @@ class PrivateUserRestController(
}
private fun throwErrorIfCannotEditUser(
userId: UserId?,
principal: Principal,
message: String = "Only admins and travel driver can modify this user."
userId: UserId?,
principal: Principal,
message: String = "Only admins and travel driver can modify this user."
) {
if (!authService.canEditUser(userId, principal))
throw InsufficientPermissions(message)

View File

@@ -1,14 +1,13 @@
package eu.fosil.okupamicoche.spring.controller
import eu.fosil.okupamicoche.dto.TravelDto
import eu.fosil.okupamicoche.dto.ListDto
import eu.fosil.okupamicoche.dto.TravelDto
import eu.fosil.okupamicoche.entities.ApiResponse
import eu.fosil.okupamicoche.entities.TravelId
import eu.fosil.okupamicoche.repositories.TravelRepository
import eu.fosil.okupamicoche.usecases.travel.ListTravels
import org.springframework.data.repository.findByIdOrNull
import org.springframework.validation.annotation.Validated
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
@@ -19,17 +18,17 @@ class PublicRestController(private val travelRepository: TravelRepository) : Api
@RequestMapping("/list")
suspend fun listTravels(
@RequestParam @Validated filter: String?,
@RequestParam @Validated sortColumn: String?,
@RequestParam @Validated sortAscending: Boolean?,
@RequestParam @Validated pageIndex: Int?,
@RequestParam @Validated pageSize: Int?,
@RequestParam @Validated filter: String?,
@RequestParam @Validated sortColumn: String?,
@RequestParam @Validated sortAscending: Boolean?,
@RequestParam @Validated pageIndex: Int?,
@RequestParam @Validated pageSize: Int?,
): ApiResponse<ListDto<TravelDto>> {
return response {
val travels =
ListTravels(travelRepository).listTravels(
filter, sortColumn, sortAscending, pageIndex, pageSize
).map { t -> TravelDto(t) }
ListTravels(travelRepository).listTravels(
filter, sortColumn, sortAscending, pageIndex, pageSize
).map { t -> TravelDto(t) }
ListDto(travelRepository.count(), travels)
}
}

View File

@@ -13,7 +13,7 @@ import java.security.Principal
@Service
class AuthService(
private val travelRepository: TravelRepository
private val travelRepository: TravelRepository
) {
private val logger = KotlinLogging.logger {}

View File

@@ -18,10 +18,10 @@ class MatrixService(private val matrixClient: MatrixClient) : MatrixApi {
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
name = name,
roomAliasId = MatrixId.RoomAliasId("#$alias:synapse"),
invite = usersToInviteId.collect(Collectors.toSet()),
topic = topic
)
return roomId.full
}

View File

@@ -8,9 +8,9 @@ import org.springframework.stereotype.Service
@Service
class UseCaseService(
private val travelRepository: TravelRepository,
private val matrixService: MatrixService
): UseCaseFactory {
private val travelRepository: TravelRepository,
private val matrixService: MatrixService
) : UseCaseFactory {
override fun getCreateTravel(): CreateTravel {
return CreateTravel(travelRepository, getCreateRoomForTravel())
}

View File

@@ -7,8 +7,8 @@ import eu.fosil.okupamicoche.repositories.UserRepository
import org.springframework.data.repository.findByIdOrNull
class AddTraveler(
private val userRepository: UserRepository,
private val travelRepository: TravelRepository
private val userRepository: UserRepository,
private val travelRepository: TravelRepository
) {
fun addTraveler(travelId: TravelId, userId: UserId) {
val user = userRepository.findByIdOrNull(userId)

View File

@@ -11,28 +11,28 @@ class ListTravels(private val travelRepository: TravelRepository) {
}
fun listTravels(
filter: String?,
sortColumn: String?,
sortAscending: Boolean?,
pageIndex: Int?,
pageSize: Int?
filter: String?,
sortColumn: String?,
sortAscending: Boolean?,
pageIndex: Int?,
pageSize: Int?
): List<Travel> {
val sort = if (sortColumn == null) {
Sort.unsorted()
} else {
Sort.by(
if (sortAscending != false) Sort.Direction.ASC else Sort.Direction.DESC,
sortColumn
if (sortAscending != false) Sort.Direction.ASC else Sort.Direction.DESC,
sortColumn
)
}
return travelRepository.findByOriginContainingOrDestinationContainingAllIgnoreCase(
filter ?: "",
filter ?: "",
PageRequest.of(
pageIndex ?: 0,
pageSize ?: 10,
sort
)
filter ?: "",
filter ?: "",
PageRequest.of(
pageIndex ?: 0,
pageSize ?: 10,
sort
)
).toList()
}
}

View File

@@ -7,8 +7,8 @@ import eu.fosil.okupamicoche.repositories.TravelRepository
class ListUserTravels(private val travelRepository: TravelRepository) {
fun listUserTravels(idUser: UserId): List<Travel> {
return listOf(
travelRepository.findUserTravelsAsDriver(idUser),
travelRepository.findUserTravelsAsTraveler(idUser)
travelRepository.findUserTravelsAsDriver(idUser),
travelRepository.findUserTravelsAsTraveler(idUser)
).flatten()
}

View File

@@ -7,8 +7,8 @@ import eu.fosil.okupamicoche.repositories.UserRepository
import org.springframework.data.repository.findByIdOrNull
class RemoveTraveler(
private val userRepository: UserRepository,
private val travelRepository: TravelRepository
private val userRepository: UserRepository,
private val travelRepository: TravelRepository
) {
fun removeTraveler(travelId: TravelId, userId: UserId) {
val user = userRepository.findByIdOrNull(userId)

View File

@@ -14,6 +14,9 @@ spring:
resourceserver:
jwt:
issuer-uri: http://localhost:8080/auth/realms/okupamicoche
jackson:
serialization:
write-dates-as-timestamps: false
logging:
level: