From 73841170cc120f17e7e1bbdf029e5cd6fee3d629 Mon Sep 17 00:00:00 2001
From: luevard <99143550+saucepommefrite@users.noreply.github.com>
Date: Thu, 11 Jan 2024 09:55:41 +0100
Subject: [PATCH 01/31] :sparkles: Add database for local usage
---
Sources/pom.xml | 5 +++++
Sources/src/main/kotlin/allin/Application.kt | 2 --
Sources/src/main/kotlin/allin/entities/UserEntity.kt | 5 +++--
Sources/src/main/kotlin/allin/model/User.kt | 4 ++--
4 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/Sources/pom.xml b/Sources/pom.xml
index 0d8b30f..c569b14 100644
--- a/Sources/pom.xml
+++ b/Sources/pom.xml
@@ -32,6 +32,11 @@
ktor-server-core-jvm
${ktor_version}
+
+ org.postgresql
+ postgresql
+ 42.7.1
+
io.ktor
ktor-server-netty-jvm
diff --git a/Sources/src/main/kotlin/allin/Application.kt b/Sources/src/main/kotlin/allin/Application.kt
index 93119eb..5f8fb99 100644
--- a/Sources/src/main/kotlin/allin/Application.kt
+++ b/Sources/src/main/kotlin/allin/Application.kt
@@ -1,6 +1,4 @@
package allin
-
-import allin.model.User
import allin.routing.BasicRouting
import allin.routing.BetRouter
import allin.routing.UserRouter
diff --git a/Sources/src/main/kotlin/allin/entities/UserEntity.kt b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
index d8f0996..0500cf5 100644
--- a/Sources/src/main/kotlin/allin/entities/UserEntity.kt
+++ b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
@@ -1,11 +1,12 @@
package allin.entities
import org.ktorm.schema.Table
+import org.ktorm.schema.double
import org.ktorm.schema.int
import org.ktorm.schema.varchar
-
-object UserEntity : Table("user") {
+object UserEntity : Table("utilisateur") {
val id = int("id").primaryKey()
val username = varchar("username")
val password = varchar("password")
+ val nbCoins = double("nbCoins")
}
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/model/User.kt b/Sources/src/main/kotlin/allin/model/User.kt
index d01dc50..3159bc9 100644
--- a/Sources/src/main/kotlin/allin/model/User.kt
+++ b/Sources/src/main/kotlin/allin/model/User.kt
@@ -1,10 +1,10 @@
package allin.model
import allin.dto.UserDTO
+import allin.routing.users
import kotlinx.serialization.Serializable
@Serializable
data class User(val username: String, val email: String, var password: String, var nbCoins: Int = 1000, var token: String? = null)
-
@Serializable
-data class CheckUser(val login: String,val password: String)
\ No newline at end of file
+data class CheckUser(val login: String,val password: String)
--
2.36.3
From ff4e36beea0c00af19cb9ab309fa7905a80cf409 Mon Sep 17 00:00:00 2001
From: luevard <99143550+saucepommefrite@users.noreply.github.com>
Date: Mon, 15 Jan 2024 13:34:26 +0100
Subject: [PATCH 02/31] :sparkles: Local Database link
---
Sources/src/main/kotlin/allin/dto/UserDTO.kt | 13 +---
.../main/kotlin/allin/entities/UserEntity.kt | 63 ++++++++++++++++++-
Sources/src/main/kotlin/allin/model/Bet.kt | 15 +----
.../src/main/kotlin/allin/model/BetAction.kt | 4 +-
Sources/src/main/kotlin/allin/model/User.kt | 4 +-
.../main/kotlin/allin/routing/BetRouter.kt | 15 +++--
.../main/kotlin/allin/routing/UserRouter.kt | 48 +++++++-------
.../kotlin/allin/serializer/DateSerializer.kt | 26 ++++----
.../main/kotlin/allin/utils/CryptManager.kt | 16 +++--
.../main/kotlin/allin/utils/TokenManager.kt | 26 +++++++-
10 files changed, 151 insertions(+), 79 deletions(-)
diff --git a/Sources/src/main/kotlin/allin/dto/UserDTO.kt b/Sources/src/main/kotlin/allin/dto/UserDTO.kt
index d59f39c..a440450 100644
--- a/Sources/src/main/kotlin/allin/dto/UserDTO.kt
+++ b/Sources/src/main/kotlin/allin/dto/UserDTO.kt
@@ -1,15 +1,4 @@
package allin.dto
-
-import allin.model.User
import kotlinx.serialization.Serializable
-
@Serializable
-data class UserDTO(val username: String,val email: String, val nbCoins: Int)
-@Serializable
-data class UserDTOWithToken(val username: String,val email: String, val nbCoins: Int, val token:String?)
-fun convertUserToUserDTO(user: User): UserDTO {
- return UserDTO(user.username, user.email, user.nbCoins)
-}
-fun convertUserToUserDTOToken(user: User): UserDTOWithToken {
- return UserDTOWithToken(user.username, user.email, user.nbCoins,user.token)
-}
+data class UserDTO(val username: String, val email: String, val nbCoins: Double, var token:String?)
diff --git a/Sources/src/main/kotlin/allin/entities/UserEntity.kt b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
index 0500cf5..e1ba032 100644
--- a/Sources/src/main/kotlin/allin/entities/UserEntity.kt
+++ b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
@@ -1,12 +1,71 @@
package allin.entities
+import allin.dto.UserDTO
+import allin.model.User
+import allin.routing.database
+import org.ktorm.dsl.*
+import org.ktorm.entity.*
import org.ktorm.schema.Table
import org.ktorm.schema.double
import org.ktorm.schema.int
import org.ktorm.schema.varchar
-object UserEntity : Table("utilisateur") {
+
+interface UserEntity : Entity {
+ val username: String
+ var email: String
+ var password: String
+ var nbCoins: Double
+}
+object UsersEntity : Table("utilisateur") {
val id = int("id").primaryKey()
val username = varchar("username")
val password = varchar("password")
val nbCoins = double("nbCoins")
-}
\ No newline at end of file
+ val email = varchar("email")
+
+ fun getUserToUserDTO(): MutableList {
+ return database.from(UsersEntity).select().map {
+ row -> UserDTO(
+ row[username].toString(),
+ row[email].toString(),
+ row[nbCoins]?:0.0,
+ null
+ )
+ }.toMutableList()
+ }
+
+ fun getUserByUsernameAndPassword(login: String): Pair {
+ return database.from(UsersEntity)
+ .select()
+ .where { (username eq login) /*and (password eq passwordParam)*/ }
+ .map { row ->
+ Pair(
+ UserDTO(
+ row[username].toString(),
+ row[email].toString(),
+ row[nbCoins] ?: 0.0,
+ null
+ ),
+ row[password].toString()
+ )
+ }
+ .firstOrNull() ?: Pair(null, null)
+ }
+
+ fun addUserEntity(user : User){
+ database.insert(UsersEntity){
+ set(it.nbCoins,user.nbCoins)
+ set(it.username,user.username)
+ set(it.password,user.password)
+ set(it.email,user.email)
+ }
+ }
+ fun deleteUserByUsername(username: String): Boolean {
+ val deletedCount = database.delete(UsersEntity) {
+ it.username eq username
+ }
+ return deletedCount > 0
+ }
+}
+
+
diff --git a/Sources/src/main/kotlin/allin/model/Bet.kt b/Sources/src/main/kotlin/allin/model/Bet.kt
index 5d4bc13..c99b923 100644
--- a/Sources/src/main/kotlin/allin/model/Bet.kt
+++ b/Sources/src/main/kotlin/allin/model/Bet.kt
@@ -1,19 +1,10 @@
package allin.model
-import allin.dto.UserDTOWithToken
-import allin.serializer.DateSerializer
+import allin.serializer.ZonedDateTimeSerializer
import kotlinx.serialization.Serializable
import java.util.*
@Serializable
-data class Bet(val id: Int, val theme: String, val sentenceBet: String, @Serializable(DateSerializer::class) val endRegistration: Date, @Serializable(DateSerializer::class) var endBet : Date, var isPrivate : Boolean, var response : MutableList, val createdBy : String)
-
-@Serializable
-data class UpdatedBetData(val id: Int,@Serializable(DateSerializer::class) val endBet: Date, val isPrivate: Boolean, val response: MutableList)
-
+data class Bet(val id: Int, val theme: String, val sentenceBet: String, @Serializable(ZonedDateTimeSerializer::class) val endRegistration: Date, @Serializable(ZonedDateTimeSerializer::class) var endBet : Date, var isPrivate : Boolean, var response : MutableList, var createdBy : String)
@Serializable
-data class BetWithoutId(val theme: String, val sentenceBet: String, @Serializable(DateSerializer::class) val endRegistration: Date, @Serializable(DateSerializer::class) var endBet : Date, var isPrivate : Boolean, var response : MutableList, val createdBy : String)
-
-fun convertBetWithoutIdToBet(betWithoutId: BetWithoutId,id : Int, username : String): Bet {
- return Bet(id,betWithoutId.theme,betWithoutId.sentenceBet,betWithoutId.endRegistration, betWithoutId.endBet, betWithoutId.isPrivate, betWithoutId.response, username)
-}
+data class UpdatedBetData(val id: Int,@Serializable(ZonedDateTimeSerializer::class) val endBet: Date, val isPrivate: Boolean, val response: MutableList)
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/model/BetAction.kt b/Sources/src/main/kotlin/allin/model/BetAction.kt
index f830e2c..2f2298b 100644
--- a/Sources/src/main/kotlin/allin/model/BetAction.kt
+++ b/Sources/src/main/kotlin/allin/model/BetAction.kt
@@ -1,5 +1,5 @@
package allin.model
-import allin.dto.UserDTOWithToken
+import allin.dto.UserDTO
data class BetAction(val id:Int, val coins: Int, val user: String, val bet: Int)
-data class BetActionCompleted(val id:Int, val coins: Int, val user: UserDTOWithToken, val bet: Bet)
+data class BetActionCompleted(val id:Int, val coins: Int, val user: UserDTO, val bet: Bet)
diff --git a/Sources/src/main/kotlin/allin/model/User.kt b/Sources/src/main/kotlin/allin/model/User.kt
index 3159bc9..4f3f1f0 100644
--- a/Sources/src/main/kotlin/allin/model/User.kt
+++ b/Sources/src/main/kotlin/allin/model/User.kt
@@ -1,10 +1,8 @@
package allin.model
-import allin.dto.UserDTO
-import allin.routing.users
import kotlinx.serialization.Serializable
@Serializable
-data class User(val username: String, val email: String, var password: String, var nbCoins: Int = 1000, var token: String? = null)
+data class User(val username: String, val email: String, var password: String, var nbCoins: Double = 1000.0, var token: String? = null)
@Serializable
data class CheckUser(val login: String,val password: String)
diff --git a/Sources/src/main/kotlin/allin/routing/BetRouter.kt b/Sources/src/main/kotlin/allin/routing/BetRouter.kt
index 997cee5..51e398d 100644
--- a/Sources/src/main/kotlin/allin/routing/BetRouter.kt
+++ b/Sources/src/main/kotlin/allin/routing/BetRouter.kt
@@ -5,7 +5,10 @@ import io.ktor.server.routing.*
import allin.model.*
import allin.utils.AppConfig
import io.ktor.http.*
+import io.ktor.server.auth.*
+import io.ktor.server.auth.jwt.*
import io.ktor.server.response.*
+import java.time.ZonedDateTime
val bets = mutableListOf()
val tokenManagerBet= AppConfig.tokenManager
@@ -16,20 +19,22 @@ fun CreateId() : Int{
fun Application.BetRouter(){
routing{
+ authenticate {
route("/bets/add"){
post{
- val bet = call.receive()
+ val bet = call.receive()
+ val token= call.principal()
val id = CreateId()
- val username = tokenManagerBet.getUsernameFromToken(bet.createdBy)
+ bet.createdBy = tokenManagerBet.getUsernameFromToken(token.toString())
val findbet = bets.find { it.id == id }
if(findbet==null){
- val betWithId = convertBetWithoutIdToBet(bet,id,username)
- bets.add(betWithId)
- call.respond(HttpStatusCode.Created, betWithId)
+ bets.add(bet)
+ call.respond(HttpStatusCode.Created, bet)
}
call.respond(HttpStatusCode.Conflict,"Bet already exist")
}
}
+ }
route("/bets/gets"){
get{
// if(bets.size>0)
diff --git a/Sources/src/main/kotlin/allin/routing/UserRouter.kt b/Sources/src/main/kotlin/allin/routing/UserRouter.kt
index 18489be..bfde82d 100644
--- a/Sources/src/main/kotlin/allin/routing/UserRouter.kt
+++ b/Sources/src/main/kotlin/allin/routing/UserRouter.kt
@@ -1,8 +1,10 @@
package allin.routing
-import allin.dto.*
-import allin.model.CheckUser
-import allin.model.User
+import allin.entities.UsersEntity.addUserEntity
+import allin.entities.UsersEntity.deleteUserByUsername
+import allin.entities.UsersEntity.getUserByUsernameAndPassword
+import allin.entities.UsersEntity.getUserToUserDTO
+import allin.model.*
import allin.utils.AppConfig
import io.ktor.http.*
import io.ktor.server.application.*
@@ -11,15 +13,13 @@ import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
+import org.ktorm.database.Database
-val users = mutableListOf()
val RegexCheckerUser= AppConfig.regexChecker
val CryptManagerUser= AppConfig.cryptManager
val tokenManagerUser=AppConfig.tokenManager
-
-
+val database = Database.connect("jdbc:postgresql://localhost:5432/Allin", user = "postgres", password = "lulu")
fun Application.UserRouter() {
-
routing {
route("/users/register"){
post {
@@ -27,12 +27,13 @@ fun Application.UserRouter() {
if (RegexCheckerUser.isEmailInvalid(TempUser.email)){
call.respond(HttpStatusCode.Forbidden,"Input a valid mail !")
}
+ val users=getUserToUserDTO()
val user = users.find { it.username == TempUser.username || it.email == TempUser.email }
if(user == null) {
CryptManagerUser.passwordCrypt(TempUser)
TempUser.token=tokenManagerUser.generateOrReplaceJWTToken(TempUser)
- users.add(TempUser)
- call.respond(HttpStatusCode.Created, TempUser)
+ addUserEntity(TempUser)
+ call.respond(HttpStatusCode.Created,TempUser)
}
call.respond(HttpStatusCode.Conflict,"Mail or/and username already exist")
}
@@ -41,25 +42,27 @@ fun Application.UserRouter() {
route("/users/login") {
post {
val checkUser = call.receive()
- val user = users.find { it.username == checkUser.login || it.email == checkUser.login }
- if (user != null && CryptManagerUser.passwordDecrypt(user,checkUser.password)) {
- user.token=tokenManagerUser.generateOrReplaceJWTToken(user)
- call.respond(HttpStatusCode.OK, convertUserToUserDTOToken(user))
+ val user =getUserByUsernameAndPassword(checkUser.login)
+ if (CryptManagerUser.passwordDecrypt(user.second.toString(),checkUser.password)) {
+ val userDtoWithToken=user.first
+ userDtoWithToken?.token=tokenManagerUser.generateOrReplaceJWTToken(userDtoWithToken!!)
+ call.respond(HttpStatusCode.OK, userDtoWithToken)
} else {
call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.")
}
}
}
-
route("/users/delete") {
post {
val checkUser = call.receive()
- val user = users.find { it.username == checkUser.login || it.email == checkUser.login }
- if (user != null && user.password == checkUser.password) {
- users.remove(user)
- call.respond(HttpStatusCode.Accepted,convertUserToUserDTO(user))
+ val user =getUserByUsernameAndPassword(checkUser.login)
+ if (CryptManagerUser.passwordDecrypt(user.second.toString(),checkUser.password)) {
+ if (!deleteUserByUsername(checkUser.login)) {
+ call.respond(HttpStatusCode.InternalServerError, "This user can't be delete now !")
+ }
+ call.respond(HttpStatusCode.Accepted,user.first!!)
} else {
- call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.")
+ call.respond(HttpStatusCode.NotFound, "Login and/or password incorrect.")
}
}
}
@@ -68,14 +71,13 @@ fun Application.UserRouter() {
get("/users/token") {
val principal = call.principal()
val username = principal!!.payload.getClaim("username").asString()
- val user = users.find { it.username == username }
- if (user != null) {
- call.respond(HttpStatusCode.OK,convertUserToUserDTO(user))
+ val user=getUserByUsernameAndPassword(username)
+ if (user.first != null) {
+ call.respond(HttpStatusCode.OK, user.first!!)
} else {
call.respond(HttpStatusCode.NotFound, "User not found with the valid token !")
}
}
}
-
}
}
diff --git a/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt b/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt
index 6002c28..dc84760 100644
--- a/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt
+++ b/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt
@@ -6,22 +6,22 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
-import java.text.SimpleDateFormat
-import java.util.*
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
-@Serializer(Date::class)
-class DateSerializer : KSerializer {
- override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING)
+@Serializer(ZonedDateTime::class)
+object ZonedDateTimeSerializer : KSerializer {
+ private val formatter: DateTimeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME
- val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.FRANCE)
+ override val descriptor: SerialDescriptor =
+ PrimitiveSerialDescriptor("ZonedDateTime", PrimitiveKind.STRING)
- override fun deserialize(decoder: Decoder): Date {
- val dateString = decoder.decodeString()
- return formatter.parse(dateString)
+ override fun serialize(encoder: Encoder, value: ZonedDateTime) {
+ encoder.encodeString(formatter.format(value))
}
- override fun serialize(encoder: Encoder, value: Date) {
- val dateString = formatter.format(value)
- encoder.encodeString(dateString)
+ override fun deserialize(decoder: Decoder): ZonedDateTime {
+ val dateString = decoder.decodeString()
+ return ZonedDateTime.parse(dateString, formatter)
}
-}
\ No newline at end of file
+}
diff --git a/Sources/src/main/kotlin/allin/utils/CryptManager.kt b/Sources/src/main/kotlin/allin/utils/CryptManager.kt
index 216e733..df9f8be 100644
--- a/Sources/src/main/kotlin/allin/utils/CryptManager.kt
+++ b/Sources/src/main/kotlin/allin/utils/CryptManager.kt
@@ -4,12 +4,18 @@ import allin.model.User
import org.mindrot.jbcrypt.BCrypt
class CryptManager {
- val salt=BCrypt.gensalt()
+ //val salt=BCrypt.gensalt()
+ fun passwordCrypt(password : String): String {
+ return BCrypt.hashpw(password,"\$2a\$10\$42wsdBeoLKaF6SM9oADONe")
+ }
fun passwordCrypt(user: User){
- user.password=BCrypt.hashpw(user.password,salt)
-
+ user.password=BCrypt.hashpw(user.password,"\$2a\$10\$42wsdBeoLKaF6SM9oADONe")
}
- fun passwordDecrypt(user: User, password: String): Boolean{
- return BCrypt.hashpw(password,salt)==user.password
+ fun passwordDecrypt(password: String, passwordClear: String): Boolean{
+ return BCrypt.hashpw(passwordClear,"\$2a\$10\$42wsdBeoLKaF6SM9oADONe")==password
+ }
+
+ fun CheckPassword(hashed: String, clear: String): Boolean{
+ return BCrypt.checkpw(hashed,clear)
}
}
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/utils/TokenManager.kt b/Sources/src/main/kotlin/allin/utils/TokenManager.kt
index d35ede5..0d82193 100644
--- a/Sources/src/main/kotlin/allin/utils/TokenManager.kt
+++ b/Sources/src/main/kotlin/allin/utils/TokenManager.kt
@@ -1,5 +1,6 @@
package allin.utils
+import allin.dto.UserDTO
import allin.model.User
import com.auth0.jwt.JWT
import com.auth0.jwt.JWTVerifier
@@ -15,7 +16,6 @@ class TokenManager private constructor(val config: HoconApplicationConfig) {
val issuer=config.property("issuer").getString()
fun generateJWTToken(user : User): String {
val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde
-
val token = JWT.create()
.withAudience(audience)
.withIssuer(issuer)
@@ -41,6 +41,26 @@ class TokenManager private constructor(val config: HoconApplicationConfig) {
}
}
+ fun generateOrReplaceJWTToken(user: UserDTO): String {
+ val userToken = getUserToken(user)
+ if (userToken != null && !isTokenExpired(userToken)) {
+ return userToken
+ } else {
+ return generateJWTToken(user)
+ }
+ }
+
+ fun generateJWTToken(user : UserDTO): String {
+ val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde
+ val token = JWT.create()
+ .withAudience(audience)
+ .withIssuer(issuer)
+ .withClaim("username", user.username)
+ .withExpiresAt(Date(expirationDate))
+ .sign(Algorithm.HMAC256(secret))
+ return token
+ }
+
fun isTokenExpired(token: String): Boolean {
val expirationTime = JWT.decode(token).expiresAt.time
return System.currentTimeMillis() > expirationTime
@@ -49,7 +69,9 @@ class TokenManager private constructor(val config: HoconApplicationConfig) {
fun getUserToken(user: User): String? {
return user.token
}
-
+ fun getUserToken(user: UserDTO): String? {
+ return user.token
+ }
fun getUsernameFromToken(token: String) : String{
val decodedJWT: DecodedJWT = JWT.decode(token)
return decodedJWT.getClaim("username").asString()
--
2.36.3
From 59faa48897b1c07d808cafcb974d52f5cc2ee902 Mon Sep 17 00:00:00 2001
From: luevard <99143550+saucepommefrite@users.noreply.github.com>
Date: Thu, 11 Jan 2024 09:55:41 +0100
Subject: [PATCH 03/31] :sparkles: Add database for local usage
---
Sources/pom.xml | 5 +++++
Sources/src/main/kotlin/allin/entities/UserEntity.kt | 5 +++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/Sources/pom.xml b/Sources/pom.xml
index 0d8b30f..c569b14 100644
--- a/Sources/pom.xml
+++ b/Sources/pom.xml
@@ -32,6 +32,11 @@
ktor-server-core-jvm
${ktor_version}
+
+ org.postgresql
+ postgresql
+ 42.7.1
+
io.ktor
ktor-server-netty-jvm
diff --git a/Sources/src/main/kotlin/allin/entities/UserEntity.kt b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
index d8f0996..0500cf5 100644
--- a/Sources/src/main/kotlin/allin/entities/UserEntity.kt
+++ b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
@@ -1,11 +1,12 @@
package allin.entities
import org.ktorm.schema.Table
+import org.ktorm.schema.double
import org.ktorm.schema.int
import org.ktorm.schema.varchar
-
-object UserEntity : Table("user") {
+object UserEntity : Table("utilisateur") {
val id = int("id").primaryKey()
val username = varchar("username")
val password = varchar("password")
+ val nbCoins = double("nbCoins")
}
\ No newline at end of file
--
2.36.3
From aa938cbfb38e12fd6ab34de635bf38578c7ded5f Mon Sep 17 00:00:00 2001
From: luevard <99143550+saucepommefrite@users.noreply.github.com>
Date: Mon, 15 Jan 2024 13:34:26 +0100
Subject: [PATCH 04/31] :sparkles: Local Database link
---
Sources/src/main/kotlin/allin/dto/UserDTO.kt | 13 +---
.../main/kotlin/allin/entities/UserEntity.kt | 63 ++++++++++++++++++-
.../src/main/kotlin/allin/model/BetAction.kt | 0
Sources/src/main/kotlin/allin/model/User.kt | 2 +-
.../main/kotlin/allin/routing/BetRouter.kt | 11 ++--
.../main/kotlin/allin/routing/UserRouter.kt | 8 ++-
.../main/kotlin/allin/utils/CryptManager.kt | 16 +++--
.../main/kotlin/allin/utils/TokenManager.kt | 22 ++++++-
8 files changed, 106 insertions(+), 29 deletions(-)
create mode 100644 Sources/src/main/kotlin/allin/model/BetAction.kt
diff --git a/Sources/src/main/kotlin/allin/dto/UserDTO.kt b/Sources/src/main/kotlin/allin/dto/UserDTO.kt
index d59f39c..a440450 100644
--- a/Sources/src/main/kotlin/allin/dto/UserDTO.kt
+++ b/Sources/src/main/kotlin/allin/dto/UserDTO.kt
@@ -1,15 +1,4 @@
package allin.dto
-
-import allin.model.User
import kotlinx.serialization.Serializable
-
@Serializable
-data class UserDTO(val username: String,val email: String, val nbCoins: Int)
-@Serializable
-data class UserDTOWithToken(val username: String,val email: String, val nbCoins: Int, val token:String?)
-fun convertUserToUserDTO(user: User): UserDTO {
- return UserDTO(user.username, user.email, user.nbCoins)
-}
-fun convertUserToUserDTOToken(user: User): UserDTOWithToken {
- return UserDTOWithToken(user.username, user.email, user.nbCoins,user.token)
-}
+data class UserDTO(val username: String, val email: String, val nbCoins: Double, var token:String?)
diff --git a/Sources/src/main/kotlin/allin/entities/UserEntity.kt b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
index 0500cf5..e1ba032 100644
--- a/Sources/src/main/kotlin/allin/entities/UserEntity.kt
+++ b/Sources/src/main/kotlin/allin/entities/UserEntity.kt
@@ -1,12 +1,71 @@
package allin.entities
+import allin.dto.UserDTO
+import allin.model.User
+import allin.routing.database
+import org.ktorm.dsl.*
+import org.ktorm.entity.*
import org.ktorm.schema.Table
import org.ktorm.schema.double
import org.ktorm.schema.int
import org.ktorm.schema.varchar
-object UserEntity : Table("utilisateur") {
+
+interface UserEntity : Entity {
+ val username: String
+ var email: String
+ var password: String
+ var nbCoins: Double
+}
+object UsersEntity : Table("utilisateur") {
val id = int("id").primaryKey()
val username = varchar("username")
val password = varchar("password")
val nbCoins = double("nbCoins")
-}
\ No newline at end of file
+ val email = varchar("email")
+
+ fun getUserToUserDTO(): MutableList {
+ return database.from(UsersEntity).select().map {
+ row -> UserDTO(
+ row[username].toString(),
+ row[email].toString(),
+ row[nbCoins]?:0.0,
+ null
+ )
+ }.toMutableList()
+ }
+
+ fun getUserByUsernameAndPassword(login: String): Pair {
+ return database.from(UsersEntity)
+ .select()
+ .where { (username eq login) /*and (password eq passwordParam)*/ }
+ .map { row ->
+ Pair(
+ UserDTO(
+ row[username].toString(),
+ row[email].toString(),
+ row[nbCoins] ?: 0.0,
+ null
+ ),
+ row[password].toString()
+ )
+ }
+ .firstOrNull() ?: Pair(null, null)
+ }
+
+ fun addUserEntity(user : User){
+ database.insert(UsersEntity){
+ set(it.nbCoins,user.nbCoins)
+ set(it.username,user.username)
+ set(it.password,user.password)
+ set(it.email,user.email)
+ }
+ }
+ fun deleteUserByUsername(username: String): Boolean {
+ val deletedCount = database.delete(UsersEntity) {
+ it.username eq username
+ }
+ return deletedCount > 0
+ }
+}
+
+
diff --git a/Sources/src/main/kotlin/allin/model/BetAction.kt b/Sources/src/main/kotlin/allin/model/BetAction.kt
new file mode 100644
index 0000000..e69de29
diff --git a/Sources/src/main/kotlin/allin/model/User.kt b/Sources/src/main/kotlin/allin/model/User.kt
index 6234988..e368fec 100644
--- a/Sources/src/main/kotlin/allin/model/User.kt
+++ b/Sources/src/main/kotlin/allin/model/User.kt
@@ -8,7 +8,7 @@ data class User(
val username: String,
val email: String,
var password: String,
- var nbCoins: Int = 1000,
+ var nbCoins: Int = 500,
var token: String? = null
)
diff --git a/Sources/src/main/kotlin/allin/routing/BetRouter.kt b/Sources/src/main/kotlin/allin/routing/BetRouter.kt
index f55abde..fa1d210 100644
--- a/Sources/src/main/kotlin/allin/routing/BetRouter.kt
+++ b/Sources/src/main/kotlin/allin/routing/BetRouter.kt
@@ -1,11 +1,8 @@
package allin.routing
-
-import allin.ext.hasToken
-import allin.ext.verifyUserFromToken
-import allin.model.ApiMessage
-import allin.model.Bet
-import allin.model.BetWithoutId
-import allin.model.UpdatedBetData
+import io.ktor.server.application.*
+import io.ktor.server.request.*
+import io.ktor.server.routing.*
+import allin.model.*
import allin.utils.AppConfig
import io.ktor.http.*
import io.ktor.server.application.*
diff --git a/Sources/src/main/kotlin/allin/routing/UserRouter.kt b/Sources/src/main/kotlin/allin/routing/UserRouter.kt
index 5cf3ba3..e0e52b1 100644
--- a/Sources/src/main/kotlin/allin/routing/UserRouter.kt
+++ b/Sources/src/main/kotlin/allin/routing/UserRouter.kt
@@ -16,6 +16,7 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.util.*
+import org.ktorm.database.Database
val users = mutableListOf()
val RegexCheckerUser = AppConfig.regexChecker
@@ -23,6 +24,11 @@ val CryptManagerUser = AppConfig.cryptManager
val tokenManagerUser = AppConfig.tokenManager
const val DEFAULT_COINS = 500
+val RegexCheckerUser= AppConfig.regexChecker
+val CryptManagerUser= AppConfig.cryptManager
+val tokenManagerUser=AppConfig.tokenManager
+val database = Database.connect("jdbc:postgresql://localhost:5432/Allin", user = "postgres", password = "lulu")
+
fun Application.UserRouter() {
routing {
@@ -79,7 +85,7 @@ fun Application.UserRouter() {
}
}
}
-
+
get("/users/token") {
hasToken { principal ->
verifyUserFromToken(principal) { user ->
diff --git a/Sources/src/main/kotlin/allin/utils/CryptManager.kt b/Sources/src/main/kotlin/allin/utils/CryptManager.kt
index 216e733..df9f8be 100644
--- a/Sources/src/main/kotlin/allin/utils/CryptManager.kt
+++ b/Sources/src/main/kotlin/allin/utils/CryptManager.kt
@@ -4,12 +4,18 @@ import allin.model.User
import org.mindrot.jbcrypt.BCrypt
class CryptManager {
- val salt=BCrypt.gensalt()
+ //val salt=BCrypt.gensalt()
+ fun passwordCrypt(password : String): String {
+ return BCrypt.hashpw(password,"\$2a\$10\$42wsdBeoLKaF6SM9oADONe")
+ }
fun passwordCrypt(user: User){
- user.password=BCrypt.hashpw(user.password,salt)
-
+ user.password=BCrypt.hashpw(user.password,"\$2a\$10\$42wsdBeoLKaF6SM9oADONe")
}
- fun passwordDecrypt(user: User, password: String): Boolean{
- return BCrypt.hashpw(password,salt)==user.password
+ fun passwordDecrypt(password: String, passwordClear: String): Boolean{
+ return BCrypt.hashpw(passwordClear,"\$2a\$10\$42wsdBeoLKaF6SM9oADONe")==password
+ }
+
+ fun CheckPassword(hashed: String, clear: String): Boolean{
+ return BCrypt.checkpw(hashed,clear)
}
}
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/utils/TokenManager.kt b/Sources/src/main/kotlin/allin/utils/TokenManager.kt
index dbebe03..93b7e50 100644
--- a/Sources/src/main/kotlin/allin/utils/TokenManager.kt
+++ b/Sources/src/main/kotlin/allin/utils/TokenManager.kt
@@ -40,6 +40,26 @@ class TokenManager private constructor(val config: HoconApplicationConfig) {
}
}
+ fun generateOrReplaceJWTToken(user: UserDTO): String {
+ val userToken = getUserToken(user)
+ if (userToken != null && !isTokenExpired(userToken)) {
+ return userToken
+ } else {
+ return generateJWTToken(user)
+ }
+ }
+
+ fun generateJWTToken(user : UserDTO): String {
+ val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde
+ val token = JWT.create()
+ .withAudience(audience)
+ .withIssuer(issuer)
+ .withClaim("username", user.username)
+ .withExpiresAt(Date(expirationDate))
+ .sign(Algorithm.HMAC256(secret))
+ return token
+ }
+
fun isTokenExpired(token: String): Boolean {
val expirationTime = JWT.decode(token).expiresAt.time
return System.currentTimeMillis() > expirationTime
@@ -49,7 +69,7 @@ class TokenManager private constructor(val config: HoconApplicationConfig) {
return user.token
}
- fun getUsernameFromToken(token: String): String {
+ fun getUsernameFromToken(token: String) : String{
val decodedJWT: DecodedJWT = JWT.decode(token)
return decodedJWT.getClaim("username").asString()
}
--
2.36.3
From b4ac31431d4d249625a6cc9c622cf17ec68e74f5 Mon Sep 17 00:00:00 2001
From: "arthur.valin"
Date: Mon, 15 Jan 2024 16:58:59 +0100
Subject: [PATCH 05/31] Start bet participations and refactoring
---
.gitignore | 2 +-
.../kotlin/allin/ext/PipelineContextExt.kt | 9 ++--
.../src/main/kotlin/allin/model/ApiMessage.kt | 1 +
.../main/kotlin/allin/routing/BetRouter.kt | 24 +++++++--
.../allin/routing/ParticipationRouter.kt | 6 +--
.../main/kotlin/allin/routing/UserRouter.kt | 51 +++++++++---------
.../main/kotlin/allin/utils/TokenManager.kt | 21 ++++----
.../classes/META-INF/allin-api.kotlin_module | Bin 132 -> 0 bytes
.../allin/ApplicationKt$extracted$1$1$1.class | Bin 4041 -> 0 bytes
.../allin/ApplicationKt$extracted$1$1.class | Bin 2618 -> 0 bytes
.../allin/ApplicationKt$extracted$1.class | Bin 2007 -> 0 bytes
.../allin/ApplicationKt$extracted$2.class | Bin 1928 -> 0 bytes
.../classes/allin/ApplicationKt$main$1.class | Bin 1543 -> 0 bytes
.../target/classes/allin/ApplicationKt.class | Bin 3163 -> 0 bytes
.../allin/dto/UserDTO$$serializer.class | Bin 5508 -> 0 bytes
.../classes/allin/dto/UserDTO$Companion.class | Bin 1275 -> 0 bytes
.../target/classes/allin/dto/UserDTO.class | Bin 5137 -> 0 bytes
.../target/classes/allin/dto/UserDTOKt.class | Bin 1390 -> 0 bytes
.../dto/UserDTOWithToken$$serializer.class | Bin 6120 -> 0 bytes
.../dto/UserDTOWithToken$Companion.class | Bin 1338 -> 0 bytes
.../classes/allin/dto/UserDTOWithToken.class | Bin 6105 -> 0 bytes
.../classes/allin/entities/UserEntity.class | Bin 2022 -> 0 bytes
.../classes/allin/model/Bet$$serializer.class | Bin 6534 -> 0 bytes
.../classes/allin/model/Bet$Companion.class | Bin 1257 -> 0 bytes
Sources/target/classes/allin/model/Bet.class | Bin 9414 -> 0 bytes
.../allin/model/CheckUser$$serializer.class | Bin 5271 -> 0 bytes
.../allin/model/CheckUser$Companion.class | Bin 1300 -> 0 bytes
.../classes/allin/model/CheckUser.class | Bin 4635 -> 0 bytes
.../model/UpdatedBetData$$serializer.class | Bin 6054 -> 0 bytes
.../model/UpdatedBetData$Companion.class | Bin 1334 -> 0 bytes
.../classes/allin/model/UpdatedBetData.class | Bin 7171 -> 0 bytes
.../allin/model/User$$serializer.class | Bin 6119 -> 0 bytes
.../classes/allin/model/User$Companion.class | Bin 1265 -> 0 bytes
Sources/target/classes/allin/model/User.class | Bin 7414 -> 0 bytes
.../BasicRoutingKt$BasicRouting$1$1.class | Bin 6007 -> 0 bytes
.../BasicRoutingKt$BasicRouting$1.class | Bin 1950 -> 0 bytes
.../allin/routing/BasicRoutingKt.class | Bin 1144 -> 0 bytes
.../routing/BetRouterKt$BetRouter$1$1$1.class | Bin 9372 -> 0 bytes
.../routing/BetRouterKt$BetRouter$1$1.class | Bin 1856 -> 0 bytes
.../routing/BetRouterKt$BetRouter$1$2$1.class | Bin 10482 -> 0 bytes
.../routing/BetRouterKt$BetRouter$1$2.class | Bin 1856 -> 0 bytes
.../routing/BetRouterKt$BetRouter$1$3$1.class | Bin 9610 -> 0 bytes
.../routing/BetRouterKt$BetRouter$1$3.class | Bin 1856 -> 0 bytes
.../routing/BetRouterKt$BetRouter$1.class | Bin 2187 -> 0 bytes
.../classes/allin/routing/BetRouterKt.class | Bin 1608 -> 0 bytes
.../UserRouterKt$UserRouter$1$1$1.class | Bin 10934 -> 0 bytes
.../routing/UserRouterKt$UserRouter$1$1.class | Bin 1865 -> 0 bytes
.../UserRouterKt$UserRouter$1$2$1.class | Bin 10232 -> 0 bytes
.../routing/UserRouterKt$UserRouter$1$2.class | Bin 1865 -> 0 bytes
.../UserRouterKt$UserRouter$1$3$1.class | Bin 9933 -> 0 bytes
.../routing/UserRouterKt$UserRouter$1$3.class | Bin 1865 -> 0 bytes
.../UserRouterKt$UserRouter$1$4$1.class | Bin 9821 -> 0 bytes
.../routing/UserRouterKt$UserRouter$1$4.class | Bin 1909 -> 0 bytes
.../routing/UserRouterKt$UserRouter$1.class | Bin 2570 -> 0 bytes
.../classes/allin/routing/UserRouterKt.class | Bin 2733 -> 0 bytes
.../allin/serializer/DateSerializer.class | Bin 3623 -> 0 bytes
.../classes/allin/utils/CryptManager.class | Bin 1717 -> 0 bytes
.../classes/allin/utils/RegexChecker.class | Bin 1249 -> 0 bytes
.../classes/allin/utils/TokenManager.class | Bin 4571 -> 0 bytes
Sources/target/classes/application.conf | 4 --
Sources/target/classes/logback.xml | 12 -----
.../META-INF/allin-api.kotlin_module | Bin 24 -> 0 bytes
.../test-classes/allin/ApplicationTest.class | Bin 486 -> 0 bytes
63 files changed, 67 insertions(+), 63 deletions(-)
delete mode 100644 Sources/target/classes/META-INF/allin-api.kotlin_module
delete mode 100644 Sources/target/classes/allin/ApplicationKt$extracted$1$1$1.class
delete mode 100644 Sources/target/classes/allin/ApplicationKt$extracted$1$1.class
delete mode 100644 Sources/target/classes/allin/ApplicationKt$extracted$1.class
delete mode 100644 Sources/target/classes/allin/ApplicationKt$extracted$2.class
delete mode 100644 Sources/target/classes/allin/ApplicationKt$main$1.class
delete mode 100644 Sources/target/classes/allin/ApplicationKt.class
delete mode 100644 Sources/target/classes/allin/dto/UserDTO$$serializer.class
delete mode 100644 Sources/target/classes/allin/dto/UserDTO$Companion.class
delete mode 100644 Sources/target/classes/allin/dto/UserDTO.class
delete mode 100644 Sources/target/classes/allin/dto/UserDTOKt.class
delete mode 100644 Sources/target/classes/allin/dto/UserDTOWithToken$$serializer.class
delete mode 100644 Sources/target/classes/allin/dto/UserDTOWithToken$Companion.class
delete mode 100644 Sources/target/classes/allin/dto/UserDTOWithToken.class
delete mode 100644 Sources/target/classes/allin/entities/UserEntity.class
delete mode 100644 Sources/target/classes/allin/model/Bet$$serializer.class
delete mode 100644 Sources/target/classes/allin/model/Bet$Companion.class
delete mode 100644 Sources/target/classes/allin/model/Bet.class
delete mode 100644 Sources/target/classes/allin/model/CheckUser$$serializer.class
delete mode 100644 Sources/target/classes/allin/model/CheckUser$Companion.class
delete mode 100644 Sources/target/classes/allin/model/CheckUser.class
delete mode 100644 Sources/target/classes/allin/model/UpdatedBetData$$serializer.class
delete mode 100644 Sources/target/classes/allin/model/UpdatedBetData$Companion.class
delete mode 100644 Sources/target/classes/allin/model/UpdatedBetData.class
delete mode 100644 Sources/target/classes/allin/model/User$$serializer.class
delete mode 100644 Sources/target/classes/allin/model/User$Companion.class
delete mode 100644 Sources/target/classes/allin/model/User.class
delete mode 100644 Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1$1.class
delete mode 100644 Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1.class
delete mode 100644 Sources/target/classes/allin/routing/BasicRoutingKt.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1$1.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2$1.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3$1.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1.class
delete mode 100644 Sources/target/classes/allin/routing/BetRouterKt.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1$1.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2$1.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3$1.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4$1.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1.class
delete mode 100644 Sources/target/classes/allin/routing/UserRouterKt.class
delete mode 100644 Sources/target/classes/allin/serializer/DateSerializer.class
delete mode 100644 Sources/target/classes/allin/utils/CryptManager.class
delete mode 100644 Sources/target/classes/allin/utils/RegexChecker.class
delete mode 100644 Sources/target/classes/allin/utils/TokenManager.class
delete mode 100644 Sources/target/classes/application.conf
delete mode 100644 Sources/target/classes/logback.xml
delete mode 100644 Sources/target/test-classes/META-INF/allin-api.kotlin_module
delete mode 100644 Sources/target/test-classes/allin/ApplicationTest.class
diff --git a/.gitignore b/.gitignore
index f0d8881..b3f8ec6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,4 +35,4 @@ out/
### VS Code ###
.vscode/
-**/src/target/**
\ No newline at end of file
+!**/src/target/**
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/ext/PipelineContextExt.kt b/Sources/src/main/kotlin/allin/ext/PipelineContextExt.kt
index 0d9cfd9..e111f9b 100644
--- a/Sources/src/main/kotlin/allin/ext/PipelineContextExt.kt
+++ b/Sources/src/main/kotlin/allin/ext/PipelineContextExt.kt
@@ -1,8 +1,8 @@
package allin.ext
+import allin.dto.UserDTO
+import allin.entities.UsersEntity
import allin.model.ApiMessage
-import allin.model.User
-import allin.routing.users
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
@@ -15,9 +15,10 @@ suspend fun PipelineContext<*, ApplicationCall>.hasToken(content: suspend (princ
suspend fun PipelineContext<*, ApplicationCall>.verifyUserFromToken(
principal: JWTPrincipal,
- content: suspend (user: User) -> Unit
+ content: suspend (user: UserDTO, password: String) -> Unit
) {
val username = principal.payload.getClaim("username").asString()
- users.find { it.username == username }?.let { content(it) }
+ val userPassword = UsersEntity.getUserByUsernameAndPassword(username)
+ userPassword.first?.let { content(it, userPassword.second ?: "") }
?: call.respond(HttpStatusCode.NotFound, ApiMessage.TokenUserNotFound)
}
\ No newline at end of file
diff --git a/Sources/src/main/kotlin/allin/model/ApiMessage.kt b/Sources/src/main/kotlin/allin/model/ApiMessage.kt
index deaa55f..9f47ea3 100644
--- a/Sources/src/main/kotlin/allin/model/ApiMessage.kt
+++ b/Sources/src/main/kotlin/allin/model/ApiMessage.kt
@@ -3,6 +3,7 @@ package allin.model
object ApiMessage {
const val Welcome = "Welcome on AllIn's API !"
const val TokenUserNotFound = "User not found with the valid token !"
+ const val UserNotFound = "User not found."
const val BetNotFound = "Bet not found."
const val BetAlreadyExist = "Bet already exists."
const val IncorrectLoginPassword = "Login and/or password incorrect."
diff --git a/Sources/src/main/kotlin/allin/routing/BetRouter.kt b/Sources/src/main/kotlin/allin/routing/BetRouter.kt
index fa1d210..6d7cb79 100644
--- a/Sources/src/main/kotlin/allin/routing/BetRouter.kt
+++ b/Sources/src/main/kotlin/allin/routing/BetRouter.kt
@@ -1,8 +1,11 @@
package allin.routing
-import io.ktor.server.application.*
-import io.ktor.server.request.*
-import io.ktor.server.routing.*
-import allin.model.*
+
+import allin.ext.hasToken
+import allin.ext.verifyUserFromToken
+import allin.model.ApiMessage
+import allin.model.Bet
+import allin.model.BetWithoutId
+import allin.model.UpdatedBetData
import allin.utils.AppConfig
import io.ktor.http.*
import io.ktor.server.application.*
@@ -40,6 +43,7 @@ fun Application.BetRouter() {
}
}
}
+
route("/bets/gets") {
get {
// if(bets.size>0)
@@ -47,6 +51,16 @@ fun Application.BetRouter() {
// else call.respond(HttpStatusCode.NoContent)
}
}
+
+ route("/bets/get/{id}") {
+ get {
+ val id = call.parameters["id"] ?: ""
+ bets.find { it.id == id }?.let { bet ->
+ call.respond(HttpStatusCode.Accepted, bet)
+ } ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound)
+ }
+ }
+
route("/bets/delete") {
post {
val idbet = call.receive