summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/build.gradle.kts48
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/SevenWonders.kt13
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/actions/ChooseNameAction.kt19
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/actions/CreateGameAction.kt19
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/actions/JoinGameAction.kt17
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/actions/PrepareMoveAction.kt18
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/actions/ReorderPlayersAction.kt18
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/actions/UpdateSettingsAction.kt18
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/api/LobbyDTO.kt17
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/api/PlayerDTO.kt14
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/config/AnonymousUsersHandshakeHandler.kt27
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/config/TopicSubscriptionInterceptor.kt38
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSecurityConfig.kt12
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt44
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameBrowserController.kt112
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameController.kt102
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/controllers/HomeController.kt46
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/controllers/LobbyController.kt107
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/doc/Documentation.kt6
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/errors/ErrorDTO.kt29
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/errors/ExceptionHandler.kt44
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Lobby.kt111
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Player.kt61
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/repositories/LobbyRepository.kt31
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/repositories/PlayerRepository.kt41
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidator.kt47
-rw-r--r--backend/src/main/resources/application.properties2
-rw-r--r--backend/src/main/resources/static/images/tokens/coin1.pngbin6284 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/coin3.pngbin8770 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/free.pngbin5062 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/pyramid-stage0.pngbin3286 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/pyramid-stage1.pngbin4114 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/pyramid-stage2.pngbin4285 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/pyramid-stage3.pngbin20663 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/pyramid.pngbin3886 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/victory1.pngbin3676 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/victory3.pngbin4786 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/victory5.pngbin7657 -> 0 bytes
-rw-r--r--backend/src/main/resources/static/images/tokens/victoryminus1.pngbin5925 -> 0 bytes
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/SevenWondersTest.kt145
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/controllers/GameBrowserControllerTest.kt124
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/controllers/HomeControllerTest.kt25
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/controllers/LobbyControllerTest.kt217
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/controllers/TestPrincipal.kt8
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/lobby/LobbyTest.kt266
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/repositories/LobbyRepositoryTest.kt78
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/repositories/PlayerRepositoryTest.kt75
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/test/TestUtils.kt10
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt38
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersSession.kt70
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidatorTest.kt147
51 files changed, 0 insertions, 2264 deletions
diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts
deleted file mode 100644
index 8bb77645..00000000
--- a/backend/build.gradle.kts
+++ /dev/null
@@ -1,48 +0,0 @@
-plugins {
- id("org.jetbrains.kotlin.jvm")
- id("org.jetbrains.kotlin.plugin.spring")
- id("org.springframework.boot") version "2.1.3.RELEASE"
- id("org.jlleitschuh.gradle.ktlint") version "7.1.0"
-}
-
-apply(plugin = "io.spring.dependency-management")
-
-tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
- kotlinOptions.jvmTarget = "1.8"
-}
-
-dependencies {
- compile(project(":game-model"))
- compile(project(":game-engine"))
- compile(kotlin("stdlib-jdk8"))
- compile(kotlin("reflect")) // required by Spring 5
-
- compile("org.springframework.boot:spring-boot-starter-websocket")
- compile("org.springframework.boot:spring-boot-starter-security")
- // required by spring security when using websockets
- compile("org.springframework.security:spring-security-messaging")
-
- compile("com.fasterxml.jackson.module:jackson-module-kotlin")
-
- compile("ch.qos.logback:logback-classic:1.1.8")
- compile("org.hildan.livedoc:livedoc-springboot:4.3.2")
- compile("org.hildan.livedoc:livedoc-ui-webjar:4.3.2")
-
- annotationProcessor("org.hildan.livedoc:livedoc-javadoc-processor:4.3.2")
-
- testImplementation(kotlin("test"))
- testImplementation(kotlin("test-junit"))
- testImplementation("org.springframework.boot:spring-boot-starter-test")
- testImplementation("org.hildan.jackstomp:jackstomp:2.0.0")
- testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin")
-}
-
-// packages the frontend app within the jar
-tasks.bootJar {
- from("../frontend/build") {
- into("static")
- }
-}
-
-// make sure we build the frontend before creating the jar
-tasks.bootJar.get().dependsOn(":frontend:assemble")
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/SevenWonders.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/SevenWonders.kt
deleted file mode 100644
index 04f03956..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/SevenWonders.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.luxons.sevenwonders
-
-import org.hildan.livedoc.spring.boot.starter.EnableJSONDoc
-import org.springframework.boot.autoconfigure.SpringBootApplication
-import org.springframework.boot.runApplication
-
-@SpringBootApplication
-@EnableJSONDoc
-class SevenWonders
-
-fun main(args: Array<String>) {
- runApplication<SevenWonders>(*args)
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/ChooseNameAction.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/actions/ChooseNameAction.kt
deleted file mode 100644
index ab444780..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/ChooseNameAction.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.luxons.sevenwonders.actions
-
-import org.hildan.livedoc.core.annotations.types.ApiType
-import org.hildan.livedoc.core.annotations.types.ApiTypeProperty
-import org.luxons.sevenwonders.doc.Documentation
-import javax.validation.constraints.Size
-
-/**
- * The action to choose the player's name. This is the first action that should be called.
- */
-@ApiType(group = Documentation.GROUP_ACTIONS)
-class ChooseNameAction(
- /**
- * The display name of the player. May contain spaces and special characters.
- */
- @Size(min = 2, max = 20)
- @ApiTypeProperty(required = true)
- val playerName: String
-)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/CreateGameAction.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/actions/CreateGameAction.kt
deleted file mode 100644
index c10f9c34..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/CreateGameAction.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.luxons.sevenwonders.actions
-
-import org.hildan.livedoc.core.annotations.types.ApiType
-import org.hildan.livedoc.core.annotations.types.ApiTypeProperty
-import org.luxons.sevenwonders.doc.Documentation
-import javax.validation.constraints.Size
-
-/**
- * The action to create a game.
- */
-@ApiType(group = Documentation.GROUP_ACTIONS)
-class CreateGameAction(
- /**
- * The name of the game to create.
- */
- @Size(min = 2, max = 30)
- @ApiTypeProperty(required = true)
- val gameName: String
-)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/JoinGameAction.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/actions/JoinGameAction.kt
deleted file mode 100644
index 002309b3..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/JoinGameAction.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.luxons.sevenwonders.actions
-
-import org.hildan.livedoc.core.annotations.types.ApiType
-import org.hildan.livedoc.core.annotations.types.ApiTypeProperty
-import org.luxons.sevenwonders.doc.Documentation
-
-/**
- * The action to join a game.
- */
-@ApiType(group = Documentation.GROUP_ACTIONS)
-class JoinGameAction(
- /**
- * The ID of the game to join.
- */
- @ApiTypeProperty(required = true)
- val gameId: Long
-)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/PrepareMoveAction.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/actions/PrepareMoveAction.kt
deleted file mode 100644
index 6b39c486..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/PrepareMoveAction.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.luxons.sevenwonders.actions
-
-import org.hildan.livedoc.core.annotations.types.ApiType
-import org.hildan.livedoc.core.annotations.types.ApiTypeProperty
-import org.luxons.sevenwonders.doc.Documentation
-import org.luxons.sevenwonders.game.api.PlayerMove
-
-/**
- * The action to prepare the next move during a game.
- */
-@ApiType(group = Documentation.GROUP_ACTIONS)
-class PrepareMoveAction(
- /**
- * The move to prepare.
- */
- @ApiTypeProperty(required = true)
- val move: PlayerMove
-)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/ReorderPlayersAction.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/actions/ReorderPlayersAction.kt
deleted file mode 100644
index 79a32137..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/ReorderPlayersAction.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.luxons.sevenwonders.actions
-
-import org.hildan.livedoc.core.annotations.types.ApiType
-import org.hildan.livedoc.core.annotations.types.ApiTypeProperty
-import org.luxons.sevenwonders.doc.Documentation
-
-/**
- * The action to update the order of the players around the table. Can only be called in the lobby by the owner of the
- * game.
- */
-@ApiType(group = Documentation.GROUP_ACTIONS)
-class ReorderPlayersAction(
- /**
- * The list of usernames of the players, in the new order.
- */
- @ApiTypeProperty(required = true)
- val orderedPlayers: List<String>
-)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/UpdateSettingsAction.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/actions/UpdateSettingsAction.kt
deleted file mode 100644
index d13e5b45..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/actions/UpdateSettingsAction.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.luxons.sevenwonders.actions
-
-import org.hildan.livedoc.core.annotations.types.ApiType
-import org.hildan.livedoc.core.annotations.types.ApiTypeProperty
-import org.luxons.sevenwonders.doc.Documentation
-import org.luxons.sevenwonders.game.api.CustomizableSettings
-
-/**
- * The action to update the settings of the game. Can only be called in the lobby by the owner of the game.
- */
-@ApiType(group = Documentation.GROUP_ACTIONS)
-class UpdateSettingsAction(
- /**
- * The new values for the settings.
- */
- @ApiTypeProperty(required = true)
- val settings: CustomizableSettings
-)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/api/LobbyDTO.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/api/LobbyDTO.kt
deleted file mode 100644
index b4445f32..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/api/LobbyDTO.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.luxons.sevenwonders.api
-
-import org.luxons.sevenwonders.lobby.Lobby
-import org.luxons.sevenwonders.lobby.State
-
-data class LobbyDTO(
- val id: Long,
- val name: String,
- val owner: String,
- val players: List<PlayerDTO>,
- val state: State
-)
-
-fun Lobby.toDTO(currentUser: String): LobbyDTO {
- val players = getPlayers().map { it.toDTO(currentUser) }
- return LobbyDTO(id, name, owner.username, players, state)
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/api/PlayerDTO.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/api/PlayerDTO.kt
deleted file mode 100644
index 54c69122..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/api/PlayerDTO.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.luxons.sevenwonders.api
-
-import org.luxons.sevenwonders.lobby.Player
-
-data class PlayerDTO(
- val username: String,
- val displayName: String,
- val index: Int,
- val isGameOwner: Boolean,
- val isUser: Boolean
-)
-
-fun Player.toDTO(currentUser: String) =
- PlayerDTO(username, displayName, index, isGameOwner, username === currentUser)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/config/AnonymousUsersHandshakeHandler.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/config/AnonymousUsersHandshakeHandler.kt
deleted file mode 100644
index db707d1b..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/config/AnonymousUsersHandshakeHandler.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.luxons.sevenwonders.config
-
-import org.springframework.http.server.ServerHttpRequest
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
-import org.springframework.web.socket.WebSocketHandler
-import org.springframework.web.socket.server.support.DefaultHandshakeHandler
-import java.security.Principal
-
-/**
- * Generates [Principal] objects for anonymous users in the form "playerX", where X is an auto-incremented number.
- */
-internal class AnonymousUsersHandshakeHandler : DefaultHandshakeHandler() {
-
- private var playerId = 0
-
- override fun determineUser(
- request: ServerHttpRequest,
- wsHandler: WebSocketHandler,
- attributes: Map<String, Any>
- ): Principal? {
- var p = super.determineUser(request, wsHandler, attributes)
- if (p == null) {
- p = UsernamePasswordAuthenticationToken("player" + playerId++, null)
- }
- return p
- }
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/config/TopicSubscriptionInterceptor.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/config/TopicSubscriptionInterceptor.kt
deleted file mode 100644
index f4c55c2c..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/config/TopicSubscriptionInterceptor.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.luxons.sevenwonders.config
-
-import org.luxons.sevenwonders.validation.DestinationAccessValidator
-import org.slf4j.LoggerFactory
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.messaging.Message
-import org.springframework.messaging.MessageChannel
-import org.springframework.messaging.simp.stomp.StompCommand
-import org.springframework.messaging.simp.stomp.StompHeaderAccessor
-import org.springframework.messaging.support.ChannelInterceptor
-import org.springframework.stereotype.Component
-
-@Component
-class TopicSubscriptionInterceptor @Autowired constructor(
- private val destinationAccessValidator: DestinationAccessValidator
-) : ChannelInterceptor {
-
- override fun preSend(message: Message<*>, channel: MessageChannel): Message<*>? {
- val headerAccessor = StompHeaderAccessor.wrap(message)
- if (StompCommand.SUBSCRIBE == headerAccessor.command) {
- val username = headerAccessor.user!!.name
- val destination = headerAccessor.destination!!
- if (!destinationAccessValidator.hasAccess(username, destination)) {
- sendForbiddenSubscriptionError(username, destination)
- return null
- }
- }
- return message
- }
-
- private fun sendForbiddenSubscriptionError(username: String, destination: String?) {
- logger.error(String.format("Player '%s' is not allowed to access %s", username, destination))
- }
-
- companion object {
- private val logger = LoggerFactory.getLogger(TopicSubscriptionInterceptor::class.java)
- }
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSecurityConfig.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSecurityConfig.kt
deleted file mode 100644
index 06b2bc90..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSecurityConfig.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.luxons.sevenwonders.config
-
-import org.springframework.context.annotation.Configuration
-import org.springframework.security.config.annotation.web.builders.HttpSecurity
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
-
-@Configuration
-class WebSecurityConfig : WebSecurityConfigurerAdapter() {
-
- // this disables default authentication settings
- override fun configure(httpSecurity: HttpSecurity) = Unit
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt
deleted file mode 100644
index 743e3d1a..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.luxons.sevenwonders.config
-
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.context.annotation.Bean
-import org.springframework.context.annotation.Configuration
-import org.springframework.messaging.simp.config.ChannelRegistration
-import org.springframework.messaging.simp.config.MessageBrokerRegistry
-import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
-import org.springframework.web.socket.config.annotation.StompEndpointRegistry
-import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
-import org.springframework.web.socket.server.support.DefaultHandshakeHandler
-
-const val SEVEN_WONDERS_WS_ENDPOINT = "/seven-wonders-websocket"
-
-@Configuration
-@EnableWebSocketMessageBroker
-class WebSocketConfig @Autowired constructor(private val topicSubscriptionInterceptor: TopicSubscriptionInterceptor) :
- WebSocketMessageBrokerConfigurer {
-
- override fun configureMessageBroker(config: MessageBrokerRegistry) {
- // prefixes for all subscriptions
- config.enableSimpleBroker("/queue", "/topic")
- config.setUserDestinationPrefix("/user")
-
- // /app for normal calls, /topic for subscription events
- config.setApplicationDestinationPrefixes("/app", "/topic")
- }
-
- override fun registerStompEndpoints(registry: StompEndpointRegistry) {
- registry.addEndpoint(SEVEN_WONDERS_WS_ENDPOINT)
- .setHandshakeHandler(handshakeHandler())
- .setAllowedOrigins("http://localhost:3000") // to allow frontend server proxy requests in dev mode
- .withSockJS()
- }
-
- @Bean
- fun handshakeHandler(): DefaultHandshakeHandler {
- return AnonymousUsersHandshakeHandler()
- }
-
- override fun configureClientInboundChannel(registration: ChannelRegistration) {
- registration.interceptors(topicSubscriptionInterceptor)
- }
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameBrowserController.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameBrowserController.kt
deleted file mode 100644
index f856365f..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameBrowserController.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import org.hildan.livedoc.core.annotations.Api
-import org.luxons.sevenwonders.actions.CreateGameAction
-import org.luxons.sevenwonders.actions.JoinGameAction
-import org.luxons.sevenwonders.api.LobbyDTO
-import org.luxons.sevenwonders.api.toDTO
-import org.luxons.sevenwonders.errors.ApiMisuseException
-import org.luxons.sevenwonders.lobby.Lobby
-import org.luxons.sevenwonders.repositories.LobbyRepository
-import org.luxons.sevenwonders.repositories.PlayerRepository
-import org.slf4j.LoggerFactory
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.messaging.handler.annotation.MessageMapping
-import org.springframework.messaging.simp.SimpMessagingTemplate
-import org.springframework.messaging.simp.annotation.SendToUser
-import org.springframework.messaging.simp.annotation.SubscribeMapping
-import org.springframework.stereotype.Controller
-import org.springframework.validation.annotation.Validated
-import java.security.Principal
-
-/**
- * This is the place where the player looks for a game.
- */
-@Api(name = "GameBrowser")
-@Controller
-class GameBrowserController @Autowired constructor(
- private val lobbyController: LobbyController,
- private val lobbyRepository: LobbyRepository,
- private val playerRepository: PlayerRepository,
- private val template: SimpMessagingTemplate
-) {
-
- /**
- * Gets the created or updated games. The list of existing games is received on this topic at once upon
- * subscription, and then each time the list changes.
- *
- * @param principal the connected user's information
- *
- * @return the current list of [Lobby]s
- */
- @SubscribeMapping("/games") // prefix /topic not shown
- fun listGames(principal: Principal): Collection<LobbyDTO> {
- logger.info("Player '{}' subscribed to /topic/games", principal.name)
- return lobbyRepository.list().map { it.toDTO(principal.name) }
- }
-
- /**
- * Creates a new [Lobby].
- *
- * @param action the action to create the game
- * @param principal the connected user's information
- *
- * @return the newly created [Lobby]
- */
- @MessageMapping("/lobby/create")
- @SendToUser("/queue/lobby/joined")
- fun createGame(@Validated action: CreateGameAction, principal: Principal): LobbyDTO {
- checkThatUserIsNotInAGame(principal, "cannot create another game")
-
- val gameOwner = playerRepository.find(principal.name)
- val lobby = lobbyRepository.create(action.gameName, gameOwner)
-
- logger.info(
- "Game '{}' ({}) created by {} ({})", lobby.name, lobby.id, gameOwner.displayName, gameOwner.username
- )
-
- // notify everyone that a new game exists
- val lobbyDto = lobby.toDTO(principal.name)
- template.convertAndSend("/topic/games", listOf(lobbyDto))
- return lobbyDto
- }
-
- /**
- * Joins an existing [Lobby].
- *
- * @param action the action to join the game
- * @param principal the connected user's information
- *
- * @return the [Lobby] that has just been joined
- */
- @MessageMapping("/lobby/join")
- @SendToUser("/queue/lobby/joined")
- fun joinGame(@Validated action: JoinGameAction, principal: Principal): LobbyDTO {
- checkThatUserIsNotInAGame(principal, "cannot join another game")
-
- val lobby = lobbyRepository.find(action.gameId)
- val newPlayer = playerRepository.find(principal.name)
- lobby.addPlayer(newPlayer)
-
- logger.info(
- "Player '{}' ({}) joined game {}", newPlayer.displayName, newPlayer.username, lobby.name
- )
- val lobbyDTO = lobby.toDTO(principal.name)
- lobbyController.sendLobbyUpdateToPlayers(lobbyDTO)
- return lobbyDTO
- }
-
- private fun checkThatUserIsNotInAGame(principal: Principal, impossibleActionDescription: String) {
- val player = playerRepository.find(principal.name)
- if (player.isInLobby || player.isInGame) {
- throw UserAlreadyInGameException(player.lobby.name, impossibleActionDescription)
- }
- }
-
- internal class UserAlreadyInGameException(gameName: String, impossibleActionDescription: String) :
- ApiMisuseException("Client already in game '$gameName', $impossibleActionDescription")
-
- companion object {
- private val logger = LoggerFactory.getLogger(GameBrowserController::class.java)
- }
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameController.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameController.kt
deleted file mode 100644
index b37c9c7c..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/GameController.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import org.hildan.livedoc.core.annotations.Api
-import org.luxons.sevenwonders.actions.PrepareMoveAction
-import org.luxons.sevenwonders.api.PlayerDTO
-import org.luxons.sevenwonders.api.toDTO
-import org.luxons.sevenwonders.game.Game
-import org.luxons.sevenwonders.game.api.Table
-import org.luxons.sevenwonders.game.cards.CardBack
-import org.luxons.sevenwonders.lobby.Player
-import org.luxons.sevenwonders.repositories.PlayerRepository
-import org.slf4j.LoggerFactory
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.messaging.handler.annotation.MessageMapping
-import org.springframework.messaging.simp.SimpMessagingTemplate
-import org.springframework.stereotype.Controller
-import java.security.Principal
-
-/**
- * This API is for in-game events management.
- */
-@Api(name = "Game")
-@Controller
-class GameController @Autowired constructor(
- private val template: SimpMessagingTemplate,
- private val playerRepository: PlayerRepository
-) {
- private val Principal.player
- get() = playerRepository.find(name)
-
- /**
- * Notifies the game that the player is ready to receive his hand.
- *
- * @param principal
- * the connected user's information
- */
- @MessageMapping("/game/sayReady")
- fun ready(principal: Principal) {
- val player = principal.player
- player.isReady = true
- val game = player.game
- logger.info("Game {}: player {} is ready for the next turn", game.id, player)
-
- val lobby = player.lobby
- val players = lobby.getPlayers()
-
- sendPlayerReady(game.id, player)
-
- val allReady = players.all { it.isReady }
- if (allReady) {
- logger.info("Game {}: all players ready, sending turn info", game.id)
- players.forEach { it.isReady = false }
- sendTurnInfo(players, game)
- }
- }
-
- private fun sendTurnInfo(players: List<Player>, game: Game) {
- for (turnInfo in game.getCurrentTurnInfo()) {
- val player = players[turnInfo.playerIndex]
- template.convertAndSendToUser(player.username, "/queue/game/turn", turnInfo)
- }
- }
-
- private fun sendPlayerReady(gameId: Long, player: Player) =
- template.convertAndSend("/topic/game/$gameId/playerReady", "\"${player.username}\"")
-
- /**
- * Prepares the player's next move. When all players have prepared their moves, all moves are executed.
- *
- * @param action
- * the action to prepare the move
- * @param principal
- * the connected user's information
- */
- @MessageMapping("/game/prepareMove")
- fun prepareMove(action: PrepareMoveAction, principal: Principal) {
- val player = principal.player
- val game = player.game
- val preparedCardBack = game.prepareMove(player.index, action.move)
- val preparedCard = PreparedCard(player.toDTO(principal.name), preparedCardBack)
- logger.info("Game {}: player {} prepared move {}", game.id, principal.name, action.move)
- sendPreparedCard(game.id, preparedCard)
-
- if (game.allPlayersPreparedTheirMove()) {
- logger.info("Game {}: all players have prepared their move, executing turn...", game.id)
- val table = game.playTurn()
- sendPlayedMoves(game.id, table)
- }
- }
-
- private fun sendPlayedMoves(gameId: Long, table: Table) =
- template.convertAndSend("/topic/game/$gameId/tableUpdates", table)
-
- private fun sendPreparedCard(gameId: Long, preparedCard: PreparedCard) =
- template.convertAndSend("/topic/game/$gameId/prepared", preparedCard)
-
- companion object {
- private val logger = LoggerFactory.getLogger(GameController::class.java)
- }
-}
-
-class PreparedCard(val player: PlayerDTO, val cardBack: CardBack)
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/HomeController.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/HomeController.kt
deleted file mode 100644
index bd672000..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/HomeController.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import org.hildan.livedoc.core.annotations.Api
-import org.luxons.sevenwonders.actions.ChooseNameAction
-import org.luxons.sevenwonders.api.PlayerDTO
-import org.luxons.sevenwonders.api.toDTO
-import org.luxons.sevenwonders.repositories.PlayerRepository
-import org.slf4j.LoggerFactory
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.messaging.handler.annotation.MessageMapping
-import org.springframework.messaging.simp.annotation.SendToUser
-import org.springframework.stereotype.Controller
-import org.springframework.validation.annotation.Validated
-import java.security.Principal
-
-/**
- * Handles actions in the homepage of the game.
- */
-@Api(name = "Home")
-@Controller
-class HomeController @Autowired constructor(
- private val playerRepository: PlayerRepository
-) {
-
- /**
- * Creates/updates the player's name (for the user's session).
- *
- * @param action the action to choose the name of the player
- * @param principal the connected user's information
- *
- * @return the created [PlayerDTO] object
- */
- @MessageMapping("/chooseName")
- @SendToUser("/queue/nameChoice")
- fun chooseName(@Validated action: ChooseNameAction, principal: Principal): PlayerDTO {
- val username = principal.name
- val player = playerRepository.createOrUpdate(username, action.playerName)
-
- logger.info("Player '{}' chose the name '{}'", username, player.displayName)
- return player.toDTO(username)
- }
-
- companion object {
- private val logger = LoggerFactory.getLogger(HomeController::class.java)
- }
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/LobbyController.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/LobbyController.kt
deleted file mode 100644
index 4e4120a9..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/controllers/LobbyController.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import org.hildan.livedoc.core.annotations.Api
-import org.luxons.sevenwonders.actions.ReorderPlayersAction
-import org.luxons.sevenwonders.actions.UpdateSettingsAction
-import org.luxons.sevenwonders.api.LobbyDTO
-import org.luxons.sevenwonders.api.toDTO
-import org.luxons.sevenwonders.lobby.Player
-import org.luxons.sevenwonders.repositories.LobbyRepository
-import org.luxons.sevenwonders.repositories.PlayerRepository
-import org.slf4j.LoggerFactory
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.messaging.handler.annotation.MessageMapping
-import org.springframework.messaging.simp.SimpMessagingTemplate
-import org.springframework.stereotype.Controller
-import org.springframework.validation.annotation.Validated
-import java.security.Principal
-
-/**
- * Handles actions in the game's lobby. The lobby is the place where players gather before a game.
- */
-@Api(name = "Lobby")
-@Controller
-class LobbyController @Autowired constructor(
- private val lobbyRepository: LobbyRepository,
- private val playerRepository: PlayerRepository,
- private val template: SimpMessagingTemplate
-) {
- private val Principal.player: Player
- get() = playerRepository.find(name)
-
- /**
- * Leaves the current lobby.
- *
- * @param principal
- * the connected user's information
- */
- @MessageMapping("/lobby/leave")
- fun leave(principal: Principal) {
- val lobby = principal.player.lobby
- val player = lobby.removePlayer(principal.name)
- if (lobby.getPlayers().isEmpty()) {
- lobbyRepository.remove(lobby.id)
- }
-
- logger.info("Player {} left game '{}'", player, lobby.name)
- sendLobbyUpdateToPlayers(lobby.toDTO(principal.name))
- }
-
- /**
- * Reorders the players in the current lobby. This can only be done by the lobby's owner.
- *
- * @param action
- * the action to reorder the players
- * @param principal
- * the connected user's information
- */
- @MessageMapping("/lobby/reorderPlayers")
- fun reorderPlayers(@Validated action: ReorderPlayersAction, principal: Principal) {
- val lobby = principal.player.ownedLobby
- lobby.reorderPlayers(action.orderedPlayers)
-
- logger.info("Players in game '{}' reordered to {}", lobby.name, action.orderedPlayers)
- sendLobbyUpdateToPlayers(lobby.toDTO(principal.name))
- }
-
- /**
- * Updates the game settings. This can only be done by the lobby's owner.
- *
- * @param action
- * the action to update the settings
- * @param principal
- * the connected user's information
- */
- @MessageMapping("/lobby/updateSettings")
- fun updateSettings(@Validated action: UpdateSettingsAction, principal: Principal) {
- val lobby = principal.player.ownedLobby
- lobby.settings = action.settings
-
- logger.info("Updated settings of game '{}'", lobby.name)
- sendLobbyUpdateToPlayers(lobby.toDTO(principal.name))
- }
-
- internal fun sendLobbyUpdateToPlayers(lobby: LobbyDTO) {
- template.convertAndSend("/topic/lobby/" + lobby.id + "/updated", lobby)
- template.convertAndSend("/topic/games", listOf(lobby))
- }
-
- /**
- * Starts the game.
- *
- * @param principal
- * the connected user's information
- */
- @MessageMapping("/lobby/startGame")
- fun startGame(principal: Principal) {
- val lobby = principal.player.ownedLobby
- val game = lobby.startGame()
-
- logger.info("Game {} successfully started", game.id)
- template.convertAndSend("/topic/lobby/" + lobby.id + "/started", "")
- }
-
- companion object {
- private val logger = LoggerFactory.getLogger(LobbyController::class.java)
- }
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/doc/Documentation.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/doc/Documentation.kt
deleted file mode 100644
index 3b04356a..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/doc/Documentation.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.luxons.sevenwonders.doc
-
-object Documentation {
-
- const val GROUP_ACTIONS = "Actions"
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/errors/ErrorDTO.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/errors/ErrorDTO.kt
deleted file mode 100644
index c3eae0b5..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/errors/ErrorDTO.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.luxons.sevenwonders.errors
-
-import org.springframework.validation.FieldError
-import org.springframework.validation.ObjectError
-
-enum class ErrorType {
- VALIDATION, CLIENT, SERVER
-}
-
-data class ErrorDTO(
- val code: String,
- val message: String,
- val type: ErrorType,
- val details: List<ValidationErrorDTO> = emptyList()
-)
-
-data class ValidationErrorDTO(
- val path: String,
- val message: String,
- val rejectedValue: Any? = null
-)
-
-fun ObjectError.toDTO() = (this as? FieldError)?.fieldError() ?: objectError()
-
-fun FieldError.fieldError(): ValidationErrorDTO =
- ValidationErrorDTO("$objectName.$field", "Invalid value for field '$field': $defaultMessage", rejectedValue)
-
-fun ObjectError.objectError(): ValidationErrorDTO =
- ValidationErrorDTO(objectName, "Invalid value for object '$objectName': $defaultMessage")
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/errors/ExceptionHandler.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/errors/ExceptionHandler.kt
deleted file mode 100644
index 76d01f5f..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/errors/ExceptionHandler.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.luxons.sevenwonders.errors
-
-import org.slf4j.LoggerFactory
-import org.springframework.messaging.converter.MessageConversionException
-import org.springframework.messaging.handler.annotation.MessageExceptionHandler
-import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException
-import org.springframework.messaging.simp.annotation.SendToUser
-import org.springframework.web.bind.annotation.ControllerAdvice
-
-open class ApiMisuseException(message: String) : RuntimeException(message)
-
-@ControllerAdvice
-@SendToUser("/queue/errors")
-class ExceptionHandler {
-
- @MessageExceptionHandler
- fun handleValidationError(exception: MethodArgumentNotValidException): ErrorDTO {
- logger.error("Invalid input", exception)
- val validationErrors = exception.bindingResult?.allErrors?.map { it.toDTO() } ?: emptyList()
- return ErrorDTO("INVALID_DATA", "Invalid input data", ErrorType.VALIDATION, validationErrors)
- }
-
- @MessageExceptionHandler
- fun handleConversionError(exception: MessageConversionException): ErrorDTO {
- logger.error("Error interpreting the message", exception)
- return ErrorDTO("INVALID_MESSAGE_FORMAT", "Invalid input format", ErrorType.VALIDATION)
- }
-
- @MessageExceptionHandler
- fun handleApiError(exception: ApiMisuseException): ErrorDTO {
- logger.error("Invalid API input", exception)
- return ErrorDTO(exception.javaClass.simpleName, exception.message!!, ErrorType.CLIENT)
- }
-
- @MessageExceptionHandler
- fun handleUnexpectedInternalError(exception: Throwable): ErrorDTO {
- logger.error("Uncaught exception thrown during message handling", exception)
- return ErrorDTO(exception.javaClass.simpleName, exception.localizedMessage ?: "", ErrorType.SERVER)
- }
-
- companion object {
- private val logger = LoggerFactory.getLogger(ExceptionHandler::class.java)
- }
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Lobby.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Lobby.kt
deleted file mode 100644
index 08249193..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Lobby.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-package org.luxons.sevenwonders.lobby
-
-import org.luxons.sevenwonders.game.Game
-import org.luxons.sevenwonders.game.api.CustomizableSettings
-import org.luxons.sevenwonders.game.data.GameDefinition
-
-enum class State {
- LOBBY, PLAYING
-}
-
-class Lobby(
- val id: Long,
- val name: String,
- var owner: Player,
- private val gameDefinition: GameDefinition
-) {
- private val players: MutableList<Player> = ArrayList(gameDefinition.maxPlayers)
-
- var settings: CustomizableSettings = CustomizableSettings()
-
- var state = State.LOBBY
- private set
-
- init {
- addPlayer(owner)
- }
-
- fun getPlayers(): List<Player> = players
-
- @Synchronized
- fun addPlayer(player: Player) {
- if (hasStarted()) {
- throw GameAlreadyStartedException(name)
- }
- if (maxPlayersReached()) {
- throw PlayerOverflowException(gameDefinition.maxPlayers)
- }
- if (playerNameAlreadyUsed(player.displayName)) {
- throw PlayerNameAlreadyUsedException(player.displayName, name)
- }
- player.join(this)
- players.add(player)
- }
-
- private fun hasStarted(): Boolean = state != State.LOBBY
-
- private fun maxPlayersReached(): Boolean = players.size >= gameDefinition.maxPlayers
-
- private fun playerNameAlreadyUsed(name: String?): Boolean = players.any { it.displayName == name }
-
- @Synchronized
- fun startGame(): Game {
- if (!hasEnoughPlayers()) {
- throw PlayerUnderflowException(gameDefinition.minPlayers)
- }
- state = State.PLAYING
- val game = gameDefinition.initGame(id, settings, players.size)
- players.forEachIndexed { index, player -> player.join(game, index) }
- return game
- }
-
- private fun hasEnoughPlayers(): Boolean = players.size >= gameDefinition.minPlayers
-
- @Synchronized
- fun reorderPlayers(orderedUsernames: List<String>) {
- val usernames = players.map { it.username }
- if (orderedUsernames.toSet() != usernames.toSet()) {
- throw PlayerListMismatchException(orderedUsernames)
- }
- players.sortBy { orderedUsernames.indexOf(it.username) }
- }
-
- private fun find(username: String): Player =
- players.firstOrNull { it.username == username } ?: throw UnknownPlayerException(username)
-
- @Synchronized
- fun isOwner(username: String?): Boolean = owner.username == username
-
- @Synchronized
- fun containsUser(username: String): Boolean = players.any { it.username == username }
-
- @Synchronized
- fun removePlayer(username: String): Player {
- val player = find(username)
- players.remove(player)
- player.leave()
-
- if (player == owner && !players.isEmpty()) {
- owner = players[0]
- }
- return player
- }
-
- internal class GameAlreadyStartedException(name: String) :
- IllegalStateException("Game '$name' has already started")
-
- internal class PlayerOverflowException(max: Int) :
- IllegalStateException("Maximum $max players allowed")
-
- internal class PlayerUnderflowException(min: Int) :
- IllegalStateException("Minimum $min players required to start a game")
-
- internal class PlayerNameAlreadyUsedException(displayName: String, gameName: String) :
- IllegalArgumentException("Name '$displayName' is already used by a player in game '$gameName'")
-
- internal class UnknownPlayerException(username: String) :
- IllegalArgumentException("Unknown player '$username'")
-
- internal class PlayerListMismatchException(usernames: List<String>) :
- IllegalArgumentException("Newly ordered usernames $usernames don't match the current player list")
-}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Player.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Player.kt
deleted file mode 100644
index d6e9b344..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/lobby/Player.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.luxons.sevenwonders.lobby
-
-import org.luxons.sevenwonders.errors.ApiMisuseException
-import org.luxons.sevenwonders.game.Game
-
-class Player(
- val username: String,
- var displayName: String
-) {
- var index: Int = -1
-
- var isReady: Boolean = false
-
- val isGameOwner: Boolean
- get() = _lobby?.isOwner(username) ?: false
-
- val isInLobby: Boolean
- get() = _lobby != null
-
- val isInGame: Boolean
- get() = _game != null
-
- private var _lobby: Lobby? = null
-
- val lobby: Lobby
- get() = _lobby ?: throw PlayerNotInLobbyException(username)
-
- val ownedLobby: Lobby
- get() = if (isGameOwner) lobby else throw PlayerIsNotOwnerException(username)
-
- private var _game: Game? = null
-
- val game: Game
- get() = _game ?: throw PlayerNotInGameException(username)
-
- fun join(lobby: Lobby) {
- _lobby = lobby
- }
-
- fun join(game: Game, index: Int) {
- _game = game
- this.index = index
- }
-
- fun leave() {
- _lobby = null
- _game = null
- index = -1
- }
-
- override fun toString(): String = "'$displayName' ($username)"
-}
-
-internal class PlayerNotInLobbyException(username: String) :
- ApiMisuseException("User $username is not in a lobby, create or join a game first")
-
-internal class PlayerIsNotOwnerException(username: String) :
- ApiMisuseException("User $username does not own the lobby he's in")
-
-internal class PlayerNotInGameException(username: String) :
- ApiMisuseException("User $username is not in a game, start a game first")
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/repositories/LobbyRepository.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/repositories/LobbyRepository.kt
deleted file mode 100644
index 768aa659..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/repositories/LobbyRepository.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.luxons.sevenwonders.repositories
-
-import org.luxons.sevenwonders.game.data.GameDefinition
-import org.luxons.sevenwonders.lobby.Lobby
-import org.luxons.sevenwonders.lobby.Player
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Repository
-import java.util.HashMap
-
-@Repository
-class LobbyRepository @Autowired constructor() {
-
- private val lobbies = HashMap<Long, Lobby>()
-
- private var lastGameId: Long = 0
-
- fun list(): Collection<Lobby> = lobbies.values
-
- fun create(gameName: String, owner: Player): Lobby {
- val id = lastGameId++
- val lobby = Lobby(id, gameName, owner, GameDefinition.load())
- lobbies[id] = lobby
- return lobby
- }
-
- fun find(lobbyId: Long): Lobby = lobbies[lobbyId] ?: throw LobbyNotFoundException(lobbyId)
-
- fun remove(lobbyId: Long): Lobby = lobbies.remove(lobbyId) ?: throw LobbyNotFoundException(lobbyId)
-}
-
-internal class LobbyNotFoundException(id: Long) : RuntimeException("Lobby not found for id '$id'")
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/repositories/PlayerRepository.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/repositories/PlayerRepository.kt
deleted file mode 100644
index 4d552eaa..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/repositories/PlayerRepository.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.luxons.sevenwonders.repositories
-
-import org.luxons.sevenwonders.errors.ApiMisuseException
-import org.luxons.sevenwonders.lobby.Player
-import org.springframework.stereotype.Repository
-import java.util.HashMap
-
-@Repository
-class PlayerRepository {
-
- private val players = HashMap<String, Player>()
-
- operator fun contains(username: String): Boolean = players.containsKey(username)
-
- fun createOrUpdate(username: String, displayName: String): Player {
- return if (players.containsKey(username)) {
- update(username, displayName)
- } else {
- create(username, displayName)
- }
- }
-
- private fun create(username: String, displayName: String): Player {
- val player = Player(username, displayName)
- players[username] = player
- return player
- }
-
- private fun update(username: String, displayName: String): Player {
- val player = find(username)
- player.displayName = displayName
- return player
- }
-
- fun find(username: String): Player = players[username] ?: throw PlayerNotFoundException(username)
-
- fun remove(username: String): Player = players.remove(username) ?: throw PlayerNotFoundException(username)
-}
-
-internal class PlayerNotFoundException(username: String) :
- ApiMisuseException("Player '$username' doesn't exist")
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidator.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidator.kt
deleted file mode 100644
index 5f704357..00000000
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidator.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.luxons.sevenwonders.validation
-
-import org.luxons.sevenwonders.repositories.LobbyRepository
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.stereotype.Component
-import java.util.regex.Pattern
-
-@Component
-class DestinationAccessValidator @Autowired constructor(private val lobbyRepository: LobbyRepository) {
-
- fun hasAccess(username: String?, destination: String): Boolean {
- return when {
- username == null -> false // unnamed user cannot belong to anything
- hasForbiddenGameReference(username, destination) -> false
- hasForbiddenLobbyReference(username, destination) -> false
- else -> true
- }
- }
-
- private fun hasForbiddenGameReference(username: String, destination: String): Boolean {
- val gameMatcher = gameDestination.matcher(destination)
- if (!gameMatcher.matches()) {
- return false // no game reference is always OK
- }
- val gameId = gameMatcher.group("id").toLong()
- return !isUserInLobby(username, gameId)
- }
-
- private fun hasForbiddenLobbyReference(username: String, destination: String): Boolean {
- val lobbyMatcher = lobbyDestination.matcher(destination)
- if (!lobbyMatcher.matches()) {
- return false // no lobby reference is always OK
- }
- val lobbyId = lobbyMatcher.group("id").toLong()
- return !isUserInLobby(username, lobbyId)
- }
-
- private fun isUserInLobby(username: String, lobbyId: Long): Boolean =
- lobbyRepository.find(lobbyId).containsUser(username)
-
- companion object {
-
- private val lobbyDestination = Pattern.compile(".*?/lobby/(?<id>\\d+?)(/.*)?")
-
- private val gameDestination = Pattern.compile(".*?/game/(?<id>\\d+?)(/.*)?")
- }
-}
diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties
deleted file mode 100644
index aa2e5d12..00000000
--- a/backend/src/main/resources/application.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-livedoc.version=1.0
-livedoc.packages[0]=org.luxons.sevenwonders
diff --git a/backend/src/main/resources/static/images/tokens/coin1.png b/backend/src/main/resources/static/images/tokens/coin1.png
deleted file mode 100644
index dd57e5f0..00000000
--- a/backend/src/main/resources/static/images/tokens/coin1.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/coin3.png b/backend/src/main/resources/static/images/tokens/coin3.png
deleted file mode 100644
index 546d41b6..00000000
--- a/backend/src/main/resources/static/images/tokens/coin3.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/free.png b/backend/src/main/resources/static/images/tokens/free.png
deleted file mode 100644
index 1c8d0782..00000000
--- a/backend/src/main/resources/static/images/tokens/free.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/pyramid-stage0.png b/backend/src/main/resources/static/images/tokens/pyramid-stage0.png
deleted file mode 100644
index b6a3977f..00000000
--- a/backend/src/main/resources/static/images/tokens/pyramid-stage0.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/pyramid-stage1.png b/backend/src/main/resources/static/images/tokens/pyramid-stage1.png
deleted file mode 100644
index ead4a34e..00000000
--- a/backend/src/main/resources/static/images/tokens/pyramid-stage1.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/pyramid-stage2.png b/backend/src/main/resources/static/images/tokens/pyramid-stage2.png
deleted file mode 100644
index 7239a3a4..00000000
--- a/backend/src/main/resources/static/images/tokens/pyramid-stage2.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/pyramid-stage3.png b/backend/src/main/resources/static/images/tokens/pyramid-stage3.png
deleted file mode 100644
index cab9912b..00000000
--- a/backend/src/main/resources/static/images/tokens/pyramid-stage3.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/pyramid.png b/backend/src/main/resources/static/images/tokens/pyramid.png
deleted file mode 100644
index 074247da..00000000
--- a/backend/src/main/resources/static/images/tokens/pyramid.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/victory1.png b/backend/src/main/resources/static/images/tokens/victory1.png
deleted file mode 100644
index 6b9aff29..00000000
--- a/backend/src/main/resources/static/images/tokens/victory1.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/victory3.png b/backend/src/main/resources/static/images/tokens/victory3.png
deleted file mode 100644
index 474cb30c..00000000
--- a/backend/src/main/resources/static/images/tokens/victory3.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/victory5.png b/backend/src/main/resources/static/images/tokens/victory5.png
deleted file mode 100644
index ad042119..00000000
--- a/backend/src/main/resources/static/images/tokens/victory5.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/main/resources/static/images/tokens/victoryminus1.png b/backend/src/main/resources/static/images/tokens/victoryminus1.png
deleted file mode 100644
index 00a615c7..00000000
--- a/backend/src/main/resources/static/images/tokens/victoryminus1.png
+++ /dev/null
Binary files differ
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/SevenWondersTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/SevenWondersTest.kt
deleted file mode 100644
index 01de366a..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/SevenWondersTest.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.luxons.sevenwonders
-
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.luxons.sevenwonders.test.api.SevenWondersClient
-import org.luxons.sevenwonders.test.api.SevenWondersSession
-import org.springframework.boot.test.context.SpringBootTest
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
-import org.springframework.boot.web.server.LocalServerPort
-import org.springframework.test.context.junit4.SpringRunner
-import java.util.concurrent.TimeUnit
-import kotlin.test.assertEquals
-import kotlin.test.assertNotNull
-import kotlin.test.assertNull
-
-@RunWith(SpringRunner::class)
-@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-class SevenWondersTest {
-
- @LocalServerPort
- private val randomServerPort: Int = 0
-
- private lateinit var client: SevenWondersClient
-
- private lateinit var serverUrl: String
-
- @Before
- fun setUpClientAndUrl() {
- client = SevenWondersClient()
- serverUrl = "ws://localhost:$randomServerPort"
- }
-
- private fun disconnect(vararg sessions: SevenWondersSession) {
- for (session in sessions) {
- session.disconnect()
- }
- }
-
- @Test
- fun chooseName() {
- val session = client.connect(serverUrl)
- val playerName = "Test User"
- val player = session.chooseName(playerName)
- assertNotNull(player)
- assertEquals(playerName, player.displayName)
- session.disconnect()
- }
-
- private fun newPlayer(name: String): SevenWondersSession {
- val otherSession = client.connect(serverUrl)
- otherSession.chooseName(name)
- return otherSession
- }
-
- @Test
- fun lobbySubscription_ignoredForOutsiders() {
- val ownerSession = newPlayer("GameOwner")
- val session1 = newPlayer("Player1")
- val session2 = newPlayer("Player2")
- val gameName = "Test Game"
- val lobby = ownerSession.createGame(gameName)
- session1.joinGame(lobby.id)
- session2.joinGame(lobby.id)
-
- val outsiderSession = newPlayer("Outsider")
- val session = outsiderSession.jackstompSession
- val started = session.subscribeEmptyMsgs("/topic/lobby/" + lobby.id + "/started")
-
- ownerSession.startGame(lobby.id)
- val nothing = started.next(1, TimeUnit.SECONDS)
- assertNull(nothing)
- disconnect(ownerSession, session1, session2, outsiderSession)
- }
-
- @Test
- fun createGame_success() {
- val ownerSession = newPlayer("GameOwner")
-
- val gameName = "Test Game"
- val lobby = ownerSession.createGame(gameName)
- assertNotNull(lobby)
- assertEquals(gameName, lobby.name)
-
- disconnect(ownerSession)
- }
-
- @Test
- fun createGame_seenByConnectedPlayers() {
- val otherSession = newPlayer("OtherPlayer")
- val games = otherSession.watchGames()
-
- var receivedLobbies = games.next()
- assertNotNull(receivedLobbies)
- assertEquals(0, receivedLobbies.size)
-
- val ownerSession = newPlayer("GameOwner")
- val gameName = "Test Game"
- val createdLobby = ownerSession.createGame(gameName)
-
- receivedLobbies = games.next()
- assertNotNull(receivedLobbies)
- assertEquals(1, receivedLobbies.size)
- val receivedLobby = receivedLobbies[0]
- assertEquals(createdLobby.id, receivedLobby.id)
- assertEquals(createdLobby.name, receivedLobby.name)
-
- disconnect(ownerSession, otherSession)
- }
-
- @Test
- fun startGame_3players() {
- val session1 = newPlayer("Player1")
- val session2 = newPlayer("Player2")
-
- val lobby = session1.createGame("Test Game")
- session2.joinGame(lobby.id)
-
- val session3 = newPlayer("Player3")
- session3.joinGame(lobby.id)
-
- session1.startGame(lobby.id)
-
- val turns1 = session1.watchTurns()
- val turns2 = session2.watchTurns()
- val turns3 = session3.watchTurns()
- session1.sayReady()
- session2.sayReady()
- session3.sayReady()
- val turn1 = turns1.next()
- val turn2 = turns2.next()
- val turn3 = turns3.next()
- assertNotNull(turn1)
- assertNotNull(turn2)
- assertNotNull(turn3)
-
- disconnect(session1, session2, session3)
- }
-
- @After
- fun tearDown() {
- client.stop()
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/GameBrowserControllerTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/GameBrowserControllerTest.kt
deleted file mode 100644
index 343b7f34..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/GameBrowserControllerTest.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import org.junit.Before
-import org.junit.Test
-import org.luxons.sevenwonders.actions.CreateGameAction
-import org.luxons.sevenwonders.actions.JoinGameAction
-import org.luxons.sevenwonders.api.toDTO
-import org.luxons.sevenwonders.controllers.GameBrowserController.UserAlreadyInGameException
-import org.luxons.sevenwonders.repositories.LobbyRepository
-import org.luxons.sevenwonders.repositories.PlayerNotFoundException
-import org.luxons.sevenwonders.repositories.PlayerRepository
-import org.luxons.sevenwonders.test.mockSimpMessagingTemplate
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
-
-class GameBrowserControllerTest {
-
- private lateinit var playerRepository: PlayerRepository
-
- private lateinit var gameBrowserController: GameBrowserController
-
- @Before
- fun setUp() {
- playerRepository = PlayerRepository()
- val lobbyRepository = LobbyRepository()
- val template = mockSimpMessagingTemplate()
- val lobbyController = LobbyController(lobbyRepository, playerRepository, template)
- gameBrowserController = GameBrowserController(lobbyController, lobbyRepository, playerRepository, template)
- }
-
- @Test
- fun listGames_initiallyEmpty() {
- val principal = TestPrincipal("testuser")
- val games = gameBrowserController.listGames(principal)
- assertTrue(games.isEmpty())
- }
-
- @Test
- fun createGame_success() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val principal = TestPrincipal("testuser")
-
- val action = CreateGameAction("Test Game")
-
- val createdLobby = gameBrowserController.createGame(action, principal)
-
- assertEquals("Test Game", createdLobby.name)
-
- val games = gameBrowserController.listGames(principal)
- assertFalse(games.isEmpty())
- val lobby = games.iterator().next()
- assertEquals(lobby, createdLobby)
- assertEquals(player.toDTO(principal.name), lobby.players[0])
- }
-
- @Test
- fun createGame_failsForUnknownPlayer() {
- val principal = TestPrincipal("unknown")
- val action = CreateGameAction("Test Game")
-
- assertFailsWith<PlayerNotFoundException> {
- gameBrowserController.createGame(action, principal)
- }
- }
-
- @Test
- fun createGame_failsWhenAlreadyInGame() {
- playerRepository.createOrUpdate("testuser", "Test User")
- val principal = TestPrincipal("testuser")
-
- val createGameAction1 = CreateGameAction("Test Game 1")
-
- // auto-enters the game
- gameBrowserController.createGame(createGameAction1, principal)
-
- val createGameAction2 = CreateGameAction("Test Game 2")
-
- // already in a game
- assertFailsWith<UserAlreadyInGameException> {
- gameBrowserController.createGame(createGameAction2, principal)
- }
- }
-
- @Test
- fun joinGame_success() {
- val owner = playerRepository.createOrUpdate("testowner", "Test User Owner")
- val ownerPrincipal = TestPrincipal("testowner")
- val createGameAction = CreateGameAction("Test Game")
-
- val createdLobby = gameBrowserController.createGame(createGameAction, ownerPrincipal)
- assertEquals(owner.toDTO(ownerPrincipal.name), createdLobby.players[0])
-
- val joiner = playerRepository.createOrUpdate("testjoiner", "Test User Joiner")
- val joinerPrincipal = TestPrincipal("testjoiner")
- val joinGameAction = JoinGameAction(createdLobby.id)
-
- val joinedLobby = gameBrowserController.joinGame(joinGameAction, joinerPrincipal)
-
- assertEquals(owner.toDTO(joinerPrincipal.name), joinedLobby.players[0])
- assertEquals(joiner.toDTO(joinerPrincipal.name), joinedLobby.players[1])
- }
-
- @Test
- fun joinGame_failsWhenAlreadyInGame() {
- playerRepository.createOrUpdate("testowner", "Test User Owner")
- val ownerPrincipal = TestPrincipal("testowner")
- val createGameAction = CreateGameAction("Test Game")
-
- val createdLobby = gameBrowserController.createGame(createGameAction, ownerPrincipal)
-
- playerRepository.createOrUpdate("testjoiner", "Test User Joiner")
- val joinerPrincipal = TestPrincipal("testjoiner")
- val joinGameAction = JoinGameAction(createdLobby.id)
-
- // joins the game
- gameBrowserController.joinGame(joinGameAction, joinerPrincipal)
- // should fail because already in a game
- assertFailsWith<UserAlreadyInGameException> {
- gameBrowserController.joinGame(joinGameAction, joinerPrincipal)
- }
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/HomeControllerTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/HomeControllerTest.kt
deleted file mode 100644
index 3374a025..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/HomeControllerTest.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import org.junit.Test
-import org.luxons.sevenwonders.actions.ChooseNameAction
-import org.luxons.sevenwonders.repositories.PlayerRepository
-import kotlin.test.assertEquals
-
-class HomeControllerTest {
-
- @Test
- fun chooseName() {
- val playerRepository = PlayerRepository()
- val homeController = HomeController(playerRepository)
-
- val action = ChooseNameAction("Test User")
- val principal = TestPrincipal("testuser")
-
- val player = homeController.chooseName(action, principal)
-
- assertEquals("testuser", player.username)
- assertEquals("Test User", player.displayName)
- assertEquals(false, player.isGameOwner)
- assertEquals(true, player.isUser)
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/LobbyControllerTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/LobbyControllerTest.kt
deleted file mode 100644
index a140e000..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/LobbyControllerTest.kt
+++ /dev/null
@@ -1,217 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import org.junit.Before
-import org.junit.Test
-import org.luxons.sevenwonders.actions.ReorderPlayersAction
-import org.luxons.sevenwonders.actions.UpdateSettingsAction
-import org.luxons.sevenwonders.game.api.CustomizableSettings
-import org.luxons.sevenwonders.game.api.WonderSidePickMethod.ALL_A
-import org.luxons.sevenwonders.lobby.Lobby
-import org.luxons.sevenwonders.lobby.Player
-import org.luxons.sevenwonders.lobby.PlayerIsNotOwnerException
-import org.luxons.sevenwonders.lobby.PlayerNotInLobbyException
-import org.luxons.sevenwonders.lobby.State
-import org.luxons.sevenwonders.repositories.LobbyRepository
-import org.luxons.sevenwonders.repositories.PlayerNotFoundException
-import org.luxons.sevenwonders.repositories.PlayerRepository
-import org.luxons.sevenwonders.test.mockSimpMessagingTemplate
-import java.util.HashMap
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertSame
-import kotlin.test.assertTrue
-
-class LobbyControllerTest {
-
- private lateinit var playerRepository: PlayerRepository
-
- private lateinit var lobbyRepository: LobbyRepository
-
- private lateinit var lobbyController: LobbyController
-
- @Before
- fun setUp() {
- val template = mockSimpMessagingTemplate()
- playerRepository = PlayerRepository()
- lobbyRepository = LobbyRepository()
- lobbyController = LobbyController(lobbyRepository, playerRepository, template)
- }
-
- @Test
- fun init_succeeds() {
- val owner = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", owner)
-
- assertTrue(lobby.getPlayers().contains(owner))
- assertSame(lobby, owner.lobby)
- assertEquals(owner, lobby.owner)
- assertTrue(owner.isInLobby)
- assertFalse(owner.isInGame)
- }
-
- @Test
- fun leave_failsWhenPlayerDoesNotExist() {
- val principal = TestPrincipal("I don't exist")
-
- assertFailsWith<PlayerNotFoundException> {
- lobbyController.leave(principal)
- }
- }
-
- @Test
- fun leave_failsWhenNotInLobby() {
- playerRepository.createOrUpdate("testuser", "Test User")
- val principal = TestPrincipal("testuser")
-
- assertFailsWith<PlayerNotInLobbyException> {
- lobbyController.leave(principal)
- }
- }
-
- @Test
- fun leave_succeedsWhenInALobby_asOwner() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
-
- val principal = TestPrincipal("testuser")
- lobbyController.leave(principal)
-
- assertFalse(lobbyRepository.list().contains(lobby))
- assertFalse(player.isInLobby)
- assertFalse(player.isInGame)
- }
-
- @Test
- fun leave_succeedsWhenInALobby_asPeasant() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
- val player2 = addPlayer(lobby, "testuser2")
-
- val principal = TestPrincipal("testuser2")
- lobbyController.leave(principal)
-
- assertFalse(lobby.getPlayers().contains(player2))
- assertFalse(player2.isInLobby)
- assertFalse(player2.isInGame)
- }
-
- @Test
- fun reorderPlayers_succeedsForOwner() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
-
- val player2 = addPlayer(lobby, "testuser2")
- val player3 = addPlayer(lobby, "testuser3")
- val player4 = addPlayer(lobby, "testuser4")
-
- val players = listOf(player, player2, player3, player4)
- assertEquals(players, lobby.getPlayers())
-
- val reorderedPlayers = listOf(player3, player, player2, player4)
- val playerNames = reorderedPlayers.map { it.username }
- val reorderPlayersAction = ReorderPlayersAction(playerNames)
-
- val principal = TestPrincipal("testuser")
- lobbyController.reorderPlayers(reorderPlayersAction, principal)
-
- assertEquals(reorderedPlayers, lobby.getPlayers())
- }
-
- @Test
- fun reorderPlayers_failsForPeasant() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
-
- val player2 = addPlayer(lobby, "testuser2")
- val player3 = addPlayer(lobby, "testuser3")
-
- val reorderedPlayers = listOf(player3, player, player2)
- val playerNames = reorderedPlayers.map { it.username }
- val reorderPlayersAction = ReorderPlayersAction(playerNames)
-
- val principal = TestPrincipal("testuser2")
-
- assertFailsWith<PlayerIsNotOwnerException> {
- lobbyController.reorderPlayers(reorderPlayersAction, principal)
- }
- }
-
- @Test
- fun updateSettings_succeedsForOwner() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
-
- addPlayer(lobby, "testuser2")
- addPlayer(lobby, "testuser3")
- addPlayer(lobby, "testuser4")
-
- assertEquals(CustomizableSettings(), lobby.settings)
-
- val newSettings = CustomizableSettings(12L, 5, ALL_A, 5, 5, 4, 10, 2, HashMap())
- val updateSettingsAction = UpdateSettingsAction(newSettings)
-
- val principal = TestPrincipal("testuser")
- lobbyController.updateSettings(updateSettingsAction, principal)
-
- assertEquals(newSettings, lobby.settings)
- }
-
- @Test
- fun updateSettings_failsForPeasant() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
-
- addPlayer(lobby, "testuser2")
- addPlayer(lobby, "testuser3")
-
- val updateSettingsAction = UpdateSettingsAction(CustomizableSettings())
-
- val principal = TestPrincipal("testuser2")
-
- assertFailsWith<PlayerIsNotOwnerException> {
- lobbyController.updateSettings(updateSettingsAction, principal)
- }
- }
-
- @Test
- fun startGame_succeedsForOwner() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
-
- addPlayer(lobby, "testuser2")
- addPlayer(lobby, "testuser3")
- addPlayer(lobby, "testuser4")
-
- val principal = TestPrincipal("testuser")
- lobbyController.startGame(principal)
-
- assertSame(State.PLAYING, lobby.state)
- }
-
- @Test
- fun startGame_failsForPeasant() {
- val player = playerRepository.createOrUpdate("testuser", "Test User")
- val lobby = lobbyRepository.create("Test Game", player)
-
- addPlayer(lobby, "testuser2")
- addPlayer(lobby, "testuser3")
-
- val principal = TestPrincipal("testuser2")
-
- assertFailsWith<PlayerIsNotOwnerException> {
- lobbyController.startGame(principal)
- }
- }
-
- private fun addPlayer(lobby: Lobby, username: String): Player {
- val player = playerRepository.createOrUpdate(username, username)
- lobby.addPlayer(player)
-
- assertTrue(lobby.getPlayers().contains(player))
- assertSame(lobby, player.lobby)
- assertTrue(player.isInLobby)
- assertFalse(player.isInGame)
- return player
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/TestPrincipal.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/TestPrincipal.kt
deleted file mode 100644
index 76b0f8fa..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/controllers/TestPrincipal.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.luxons.sevenwonders.controllers
-
-import java.security.Principal
-
-internal class TestPrincipal(private val name: String) : Principal {
-
- override fun getName(): String = name
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/lobby/LobbyTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/lobby/LobbyTest.kt
deleted file mode 100644
index 967a97e2..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/lobby/LobbyTest.kt
+++ /dev/null
@@ -1,266 +0,0 @@
-package org.luxons.sevenwonders.lobby
-
-import org.junit.Assume.assumeTrue
-import org.junit.Before
-import org.junit.BeforeClass
-import org.junit.Test
-import org.junit.experimental.theories.DataPoints
-import org.junit.experimental.theories.Theories
-import org.junit.experimental.theories.Theory
-import org.junit.runner.RunWith
-import org.luxons.sevenwonders.game.api.CustomizableSettings
-import org.luxons.sevenwonders.game.data.GameDefinition
-import org.luxons.sevenwonders.lobby.Lobby.GameAlreadyStartedException
-import org.luxons.sevenwonders.lobby.Lobby.PlayerListMismatchException
-import org.luxons.sevenwonders.lobby.Lobby.PlayerNameAlreadyUsedException
-import org.luxons.sevenwonders.lobby.Lobby.PlayerOverflowException
-import org.luxons.sevenwonders.lobby.Lobby.PlayerUnderflowException
-import org.luxons.sevenwonders.lobby.Lobby.UnknownPlayerException
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertNotNull
-import kotlin.test.assertSame
-import kotlin.test.assertTrue
-
-@RunWith(Theories::class)
-class LobbyTest {
-
- private lateinit var gameOwner: Player
-
- private lateinit var lobby: Lobby
-
- @Before
- fun setUp() {
- gameOwner = Player("gameowner", "Game owner")
- lobby = Lobby(0, "Test Game", gameOwner, gameDefinition)
- }
-
- @Test
- fun testId() {
- val lobby = Lobby(5, "Test Game", gameOwner, gameDefinition)
- assertEquals(5, lobby.id)
- }
-
- @Test
- fun testName() {
- val lobby = Lobby(5, "Test Game", gameOwner, gameDefinition)
- assertEquals("Test Game", lobby.name)
- }
-
- @Test
- fun testOwner() {
- val lobby = Lobby(5, "Test Game", gameOwner, gameDefinition)
- assertSame(gameOwner, lobby.getPlayers()[0])
- assertSame(lobby, gameOwner.lobby)
- }
-
- @Test
- fun isOwner_falseWhenNull() {
- assertFalse(lobby.isOwner(null))
- }
-
- @Test
- fun isOwner_falseWhenEmptyString() {
- assertFalse(lobby.isOwner(""))
- }
-
- @Test
- fun isOwner_falseWhenGarbageString() {
- assertFalse(lobby.isOwner("this is garbage"))
- }
-
- @Test
- fun isOwner_trueWhenOwnerUsername() {
- assertTrue(lobby.isOwner(gameOwner.username))
- }
-
- @Test
- fun isOwner_falseWhenOtherPlayerName() {
- val player = Player("testuser", "Test User")
- lobby.addPlayer(player)
- assertFalse(lobby.isOwner(player.username))
- }
-
- @Test
- fun addPlayer_success() {
- val player = Player("testuser", "Test User")
- lobby.addPlayer(player)
- assertTrue(lobby.containsUser("testuser"))
- assertSame(lobby, player.lobby)
- }
-
- @Test
- fun addPlayer_failsOnSameName() {
- val player = Player("testuser", "Test User")
- val player2 = Player("testuser2", "Test User")
- lobby.addPlayer(player)
- assertFailsWith<PlayerNameAlreadyUsedException> {
- lobby.addPlayer(player2)
- }
- }
-
- @Test
- fun addPlayer_playerOverflowWhenTooMany() {
- assertFailsWith<PlayerOverflowException> {
- // the owner + the max number gives an overflow
- addPlayers(gameDefinition.maxPlayers)
- }
- }
-
- @Test
- fun addPlayer_failWhenGameStarted() {
- // total with owner is the minimum
- addPlayers(gameDefinition.minPlayers - 1)
- lobby.startGame()
- assertFailsWith<GameAlreadyStartedException> {
- lobby.addPlayer(Player("soonerNextTime", "The Late Guy"))
- }
- }
-
- private fun addPlayers(nbPlayers: Int) {
- repeat(nbPlayers) {
- val player = Player("testuser$it", "Test User $it")
- lobby.addPlayer(player)
- }
- }
-
- @Test
- fun removePlayer_failsWhenNotPresent() {
- assertFailsWith<UnknownPlayerException> {
- lobby.removePlayer("anyname")
- }
- }
-
- @Test
- fun removePlayer_success() {
- val player = Player("testuser", "Test User")
- lobby.addPlayer(player)
- assertTrue(player.isInLobby)
- assertFalse(player.isInGame)
-
- lobby.removePlayer("testuser")
- assertFalse(lobby.containsUser("testuser"))
- assertFalse(player.isInLobby)
- assertFalse(player.isInGame)
- }
-
- @Test
- fun reorderPlayers_success() {
- val player1 = Player("testuser1", "Test User 1")
- val player2 = Player("testuser2", "Test User 2")
- val player3 = Player("testuser3", "Test User 3")
- lobby.addPlayer(player1)
- lobby.addPlayer(player2)
- lobby.addPlayer(player3)
-
- val reorderedUsernames = listOf("testuser3", "gameowner", "testuser1", "testuser2")
- lobby.reorderPlayers(reorderedUsernames)
-
- assertEquals(reorderedUsernames, lobby.getPlayers().map { it.username })
- }
-
- @Test
- fun reorderPlayers_failsOnUnknownPlayer() {
- val player1 = Player("testuser1", "Test User 1")
- val player2 = Player("testuser2", "Test User 2")
- lobby.addPlayer(player1)
- lobby.addPlayer(player2)
-
- assertFailsWith<PlayerListMismatchException> {
- lobby.reorderPlayers(listOf("unknown", "testuser2", "gameowner"))
- }
- }
-
- @Test
- fun reorderPlayers_failsOnExtraPlayer() {
- val player1 = Player("testuser1", "Test User 1")
- val player2 = Player("testuser2", "Test User 2")
- lobby.addPlayer(player1)
- lobby.addPlayer(player2)
-
- assertFailsWith<PlayerListMismatchException> {
- lobby.reorderPlayers(listOf("testuser2", "onemore", "testuser1", "gameowner"))
- }
- }
-
- @Test
- fun reorderPlayers_failsOnMissingPlayer() {
- val player1 = Player("testuser1", "Test User 1")
- val player2 = Player("testuser2", "Test User 2")
- lobby.addPlayer(player1)
- lobby.addPlayer(player2)
-
- assertFailsWith<PlayerListMismatchException> {
- lobby.reorderPlayers(listOf("testuser2", "gameowner"))
- }
- }
-
- @Theory
- fun startGame_failsBelowMinPlayers(nbPlayers: Int) {
- assumeTrue(nbPlayers < gameDefinition.minPlayers)
-
- // there is already the owner
- addPlayers(nbPlayers - 1)
-
- assertFailsWith<PlayerUnderflowException> {
- lobby.startGame()
- }
- }
-
- @Theory
- fun startGame_succeedsAboveMinPlayers(nbPlayers: Int) {
- assumeTrue(nbPlayers >= gameDefinition.minPlayers)
- assumeTrue(nbPlayers <= gameDefinition.maxPlayers)
- // there is already the owner
- addPlayers(nbPlayers - 1)
-
- assertEquals(nbPlayers, lobby.getPlayers().size)
- lobby.getPlayers().forEach {
- assertSame(lobby, it.lobby)
- assertTrue(it.isInLobby)
- assertFalse(it.isInGame)
- }
-
- val game = lobby.startGame()
- assertNotNull(game)
- lobby.getPlayers().forEachIndexed { index, it ->
- assertSame(index, it.index)
- assertSame(lobby, it.lobby)
- assertSame(game, it.game)
- assertTrue(it.isInLobby)
- assertTrue(it.isInGame)
- }
- }
-
- @Test
- fun startGame_switchesState() {
- assertEquals(State.LOBBY, lobby.state)
- // there is already the owner
- addPlayers(gameDefinition.minPlayers - 1)
- lobby.startGame()
- assertEquals(State.PLAYING, lobby.state)
- }
-
- @Test
- fun setSettings() {
- val settings = CustomizableSettings()
- lobby.settings = settings
- assertSame(settings, lobby.settings)
- }
-
- companion object {
-
- private lateinit var gameDefinition: GameDefinition
-
- @JvmStatic
- @DataPoints
- fun nbPlayers(): IntArray = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
-
- @JvmStatic
- @BeforeClass
- fun loadDefinition() {
- gameDefinition = GameDefinition.load()
- }
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/LobbyRepositoryTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/LobbyRepositoryTest.kt
deleted file mode 100644
index 446feee6..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/LobbyRepositoryTest.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.luxons.sevenwonders.repositories
-
-import org.junit.Before
-import org.junit.Test
-import org.luxons.sevenwonders.lobby.Player
-import kotlin.test.assertFailsWith
-import kotlin.test.assertNotNull
-import kotlin.test.assertSame
-import kotlin.test.assertTrue
-import kotlin.test.fail
-
-class LobbyRepositoryTest {
-
- private lateinit var repository: LobbyRepository
-
- @Before
- fun setUp() {
- repository = LobbyRepository()
- }
-
- @Test
- fun list_initiallyEmpty() {
- assertTrue(repository.list().isEmpty())
- }
-
- @Test
- fun list_returnsAllLobbies() {
- val owner = Player("owner", "The Owner")
- val lobby1 = repository.create("Test Name 1", owner)
- val lobby2 = repository.create("Test Name 2", owner)
- assertTrue(repository.list().contains(lobby1))
- assertTrue(repository.list().contains(lobby2))
- }
-
- @Test
- fun create_withCorrectOwner() {
- val owner = Player("owner", "The Owner")
- val lobby = repository.create("Test Name", owner)
- assertTrue(lobby.isOwner(owner.username))
- }
-
- @Test
- fun find_failsOnUnknownId() {
- assertFailsWith<LobbyNotFoundException> {
- repository.find(123)
- }
- }
-
- @Test
- fun find_returnsTheSameObject() {
- val owner = Player("owner", "The Owner")
- val lobby1 = repository.create("Test Name 1", owner)
- val lobby2 = repository.create("Test Name 2", owner)
- assertSame(lobby1, repository.find(lobby1.id))
- assertSame(lobby2, repository.find(lobby2.id))
- }
-
- @Test
- fun remove_failsOnUnknownId() {
- assertFailsWith<LobbyNotFoundException> {
- repository.remove(123)
- }
- }
-
- @Test
- fun remove_succeeds() {
- val owner = Player("owner", "The Owner")
- val lobby1 = repository.create("Test Name 1", owner)
- assertNotNull(repository.find(lobby1.id))
- repository.remove(lobby1.id)
- try {
- repository.find(lobby1.id)
- fail() // the call to find() should have failed
- } catch (e: LobbyNotFoundException) {
- // the lobby has been properly removed
- }
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/PlayerRepositoryTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/PlayerRepositoryTest.kt
deleted file mode 100644
index aeedc54c..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/repositories/PlayerRepositoryTest.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.luxons.sevenwonders.repositories
-
-import org.junit.Before
-import org.junit.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertSame
-import kotlin.test.assertTrue
-
-class PlayerRepositoryTest {
-
- private lateinit var repository: PlayerRepository
-
- @Before
- fun setUp() {
- repository = PlayerRepository()
- }
-
- @Test
- fun contains_falseIfNoUserAdded() {
- assertFalse(repository.contains("anyUsername"))
- }
-
- @Test
- fun contains_trueForCreatedPlayer() {
- repository.createOrUpdate("player1", "Player 1")
- assertTrue(repository.contains("player1"))
- }
-
- @Test
- fun createOrUpdate_createsProperly() {
- val player1 = repository.createOrUpdate("player1", "Player 1")
- assertEquals("player1", player1.username)
- assertEquals("Player 1", player1.displayName)
- }
-
- @Test
- fun createOrUpdate_updatesDisplayName() {
- val player1 = repository.createOrUpdate("player1", "Player 1")
- val player1Updated = repository.createOrUpdate("player1", "Much Better Name")
- assertSame(player1, player1Updated)
- assertEquals("Much Better Name", player1Updated.displayName)
- }
-
- @Test
- fun find_failsOnUnknownUsername() {
- assertFailsWith<PlayerNotFoundException> {
- repository.find("anyUsername")
- }
- }
-
- @Test
- fun find_returnsTheSameObject() {
- val player1 = repository.createOrUpdate("player1", "Player 1")
- val player2 = repository.createOrUpdate("player2", "Player 2")
- assertSame(player1, repository.find("player1"))
- assertSame(player2, repository.find("player2"))
- }
-
- @Test
- fun remove_failsOnUnknownUsername() {
- assertFailsWith<PlayerNotFoundException> {
- repository.remove("anyUsername")
- }
- }
-
- @Test
- fun remove_succeeds() {
- repository.createOrUpdate("player1", "Player 1")
- assertTrue(repository.contains("player1"))
- repository.remove("player1")
- assertFalse(repository.contains("player1"))
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/TestUtils.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/TestUtils.kt
deleted file mode 100644
index 9f328c5f..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/test/TestUtils.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.luxons.sevenwonders.test
-
-import org.springframework.messaging.Message
-import org.springframework.messaging.MessageChannel
-import org.springframework.messaging.simp.SimpMessagingTemplate
-
-fun mockSimpMessagingTemplate(): SimpMessagingTemplate = SimpMessagingTemplate(object : MessageChannel {
- override fun send(message: Message<*>): Boolean = true
- override fun send(message: Message<*>, timeout: Long): Boolean = true
-})
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt
deleted file mode 100644
index ee5827cc..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.luxons.sevenwonders.test.api
-
-import com.fasterxml.jackson.databind.module.SimpleModule
-import com.fasterxml.jackson.module.kotlin.KotlinModule
-import org.hildan.jackstomp.JackstompClient
-import org.luxons.sevenwonders.config.SEVEN_WONDERS_WS_ENDPOINT
-import org.luxons.sevenwonders.game.resources.MutableResources
-import org.luxons.sevenwonders.game.resources.Resources
-import org.springframework.messaging.converter.MappingJackson2MessageConverter
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.TimeoutException
-
-class SevenWondersClient {
-
- private val client: JackstompClient
-
- init {
- val customMappingsModule = SimpleModule("ConcreteResourcesDeserializationModule")
- customMappingsModule.addAbstractTypeMapping(Resources::class.java, MutableResources::class.java)
-
- val mappingJackson2MessageConverter = MappingJackson2MessageConverter()
- mappingJackson2MessageConverter.objectMapper.registerModule(customMappingsModule)
- mappingJackson2MessageConverter.objectMapper.registerModule(KotlinModule())
-
- client = JackstompClient()
- client.webSocketClient.messageConverter = mappingJackson2MessageConverter
- }
-
- @Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class)
- fun connect(serverUrl: String): SevenWondersSession {
- val session = client.syncConnect(serverUrl + SEVEN_WONDERS_WS_ENDPOINT)
- return SevenWondersSession(session)
- }
-
- fun stop() {
- client.stop()
- }
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersSession.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersSession.kt
deleted file mode 100644
index 70031a71..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersSession.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.luxons.sevenwonders.test.api
-
-import org.hildan.jackstomp.Channel
-import org.hildan.jackstomp.JackstompSession
-import org.luxons.sevenwonders.actions.ChooseNameAction
-import org.luxons.sevenwonders.actions.CreateGameAction
-import org.luxons.sevenwonders.actions.JoinGameAction
-import org.luxons.sevenwonders.api.LobbyDTO
-import org.luxons.sevenwonders.api.PlayerDTO
-import org.luxons.sevenwonders.errors.ErrorDTO
-import org.luxons.sevenwonders.game.api.PlayerTurnInfo
-import kotlin.test.assertEquals
-import kotlin.test.assertNotNull
-import kotlin.test.assertTrue
-
-class SevenWondersSession(val jackstompSession: JackstompSession) {
-
- fun disconnect() {
- jackstompSession.disconnect()
- }
-
- fun watchErrors(): Channel<ErrorDTO> = jackstompSession.subscribe("/user/queue/errors", ErrorDTO::class.java)
-
- @Throws(InterruptedException::class)
- fun chooseName(displayName: String): PlayerDTO {
- val action = ChooseNameAction(displayName)
- return jackstompSession.request(action, PlayerDTO::class.java, "/app/chooseName", "/user/queue/nameChoice")
- }
-
- fun watchGames(): Channel<Array<LobbyDTO>> {
- return jackstompSession.subscribe("/topic/games", Array<LobbyDTO>::class.java)
- }
-
- @Throws(InterruptedException::class)
- fun createGame(gameName: String): LobbyDTO {
- val action = CreateGameAction(gameName)
- return jackstompSession.request(action, LobbyDTO::class.java, "/app/lobby/create", "/user/queue/lobby/joined")
- }
-
- @Throws(InterruptedException::class)
- fun joinGame(gameId: Long): LobbyDTO {
- val action = JoinGameAction(gameId)
- val lobby =
- jackstompSession.request(action, LobbyDTO::class.java, "/app/lobby/join", "/user/queue/lobby/joined")
- assertNotNull(lobby)
- assertEquals(gameId, lobby.id)
- return lobby
- }
-
- fun watchLobbyUpdates(gameId: Long): Channel<LobbyDTO> =
- jackstompSession.subscribe("/topic/lobby/$gameId/updated", LobbyDTO::class.java)
-
- fun watchLobbyStart(gameId: Long): Channel<LobbyDTO> =
- jackstompSession.subscribe("/topic/lobby/$gameId/started", LobbyDTO::class.java)
-
- @Throws(InterruptedException::class)
- fun startGame(gameId: Long) {
- val sendDestination = "/app/lobby/startGame"
- val receiveDestination = "/topic/lobby/$gameId/started"
- val received = jackstompSession.request(null, sendDestination, receiveDestination)
- assertTrue(received)
- }
-
- fun sayReady() {
- jackstompSession.send("/app/game/sayReady", "")
- }
-
- fun watchTurns(): Channel<PlayerTurnInfo> =
- jackstompSession.subscribe("/user/queue/game/turn", PlayerTurnInfo::class.java)
-}
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidatorTest.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidatorTest.kt
deleted file mode 100644
index 85d03e99..00000000
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/validation/DestinationAccessValidatorTest.kt
+++ /dev/null
@@ -1,147 +0,0 @@
-package org.luxons.sevenwonders.validation
-
-import org.junit.Before
-import org.junit.Test
-import org.luxons.sevenwonders.lobby.Lobby
-import org.luxons.sevenwonders.lobby.Player
-import org.luxons.sevenwonders.repositories.LobbyNotFoundException
-import org.luxons.sevenwonders.repositories.LobbyRepository
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertTrue
-
-class DestinationAccessValidatorTest {
-
- private lateinit var lobbyRepository: LobbyRepository
-
- private lateinit var destinationAccessValidator: DestinationAccessValidator
-
- @Before
- fun setup() {
- lobbyRepository = LobbyRepository()
- destinationAccessValidator = DestinationAccessValidator(lobbyRepository)
- }
-
- private fun createLobby(gameName: String, ownerUsername: String, vararg otherPlayers: String): Lobby {
- val owner = Player(ownerUsername, ownerUsername)
- val lobby = lobbyRepository.create(gameName, owner)
- for (playerName in otherPlayers) {
- val player = Player(playerName, playerName)
- lobby.addPlayer(player)
- }
- return lobby
- }
-
- private fun createGame(gameName: String, ownerUsername: String, vararg otherPlayers: String) {
- val lobby = createLobby(gameName, ownerUsername, *otherPlayers)
- lobby.startGame()
- }
-
- @Test
- fun validate_failsOnNullUser() {
- assertFalse(destinationAccessValidator.hasAccess(null, "doesNotMatter"))
- }
-
- @Test
- fun validate_successWhenNoReference() {
- assertTrue(destinationAccessValidator.hasAccess("", ""))
- assertTrue(destinationAccessValidator.hasAccess("", "test"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "test"))
- }
-
- @Test
- fun validate_successWhenNoRefFollows() {
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/game/"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby/"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/game/"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/lobby/"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/game//suffix"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby//suffix"))
- }
-
- @Test
- fun validate_successWhenRefIsNotANumber() {
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/game/notANumber"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby/notANumber"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/game/notANumber"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "prefix/lobby/notANumber"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/game/notANumber/suffix"))
- assertTrue(destinationAccessValidator.hasAccess("testUser", "/lobby/notANumber/suffix"))
- }
-
- @Test
- fun validate_failWhenNoLobbyExist() {
- assertFailsWith<LobbyNotFoundException> {
- destinationAccessValidator.hasAccess("", "/lobby/0")
- }
- }
-
- @Test
- fun validate_failWhenNoGameExist() {
- assertFailsWith<LobbyNotFoundException> {
- destinationAccessValidator.hasAccess("", "/game/0")
- }
- }
-
- @Test
- fun validate_failWhenReferencedLobbyDoesNotExist() {
- createLobby("Test Game", "ownerUser1")
- createLobby("Test Game 2", "ownerUser2")
- assertFailsWith<LobbyNotFoundException> {
- destinationAccessValidator.hasAccess("doesNotMatter", "/lobby/3")
- }
- }
-
- @Test
- fun validate_failWhenReferencedGameDoesNotExist() {
- createGame("Test Game 1", "user1", "user2", "user3")
- createGame("Test Game 2", "user4", "user5", "user6")
- assertFailsWith<LobbyNotFoundException> {
- destinationAccessValidator.hasAccess("doesNotMatter", "/game/3")
- }
- }
-
- @Test
- fun validate_failWhenUserIsNotPartOfReferencedLobby() {
- createLobby("Test Game", "ownerUser")
- destinationAccessValidator.hasAccess("userNotInLobby", "/lobby/0")
- }
-
- @Test
- fun validate_failWhenUserIsNotPartOfReferencedGame() {
- createGame("Test Game", "ownerUser", "otherUser1", "otherUser2")
- destinationAccessValidator.hasAccess("userNotInGame", "/game/0")
- }
-
- @Test
- fun validate_successWhenUserIsOwnerOfReferencedLobby() {
- createLobby("Test Game 1", "user1")
- assertTrue(destinationAccessValidator.hasAccess("user1", "/lobby/0"))
- createLobby("Test Game 2", "user2")
- assertTrue(destinationAccessValidator.hasAccess("user2", "/lobby/1"))
- }
-
- @Test
- fun validate_successWhenUserIsMemberOfReferencedLobby() {
- createLobby("Test Game 1", "user1", "user2")
- assertTrue(destinationAccessValidator.hasAccess("user2", "/lobby/0"))
- createLobby("Test Game 2", "user3", "user4")
- assertTrue(destinationAccessValidator.hasAccess("user4", "/lobby/1"))
- }
-
- @Test
- fun validate_successWhenUserIsOwnerOfReferencedGame() {
- createGame("Test Game 1", "owner1", "user2", "user3")
- assertTrue(destinationAccessValidator.hasAccess("owner1", "/game/0"))
- createGame("Test Game 2", "owner4", "user5", "user6")
- assertTrue(destinationAccessValidator.hasAccess("owner4", "/game/1"))
- }
-
- @Test
- fun validate_successWhenUserIsMemberOfReferencedGame() {
- createGame("Test Game 1", "owner1", "user2", "user3")
- assertTrue(destinationAccessValidator.hasAccess("user2", "/game/0"))
- createGame("Test Game 2", "owner4", "user5", "user6")
- assertTrue(destinationAccessValidator.hasAccess("user6", "/game/1"))
- }
-}
bgstack15