diff --git a/Sources/src/main/kotlin/allin/Application.kt b/Sources/src/main/kotlin/allin/Application.kt index e35782f..826268a 100644 --- a/Sources/src/main/kotlin/allin/Application.kt +++ b/Sources/src/main/kotlin/allin/Application.kt @@ -1,5 +1,8 @@ package allin +import allin.entities.BetEntity +import allin.entities.BetsEntity +import allin.entities.ResponsesEntity import allin.entities.UsersEntity import allin.routing.BasicRouting import allin.routing.BetRouter @@ -52,4 +55,6 @@ private fun Application.extracted() { BetRouter() ParticipationRouter() UsersEntity.createUserTable() + BetsEntity.createBetsTable() + ResponsesEntity.createResponseTable() } diff --git a/Sources/src/main/kotlin/allin/dto/UserDTO.kt b/Sources/src/main/kotlin/allin/dto/UserDTO.kt index a440450..c0bec1d 100644 --- a/Sources/src/main/kotlin/allin/dto/UserDTO.kt +++ b/Sources/src/main/kotlin/allin/dto/UserDTO.kt @@ -1,4 +1,4 @@ package allin.dto import kotlinx.serialization.Serializable @Serializable -data class UserDTO(val username: String, val email: String, val nbCoins: Double, var token:String?) +data class UserDTO(val id: String, val username: String, val email: String, val nbCoins: Double, var token:String?) diff --git a/Sources/src/main/kotlin/allin/entities/BetEntity.kt b/Sources/src/main/kotlin/allin/entities/BetEntity.kt new file mode 100644 index 0000000..c4b7cf3 --- /dev/null +++ b/Sources/src/main/kotlin/allin/entities/BetEntity.kt @@ -0,0 +1,65 @@ +package allin.entities + +import allin.database +import allin.entities.ResponsesEntity.getResponse +import allin.model.Bet +import allin.utils.Execute +import org.ktorm.dsl.* +import org.ktorm.entity.Entity +import org.ktorm.schema.* +import java.time.ZoneId +import java.time.ZonedDateTime +import java.util.UUID.fromString + + +interface BetEntity : Entity { + val theme: String + val sentenceBet: String + val endRegistration: ZonedDateTime + val endBet: ZonedDateTime + val isPrivate: Boolean + val createdBy: String +} + +object BetsEntity : Table("bet") { + val id = uuid("id").primaryKey() + val theme = varchar("theme") + val sentenceBet = varchar("sentencebet") + val endRegistration = timestamp("endregistration") + val endBet = timestamp("endbet") + val isPrivate = boolean("isprivate") + val createdBy = varchar("createdby") + + fun getBets(): MutableList { + return database.from(BetsEntity).select().map { + row -> Bet( + row[id].toString(), + row[theme].toString(), + row[sentenceBet].toString(), + row[endRegistration]!!.atZone(ZoneId.of("Europe/Paris")), + row[endBet]!!.atZone(ZoneId.of("Europe/Paris")), + row[isPrivate]?: false, + getResponse(fromString(row[id].toString())), + row[createdBy].toString() + ) + }.toMutableList() + } + + fun createBetsTable(){ + val request="CREATE TABLE IF not exists bet ( id uuid PRIMARY KEY, theme VARCHAR(255), endregistration timestamp,endbet timestamp,sentencebet varchar(500),isprivate boolean, createdby varchar(250))" + database.Execute(request) + } + + fun addBetEntity(bet : Bet) { + database.insert(BetsEntity) { + set(it.id, fromString(bet.id)) + set(it.endBet,bet.endBet.toInstant()) + set(it.endRegistration,bet.endRegistration.toInstant()) + set(it.sentenceBet,bet.sentenceBet) + set(it.theme, bet.theme) + set(it.isPrivate, bet.isPrivate) + set(it.createdBy, bet.createdBy) + } + ResponsesEntity.addResponse(bet.response,fromString(bet.id)) + } +} \ No newline at end of file diff --git a/Sources/src/main/kotlin/allin/entities/ResponseEntity.kt b/Sources/src/main/kotlin/allin/entities/ResponseEntity.kt new file mode 100644 index 0000000..c029a5e --- /dev/null +++ b/Sources/src/main/kotlin/allin/entities/ResponseEntity.kt @@ -0,0 +1,41 @@ +package allin.entities + +import allin.database +import allin.utils.Execute +import org.ktorm.dsl.* +import org.ktorm.entity.Entity +import org.ktorm.schema.Table +import org.ktorm.schema.uuid +import org.ktorm.schema.varchar +import java.util.* + + +interface ResponseEntity : Entity { + val betId: UUID + val response: String +} + +object ResponsesEntity : Table("response") { + val id = uuid("id").primaryKey() + val response = varchar("response").primaryKey() + fun createResponseTable(){ + val request="CREATE TABLE IF NOT EXISTS response (id UUID,response VARCHAR(250),CONSTRAINT pk_response_id PRIMARY KEY (id,response));" + database.Execute(request) + } + + fun getResponse(idBet: UUID): MutableList { + return database.from(ResponsesEntity) + .select(response) + .where { id eq idBet } + .map { it[response].toString() }.toMutableList() + } + + fun addResponse(responses : MutableList, idBet : UUID ) { + responses.forEach {selected -> + database.insert(ResponsesEntity) { + set(it.id, idBet) + set(it.response,selected) + } + } + } +} diff --git a/Sources/src/main/kotlin/allin/entities/UserEntity.kt b/Sources/src/main/kotlin/allin/entities/UserEntity.kt index 21df0cb..9a1bcfc 100644 --- a/Sources/src/main/kotlin/allin/entities/UserEntity.kt +++ b/Sources/src/main/kotlin/allin/entities/UserEntity.kt @@ -6,10 +6,9 @@ import allin.model.User import allin.utils.Execute 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 +import org.ktorm.schema.* +import java.util.* +import java.util.UUID.fromString interface UserEntity : Entity { val username: String @@ -18,7 +17,7 @@ interface UserEntity : Entity { var nbCoins: Double } object UsersEntity : Table("utilisateur") { - val id = int("id").primaryKey() + val id = uuid("id").primaryKey() val username = varchar("username") val password = varchar("password") val nbCoins = double("coins") @@ -27,6 +26,7 @@ object UsersEntity : Table("utilisateur") { fun getUserToUserDTO(): MutableList { return database.from(UsersEntity).select().map { row -> UserDTO( + row[id].toString(), row[username].toString(), row[email].toString(), row[nbCoins]?:0.0, @@ -36,7 +36,7 @@ object UsersEntity : Table("utilisateur") { } fun createUserTable(){ - val request="CREATE TABLE IF not exists utilisateur ( id SERIAL PRIMARY KEY, username VARCHAR(255), password VARCHAR(255),coins double precision,email VARCHAR(255))" + val request="CREATE TABLE IF not exists utilisateur ( id uuid PRIMARY KEY, username VARCHAR(255), password VARCHAR(255),coins double precision,email VARCHAR(255))" database.Execute(request) } @@ -48,6 +48,7 @@ object UsersEntity : Table("utilisateur") { .map { row -> Pair( UserDTO( + row[id].toString(), row[username].toString(), row[email].toString(), row[nbCoins] ?: 0.0, @@ -61,6 +62,7 @@ object UsersEntity : Table("utilisateur") { fun addUserEntity(user : User){ database.insert(UsersEntity){ + set(it.id,fromString(user.id)) set(it.nbCoins,user.nbCoins) set(it.username,user.username) set(it.password,user.password) diff --git a/Sources/src/main/kotlin/allin/model/Bet.kt b/Sources/src/main/kotlin/allin/model/Bet.kt index 16d7bb1..e088e2b 100644 --- a/Sources/src/main/kotlin/allin/model/Bet.kt +++ b/Sources/src/main/kotlin/allin/model/Bet.kt @@ -1,19 +1,21 @@ package allin.model +import allin.serializer.UUIDSerializer import allin.serializer.ZonedDateTimeSerializer import kotlinx.serialization.Serializable import java.time.ZonedDateTime +import java.util.* @Serializable data class Bet( - val id: String, + val id: String = "", val theme: String, val sentenceBet: String, @Serializable(ZonedDateTimeSerializer::class) val endRegistration: ZonedDateTime, @Serializable(ZonedDateTimeSerializer::class) var endBet: ZonedDateTime, var isPrivate: Boolean, var response: MutableList, - val createdBy: String + val createdBy: String = "" ) @Serializable @@ -22,15 +24,4 @@ data class UpdatedBetData( @Serializable(ZonedDateTimeSerializer::class) val endBet: ZonedDateTime, val isPrivate: Boolean, val response: MutableList -) - -@Serializable -data class BetWithoutId( - val theme: String, - val sentenceBet: String, - @Serializable(ZonedDateTimeSerializer::class) val endRegistration: ZonedDateTime, - @Serializable(ZonedDateTimeSerializer::class) var endBet: ZonedDateTime, - var isPrivate: Boolean, - var response: MutableList, - val createdBy: String ) \ 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 ac0122e..70a74be 100644 --- a/Sources/src/main/kotlin/allin/model/User.kt +++ b/Sources/src/main/kotlin/allin/model/User.kt @@ -1,4 +1,4 @@ -package allin.model + package allin.model import kotlinx.serialization.Serializable diff --git a/Sources/src/main/kotlin/allin/routing/BetRouter.kt b/Sources/src/main/kotlin/allin/routing/BetRouter.kt index e54e685..619cb55 100644 --- a/Sources/src/main/kotlin/allin/routing/BetRouter.kt +++ b/Sources/src/main/kotlin/allin/routing/BetRouter.kt @@ -1,5 +1,7 @@ package allin.routing +import allin.entities.BetsEntity.addBetEntity +import allin.entities.BetsEntity.getBets import allin.ext.hasToken import allin.ext.verifyUserFromToken import allin.model.ApiMessage @@ -14,16 +16,19 @@ import io.ktor.server.response.* import io.ktor.server.routing.* import java.util.* -val bets = mutableListOf() +//val bets = mutableListOf() val tokenManagerBet = AppConfig.tokenManager fun Application.BetRouter() { routing { route("/bets/add") { + authenticate { post { + hasToken { principal -> val bet = call.receive() val id = UUID.randomUUID().toString() - val username = tokenManagerBet.getUsernameFromToken(bet.createdBy) + val username = tokenManagerBet.getUsernameFromToken(principal) + val bets = getBets() bets.find { it.id == id }?.let { call.respond(HttpStatusCode.Conflict, ApiMessage.BetAlreadyExist) } ?: run { @@ -37,15 +42,21 @@ fun Application.BetRouter() { bet.response, username ) - bets.add(betWithId) + //bets.add(betWithId) + addBetEntity(betWithId) call.respond(HttpStatusCode.Created, betWithId) } + } + + } + } } route("/bets/gets") { get { // if(bets.size>0) + val bets= getBets() call.respond(HttpStatusCode.Accepted, bets.toList()) // else call.respond(HttpStatusCode.NoContent) } @@ -53,6 +64,7 @@ fun Application.BetRouter() { route("/bets/get/{id}") { get { + val bets= getBets() val id = call.parameters["id"] ?: "" bets.find { it.id == id }?.let { bet -> call.respond(HttpStatusCode.Accepted, bet) @@ -63,6 +75,7 @@ fun Application.BetRouter() { route("/bets/delete") { post { val idbet = call.receive>()["id"] + val bets= getBets() bets.find { it.id == idbet }?.let { findbet -> bets.remove(findbet) call.respond(HttpStatusCode.Accepted, findbet) @@ -72,6 +85,7 @@ fun Application.BetRouter() { route("bets/update") { post { val updatedBetData = call.receive() + val bets= getBets() bets.find { it.id == updatedBetData.id }?.let { findbet -> findbet.endBet = updatedBetData.endBet findbet.isPrivate = updatedBetData.isPrivate @@ -83,6 +97,7 @@ fun Application.BetRouter() { authenticate { get("/bets/current") { + val bets= getBets() hasToken { principal -> verifyUserFromToken(principal) { user, _ -> val bets = participations diff --git a/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt b/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt index dc84760..febe993 100644 --- a/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt +++ b/Sources/src/main/kotlin/allin/serializer/DateSerializer.kt @@ -1,17 +1,22 @@ package allin.serializer -import kotlinx.serialization.* +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder +import java.sql.Timestamp +import java.time.Instant +import java.time.ZoneId import java.time.ZonedDateTime import java.time.format.DateTimeFormatter + @Serializer(ZonedDateTime::class) object ZonedDateTimeSerializer : KSerializer { - private val formatter: DateTimeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME + private val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z") override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ZonedDateTime", PrimitiveKind.STRING) diff --git a/Sources/src/main/kotlin/allin/serializer/UUIDSerializer.kt b/Sources/src/main/kotlin/allin/serializer/UUIDSerializer.kt new file mode 100644 index 0000000..4bd17fb --- /dev/null +++ b/Sources/src/main/kotlin/allin/serializer/UUIDSerializer.kt @@ -0,0 +1,20 @@ +package allin.serializer + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import java.util.* + +object UUIDSerializer : KSerializer { + override val descriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): UUID { + return UUID.fromString(decoder.decodeString()) + } + + override fun serialize(encoder: Encoder, value: UUID) { + encoder.encodeString(value.toString()) + } +} \ 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 9a34cc9..7f8d7fa 100644 --- a/Sources/src/main/kotlin/allin/utils/CryptManager.kt +++ b/Sources/src/main/kotlin/allin/utils/CryptManager.kt @@ -18,7 +18,6 @@ class CryptManager { return BCrypt.hashpw(password,salt) } fun passwordCrypt(user: User){ - println(salt) user.password=BCrypt.hashpw(user.password,salt) } fun passwordDecrypt(password: String, passwordClear: String): Boolean{ diff --git a/Sources/src/main/kotlin/allin/utils/TokenManager.kt b/Sources/src/main/kotlin/allin/utils/TokenManager.kt index 86f2073..0034ad8 100644 --- a/Sources/src/main/kotlin/allin/utils/TokenManager.kt +++ b/Sources/src/main/kotlin/allin/utils/TokenManager.kt @@ -6,6 +6,7 @@ import com.auth0.jwt.JWT import com.auth0.jwt.JWTVerifier import com.auth0.jwt.algorithms.Algorithm import com.auth0.jwt.interfaces.DecodedJWT +import io.ktor.server.auth.jwt.* import io.ktor.server.config.* import java.util.* @@ -70,9 +71,8 @@ class TokenManager private constructor(val config: HoconApplicationConfig) { fun getUserToken(user: User): String? = user.token fun getUserToken(user: UserDTO): String? = user.token - fun getUsernameFromToken(token: String): String { - val decodedJWT: DecodedJWT = JWT.decode(token) - return decodedJWT.getClaim("username").asString() + fun getUsernameFromToken(principal: JWTPrincipal): String { + return principal.payload.getClaim("username").asString() } companion object {