diff --git a/README.md b/README.md index 4bcf77ff72bb7eec9ee8af4bd482421220757720..c185f273e090e217f7b4c4a6190528ba080c82bd 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,42 @@ -# tournament-api +# Tournament API -This project was created using the [Ktor Project Generator](https://start.ktor.io). +## Initalisation -Here are some useful links to get you started: +### Pre-requisites -- [Ktor Documentation](https://ktor.io/docs/home.html) -- [Ktor GitHub page](https://github.com/ktorio/ktor) -- The [Ktor Slack chat](https://app.slack.com/client/T09229ZC6/C0A974TJ9). You'll need - to [request an invite](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up) to join. +You need to have Docker and AWS CLI installed on your machine -## Features +### How to start the database -Here's a list of features included in this project: +In `docker/db` folder, run the following command: -| Name | Description | -| --------------------------------------------------------------------|------------------------------------------------------------------------------------ | -| [Routing](https://start.ktor.io/p/routing) | Provides a structured routing DSL | -| [Authentication](https://start.ktor.io/p/auth) | Provides extension point for handling the Authorization header | -| [OpenAPI](https://start.ktor.io/p/openapi) | Serves OpenAPI documentation | -| [Koin](https://start.ktor.io/p/koin) | Provides dependency injection | -| [Content Negotiation](https://start.ktor.io/p/content-negotiation) | Provides automatic content conversion according to Content-Type and Accept headers | -| [Jackson](https://start.ktor.io/p/ktor-jackson) | Handles JSON serialization using Jackson library | +```bash +docker compose up -d +``` -## Building & Running +### How to start the API -To build or run the project, use one of the following tasks: +Place yourself at root and start -| Task | Description | -| -------------------------------|---------------------------------------------------------------------- | -| `./gradlew test` | Run the tests | -| `./gradlew build` | Build everything | -| `buildFatJar` | Build an executable JAR of the server with all dependencies included | -| `buildImage` | Build the docker image to use with the fat JAR | -| `publishImageToLocalRegistry` | Publish the docker image locally | -| `run` | Run the server | -| `runDocker` | Run using the local docker image | +```bash +docker compose up -d +``` -If the server starts successfully, you'll see the following output: +## Available endpoints -``` -2024-12-04 14:32:45.584 [main] INFO Application - Application started in 0.303 seconds. -2024-12-04 14:32:45.682 [main] INFO Application - Responding at http://0.0.0.0:8080 -``` +## I want to ensure tests are running + +## Left to do +- [x] setup dynamo DB +- [x] faire la connexion avec Dynamo +- 1er endpoint + - [x] créer l'entité joueur + - [ ] créer le repo et le connecter à la BD + - [ ] tester unitairement le service + - [ ] tester l'intégration complète +- [ ] endpoint fonctionnel pour l'ajout d'un avec test + - [ ] tests d'inté + - [ ] tests unitaires +- [ ] tous les endpoints autres +- [ ] gestion de la sécurité \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 97793e0e841858857e50a37f9253b7530b70e88d..ad355185daff0d5fa04af60a68110aa1fd063cc1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,11 +3,12 @@ val kotlin_version: String by project val logback_version: String by project val dynamo_version: String by project val dynamo_kt_version: String by project +val mockk_version: String by project plugins { kotlin("jvm") version "2.1.10" - id("io.ktor.plugin") version "3.0.3" + id("io.ktor.plugin") version "2.3.13" } group = "betclic.test" @@ -39,5 +40,6 @@ dependencies { implementation("software.amazon.awssdk:dynamodb:$dynamo_version") implementation("dev.andrewohara:dynamokt:$dynamo_kt_version") testImplementation("io.ktor:ktor-server-test-host") + testImplementation("io.mockk:mockk:$mockk_version") testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") } diff --git a/docker/db/README.md b/docker/db/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f3d294899b5cb8ec89f69495bd7973fc0f53d112 --- /dev/null +++ b/docker/db/README.md @@ -0,0 +1,17 @@ +# Local Database + +Use this docker-compose file to run a local database for development. + +## Usage + +### Pre-requisites + +You need to have Docker and AWS CLI installed on your machine + +### How to start the database + +In `docker/db` folder, run the following command: + +```bash +docker compose up +``` diff --git a/gradle.properties b/gradle.properties index d7945c570c885b7422decff0dd1fefef5a036b12..4bf19e423ad49f08562490a302fd7a7286251344 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,5 +3,6 @@ koin_version=3.5.6 kotlin_version=2.1.10 dynamo_version=2.28.1 dynamo_kt_version=1.0.0 -ktor_version=3.0.3 +ktor_version=2.3.13 logback_version=1.4.14 +mockk_version=1.10.0 diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt index 08311e31f8d018cf04f68bf788b8de5cede9e82c..074276f1574861c360f46f3b33860cf928584dc0 100644 --- a/src/main/kotlin/Application.kt +++ b/src/main/kotlin/Application.kt @@ -1,15 +1,16 @@ package betclic.test +import betclic.test.player.configureRouting import io.ktor.server.application.* +import kotlinx.coroutines.runBlocking fun main(args: Array<String>) { io.ktor.server.netty.EngineMain.main(args) } -fun Application.module() { - configureSecurity() +fun Application.module() = runBlocking { configureHTTP() - configureFrameworks() + configureKoin() configureSerialization() configureRouting() } diff --git a/src/main/kotlin/DynamoDbConfiguration.kt b/src/main/kotlin/DynamoDbConfiguration.kt new file mode 100644 index 0000000000000000000000000000000000000000..8c3d3ad3e6bf45d4b4cc85f11bdea5a3691cb5b3 --- /dev/null +++ b/src/main/kotlin/DynamoDbConfiguration.kt @@ -0,0 +1,58 @@ +package betclic.test + +import betclic.test.player.PlayerEntity +import dev.andrewohara.dynamokt.DataClassTableSchema +import io.ktor.server.application.* +import kotlinx.coroutines.future.await +import org.slf4j.LoggerFactory +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient +import java.net.URI +import kotlin.reflect.KClass + +class DynamoDbConfiguration() { + private val logger = LoggerFactory.getLogger(DynamoDbConfiguration::class.java) + fun dataSource(): DynamoDbEnhancedAsyncClient { + logger.info("Using dynamo-db config") + return DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(createDynamoDbClient()) + .build() + } +} + +private fun createDynamoDbClient(): DynamoDbAsyncClient { + return DynamoDbAsyncClient.builder().endpointOverride(URI("http://localhost:8000")).build() +} + +fun Application.createEnhancedDynamoDbClient(dynamoDbClient: DynamoDbAsyncClient): DynamoDbEnhancedAsyncClient { + return DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(dynamoDbClient) + .build() +} + +suspend fun createNecessaryTables( + dynamoDbClient: DynamoDbAsyncClient, + dynamoDbEnhancedClient: DynamoDbEnhancedAsyncClient +) { + val existingTables = dynamoDbClient.listTables().await().tableNames().toList() + + listOf(PlayerEntity::class).forEach { + createTableIfNotExists(existingTables, it, dynamoDbEnhancedClient) + } +} + +private val logger = LoggerFactory.getLogger(Application::class.java) + +private suspend fun <T : Any> createTableIfNotExists( + existingTables: List<String>, + item: KClass<T>, + dynamoDbEnhancedClient: DynamoDbEnhancedAsyncClient +) { + val tableSchema = DataClassTableSchema(item) + if (existingTables.contains(item.simpleName)) { + logger.info("Table '${item.simpleName}' already exists.") + } else { + dynamoDbEnhancedClient.table(item.simpleName, tableSchema).createTable().await() + logger.info("Table '${item.simpleName}' created successfully.") + } +} \ No newline at end of file diff --git a/src/main/kotlin/Frameworks.kt b/src/main/kotlin/Frameworks.kt deleted file mode 100644 index 7e7b4dee0d4a59e38caec8c4fedcc3006029133a..0000000000000000000000000000000000000000 --- a/src/main/kotlin/Frameworks.kt +++ /dev/null @@ -1,25 +0,0 @@ -package betclic.test - -import com.fasterxml.jackson.databind.* -import io.ktor.serialization.jackson.* -import io.ktor.server.application.* -import io.ktor.server.plugins.contentnegotiation.* -import io.ktor.server.plugins.openapi.* -import io.ktor.server.response.* -import io.ktor.server.routing.* -import org.koin.dsl.module -import org.koin.ktor.plugin.Koin -import org.koin.logger.slf4jLogger - -fun Application.configureFrameworks() { - install(Koin) { - slf4jLogger() - modules(module { - single<HelloService> { - HelloService { - println(environment.log.info("Hello, World!")) - } - } - }) - } -} diff --git a/src/main/kotlin/Koin.kt b/src/main/kotlin/Koin.kt new file mode 100644 index 0000000000000000000000000000000000000000..e8afee56714ea9b172003630cabc19e6c4c21dfe --- /dev/null +++ b/src/main/kotlin/Koin.kt @@ -0,0 +1,22 @@ +package betclic.test + +import betclic.test.player.PlayerRepository +import betclic.test.player.PlayerService +import betclic.test.player.PlayerServiceImpl +import io.ktor.server.application.* +import org.koin.dsl.module +import org.koin.ktor.plugin.Koin +import org.koin.logger.slf4jLogger + +fun Application.configureKoin() { + install(Koin) { + slf4jLogger() + modules(playerModule) + } +} + +val playerModule = module { + single { DynamoDbConfiguration().dataSource() } + single<PlayerRepository> { PlayerRepository(get()) } + single<PlayerService> { PlayerServiceImpl(get()) } +} diff --git a/src/main/kotlin/Routing.kt b/src/main/kotlin/Routing.kt deleted file mode 100644 index d89e2e81b3026cd4baf578159a7265d15ed9bfe1..0000000000000000000000000000000000000000 --- a/src/main/kotlin/Routing.kt +++ /dev/null @@ -1,13 +0,0 @@ -package betclic.test - -import io.ktor.server.application.* -import io.ktor.server.response.* -import io.ktor.server.routing.* - -fun Application.configureRouting() { - routing { - get("/") { - call.respondText("Hello World!") - } - } -} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 23f6a01b1e136a2ee2b26f8df378f71fdc586672..bd3c34ff7cc46fa7aa2c4666beaf425766210b20 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -4,3 +4,5 @@ ktor: - betclic.test.ApplicationKt.module deployment: port: 8080 + database: + dynamodbUrl: "http://localhost:8000"