Merge branch 'Stub_Db'

# Conflicts:
#	Sources/src/main/kotlin/allin/entities/UserEntity.kt
#	Sources/src/main/kotlin/allin/routing/UserRouter.kt
pull/10/head
Arthur VALIN 1 year ago
commit a877762d2d

@ -52,7 +52,7 @@ steps:
IMAGENAME: postgres:latest IMAGENAME: postgres:latest
CONTAINERNAME: postgresapi CONTAINERNAME: postgresapi
COMMAND: create COMMAND: create
OVERWRITE: false OVERWRITE: true
PRIVATE: false PRIVATE: false
ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_ROOT_PASSWORD: CODEFIRST_CLIENTDRONE_ENV_POSTGRES_ROOT_PASSWORD:

2
.gitignore vendored

@ -36,3 +36,5 @@ out/
.vscode/ .vscode/
!**/src/target/** !**/src/target/**
**/src/target/**
/src/target

@ -47,6 +47,11 @@
<artifactId>ktorm-core</artifactId> <artifactId>ktorm-core</artifactId>
<version>3.2.0</version> <version>3.2.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.ktorm</groupId>
<artifactId>ktorm-support-postgresql</artifactId>
<version>3.2.0</version>
</dependency>
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId> <artifactId>logback-classic</artifactId>

@ -1,8 +1,11 @@
package allin package allin
import allin.entities.* import allin.data.AllInDataSource
import allin.data.mock.MockDataSource
import allin.data.postgres.PostgresDataSource
import allin.routing.* import allin.routing.*
import allin.utils.* import allin.utils.TokenManager
import allin.utils.kronJob
import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigFactory
import io.ktor.serialization.kotlinx.json.* import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.* import io.ktor.server.application.*
@ -12,14 +15,23 @@ import io.ktor.server.config.*
import io.ktor.server.engine.* import io.ktor.server.engine.*
import io.ktor.server.netty.* import io.ktor.server.netty.*
import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.plugins.contentnegotiation.*
import org.ktorm.database.Database import java.time.ZonedDateTime
import kotlin.time.ExperimentalTime
import kotlin.time.minutes
val db_database=System.getenv().get("POSTGRES_DB") @ExperimentalTime
val db_user=System.getenv().get("POSTGRES_USER") val BET_VERIFY_DELAY = 1.minutes
val db_password=System.getenv().get("POSTGRES_PASSWORD")
val db_host=System.getenv().get("POSTGRES_HOST") val data_source = System.getenv()["DATA_SOURCE"]
private val allInDataSource: AllInDataSource = when (data_source) {
"mock" -> MockDataSource()
"postgres" -> PostgresDataSource()
else -> MockDataSource()
}
val Application.dataSource: AllInDataSource
get() = allInDataSource
val database = Database.connect("jdbc:postgresql://$db_host/$db_database", user = db_user, password = db_password)
fun main() { fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") { embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
@ -27,6 +39,7 @@ fun main() {
}.start(wait = true) }.start(wait = true)
} }
@OptIn(ExperimentalTime::class)
private fun Application.extracted() { private fun Application.extracted() {
val config = HoconApplicationConfig(ConfigFactory.load()) val config = HoconApplicationConfig(ConfigFactory.load())
val tokenManager = TokenManager.getInstance(config) val tokenManager = TokenManager.getInstance(config)
@ -41,16 +54,15 @@ private fun Application.extracted() {
} }
} }
} }
install(ContentNegotiation) { install(ContentNegotiation) { json() }
json()
}
BasicRouting() BasicRouting()
UserRouter() UserRouter()
BetRouter() BetRouter()
ParticipationRouter() ParticipationRouter()
BetDetailRouter() BetDetailRouter()
UsersEntity.createUserTable()
BetsEntity.createBetsTable() kronJob(BET_VERIFY_DELAY) {
ResponsesEntity.createResponseTable() dataSource.betDataSource.updateBetStatuses(ZonedDateTime.now())
ParticipationsEntity.createParticipationTable() }
} }

@ -0,0 +1,12 @@
package allin.data
abstract class AllInDataSource {
abstract val userDataSource: UserDataSource
abstract val betDataSource: BetDataSource
abstract val participationDataSource: ParticipationDataSource
}

@ -0,0 +1,15 @@
package allin.data
import allin.model.Bet
import allin.model.UpdatedBetData
import java.time.ZonedDateTime
interface BetDataSource {
fun getAllBets(): List<Bet>
fun getBetById(id: String): Bet?
fun getBetsNotFinished(): List<Bet>
fun addBet(bet: Bet)
fun removeBet(id: String): Boolean
fun updateBet(data: UpdatedBetData): Boolean
fun updateBetStatuses(date: ZonedDateTime)
}

@ -0,0 +1,18 @@
package allin.data
import allin.model.Participation
interface ParticipationDataSource {
fun addParticipation(participation: Participation)
fun getParticipationFromBetId(betid: String): List<Participation>
fun getParticipationFromUserId(username: String, betid: String): List<Participation>
fun deleteParticipation(id: String): Boolean
}

@ -0,0 +1,21 @@
package allin.data
import allin.dto.UserDTO
import allin.model.User
interface UserDataSource {
fun getUserByUsername(username: String): Pair<UserDTO?, String?>
fun addUser(user: User)
fun deleteUser(username: String): Boolean
fun modifyUserCoins(username: String, amount: Int)
fun userExists(username: String, email: String): Boolean
}

@ -0,0 +1,44 @@
package allin.data.mock
import allin.data.BetDataSource
import allin.model.Bet
import allin.model.BetStatus
import allin.model.UpdatedBetData
import java.time.ZonedDateTime
class MockBetDataSource : BetDataSource {
override fun getAllBets(): List<Bet> = bets
override fun getBetById(id: String): Bet? =
bets.find { it.id == id }
override fun removeBet(id: String): Boolean =
bets.removeIf { it.id == id }
override fun updateBet(data: UpdatedBetData): Boolean {
return bets.find { it.id == data.id }?.let {
it.isPrivate = data.isPrivate
} != null
}
override fun getBetsNotFinished(): List<Bet> =
bets.filter { it.endBet >= ZonedDateTime.now() }
override fun addBet(bet: Bet) {
bets += bet
}
override fun updateBetStatuses(date: ZonedDateTime) {
bets.forEachIndexed { idx, bet ->
if (date >= bet.endRegistration) {
if (date >= bet.endBet) {
bets[idx] = bet.copy(status = BetStatus.WAITING)
} else {
bets[idx] = bet.copy(status = BetStatus.CLOSING)
}
}
}
}
private val bets by lazy { mutableListOf<Bet>() }
}

@ -0,0 +1,12 @@
package allin.data.mock
import allin.data.AllInDataSource
import allin.data.BetDataSource
import allin.data.ParticipationDataSource
import allin.data.UserDataSource
class MockDataSource : AllInDataSource() {
override val userDataSource: UserDataSource = MockUserDataSource()
override val betDataSource: BetDataSource = MockBetDataSource()
override val participationDataSource: ParticipationDataSource = MockParticipationDataSource()
}

@ -0,0 +1,22 @@
package allin.data.mock
import allin.data.ParticipationDataSource
import allin.model.Participation
class MockParticipationDataSource : ParticipationDataSource {
override fun addParticipation(participation: Participation) {
participations += participations
}
override fun getParticipationFromBetId(betid: String): List<Participation> =
participations.filter { it.betId == betid }
override fun getParticipationFromUserId(username: String, betid: String): List<Participation> =
participations.filter { it.betId == betid && it.username == username }
override fun deleteParticipation(id: String): Boolean =
participations.removeIf { it.id == id }
private val participations by lazy { mutableListOf<Participation>() }
}

@ -0,0 +1,41 @@
package allin.data.mock
import allin.data.UserDataSource
import allin.dto.UserDTO
import allin.model.User
class MockUserDataSource : UserDataSource {
override fun getUserByUsername(username: String): Pair<UserDTO?, String?> =
users.find { it.username == username }?.let {
Pair(
UserDTO(
id = it.id,
username = it.username,
email = it.email,
nbCoins = it.nbCoins,
token = it.token
),
it.password
)
} ?: Pair(null, null)
override fun addUser(user: User) {
users += user
}
override fun deleteUser(username: String): Boolean =
users.removeIf { it.username == username }
override fun modifyUserCoins(username: String, amount: Int) {
users.find { it.username == username }?.let {
it.nbCoins += amount
}
}
override fun userExists(username: String, email: String): Boolean =
users.any { it.username == username && it.email == email }
private val users by lazy {
mutableListOf<User>()
}
}

@ -0,0 +1,115 @@
package allin.data.postgres
import allin.data.BetDataSource
import allin.entities.BetsEntity
import allin.entities.NO_VALUE
import allin.entities.ResponsesEntity
import allin.entities.ResponsesEntity.response
import allin.entities.YES_VALUE
import allin.model.Bet
import allin.model.BetStatus
import allin.model.BetType
import allin.model.UpdatedBetData
import org.ktorm.database.Database
import org.ktorm.dsl.*
import java.time.ZoneId
import java.time.ZonedDateTime
import java.util.*
class PostgresBetDataSource(private val database: Database) : BetDataSource {
private fun QueryRowSet.toBet() =
Bet(
id = this[BetsEntity.id].toString(),
theme = this[BetsEntity.theme].toString(),
sentenceBet = this[BetsEntity.sentenceBet].toString(),
endRegistration = this[BetsEntity.endRegistration]!!.atZone(ZoneId.of("Europe/Paris")),
endBet = this[BetsEntity.endBet]!!.atZone(ZoneId.of("Europe/Paris")),
isPrivate = this[BetsEntity.isPrivate] ?: false,
status = this[BetsEntity.status] ?: BetStatus.IN_PROGRESS,
type = this[BetsEntity.type] ?: BetType.CUSTOM,
createdBy = this[BetsEntity.createdBy].toString(),
response = let {
val idBet = this[BetsEntity.id].toString()
val type = this[BetsEntity.type] ?: BetType.CUSTOM
if (type == BetType.CUSTOM) {
database.from(ResponsesEntity)
.select(response)
.where { ResponsesEntity.id eq UUID.fromString(idBet) }
.map { it[response].toString() }
} else {
listOf(YES_VALUE, NO_VALUE)
}
}
)
private fun Query.mapToBet() = this.map { it.toBet() }
override fun getAllBets(): List<Bet> =
database.from(BetsEntity).select().mapToBet()
override fun getBetById(id: String): Bet? =
database.from(BetsEntity).select().where {
BetsEntity.id eq UUID.fromString(id)
}.mapToBet().firstOrNull()
override fun getBetsNotFinished(): List<Bet> {
val currentTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"))
return database.from(BetsEntity)
.select()
.where { BetsEntity.endBet greaterEq currentTime.toInstant() }
.mapToBet()
}
override fun addBet(bet: Bet) {
database.insert(BetsEntity) {
set(it.id, UUID.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)
set(it.status, bet.status)
set(it.type, bet.type)
}
if (bet.type == BetType.CUSTOM) {
bet.response.forEach { selected ->
database.insert(ResponsesEntity) {
set(it.id, UUID.fromString(bet.id))
set(it.response, selected)
}
}
}
}
override fun removeBet(id: String): Boolean {
return database.delete(BetsEntity) { it.id eq UUID.fromString(id) } > 0
}
override fun updateBet(data: UpdatedBetData): Boolean {
return database.update(BetsEntity) {
set(BetsEntity.isPrivate, data.isPrivate)
where { BetsEntity.id eq UUID.fromString(data.id) }
} > 0
}
override fun updateBetStatuses(date: ZonedDateTime) {
database.update(BetsEntity) {
set(BetsEntity.status, BetStatus.WAITING)
where {
(date.toInstant() greaterEq BetsEntity.endRegistration) and
(date.toInstant() less BetsEntity.endBet)
}
}
database.update(BetsEntity) {
set(BetsEntity.status, BetStatus.CLOSING)
where {
(date.toInstant() greaterEq BetsEntity.endRegistration) and
(date.toInstant() greaterEq BetsEntity.endBet)
}
}
}
}

@ -0,0 +1,82 @@
package allin.data.postgres
import allin.data.AllInDataSource
import allin.data.BetDataSource
import allin.data.ParticipationDataSource
import allin.data.UserDataSource
import allin.utils.Execute
import org.ktorm.database.Database
class PostgresDataSource : AllInDataSource() {
private val database: Database
init {
val dbDatabase = System.getenv()["POSTGRES_DB"]
val dbUser = System.getenv()["POSTGRES_USER"]
val dbPassword = System.getenv()["POSTGRES_PASSWORD"]
val dbHost = System.getenv()["POSTGRES_HOST"]
database = Database.connect(
url = "jdbc:postgresql://$dbHost/$dbDatabase",
user = dbUser,
password = dbPassword
)
database.Execute(
"""
CREATE TABLE IF not exists utilisateur (
id uuid PRIMARY KEY,
username VARCHAR(255),
password VARCHAR(255),
coins double precision,
email VARCHAR(255)
)""".trimIndent()
)
database.Execute(
"""
CREATE TYPE betstatus AS ENUM
('InProgress', 'Waiting', 'Closing', 'Finished', 'Cancelled');
CREATE TYPE bettype AS ENUM
('Match', 'Binary', 'Custom');
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),
status varchar(20),
type varchar(20)
)""".trimIndent()
)
database.Execute(
"""
CREATE TABLE IF NOT EXISTS participation (
id uuid PRIMARY KEY,
bet uuid,
username varchar(250),
answer varchar(250),
stake int
)""".trimIndent()
)
database.Execute(
"""
CREATE TABLE IF NOT EXISTS response (
id UUID,
response VARCHAR(250),
CONSTRAINT pk_response_id PRIMARY KEY (id,response)
)""".trimIndent()
)
}
override val userDataSource: UserDataSource = PostgresUserDataSource(database)
override val betDataSource: BetDataSource = PostgresBetDataSource(database)
override val participationDataSource: ParticipationDataSource = PostgresParticipationDataSource(database)
}

@ -0,0 +1,57 @@
package allin.data.postgres
import allin.data.ParticipationDataSource
import allin.entities.ParticipationsEntity
import allin.model.Participation
import org.ktorm.database.Database
import org.ktorm.dsl.*
import java.util.*
class PostgresParticipationDataSource(private val database: Database) : ParticipationDataSource {
private fun QueryRowSet.toParticipation() =
Participation(
id = this[ParticipationsEntity.id].toString(),
betId = this[ParticipationsEntity.betId].toString(),
username = this[ParticipationsEntity.username].toString(),
answer = this[ParticipationsEntity.answer].toString(),
stake = this[ParticipationsEntity.stake] ?: 0,
)
private fun Query.mapToParticipation() = this.map { it.toParticipation() }
override fun addParticipation(participation: Participation) {
database.insert(ParticipationsEntity) {
set(it.id, UUID.fromString(participation.id))
set(it.betId, UUID.fromString(participation.betId))
set(it.username, participation.username)
set(it.answer, participation.answer)
set(it.stake, participation.stake)
}
}
override fun getParticipationFromBetId(betid: String): List<Participation> {
return database.from(ParticipationsEntity)
.select()
.where { ParticipationsEntity.betId eq UUID.fromString(betid) }
.mapToParticipation()
}
override fun getParticipationFromUserId(username: String, betid: String): List<Participation> {
return database.from(ParticipationsEntity)
.select()
.where { (ParticipationsEntity.betId eq UUID.fromString(betid)) and (ParticipationsEntity.username eq username) }
.mapToParticipation()
}
fun getParticipationEntity(): List<Participation> {
return database.from(ParticipationsEntity).select().mapToParticipation()
}
override fun deleteParticipation(id: String): Boolean {
return database.delete(ParticipationsEntity) {
it.id eq UUID.fromString(id)
} > 0
}
}

@ -0,0 +1,59 @@
package allin.data.postgres
import allin.data.UserDataSource
import allin.dto.UserDTO
import allin.entities.UsersEntity
import allin.model.User
import org.ktorm.database.Database
import org.ktorm.dsl.*
import java.util.*
class PostgresUserDataSource(private val database: Database) : UserDataSource {
override fun getUserByUsername(username: String): Pair<UserDTO?, String?> =
database.from(UsersEntity)
.select()
.where { UsersEntity.username eq username }
.map { row ->
Pair(
UserDTO(
row[UsersEntity.id].toString(),
row[UsersEntity.username].toString(),
row[UsersEntity.email].toString(),
row[UsersEntity.nbCoins] ?: 0,
null
),
row[UsersEntity.password].toString()
)
}
.firstOrNull() ?: Pair(null, null)
override fun addUser(user: User) {
database.insert(UsersEntity) {
set(it.id, UUID.fromString(user.id))
set(it.nbCoins, user.nbCoins)
set(it.username, user.username)
set(it.password, user.password)
set(it.email, user.email)
}
}
override fun deleteUser(username: String): Boolean {
val deletedCount = database.delete(UsersEntity) {
it.username eq username
}
return deletedCount > 0
}
override fun userExists(username: String, email: String): Boolean {
return database.from(UsersEntity).select(UsersEntity.username, UsersEntity.email).where {
(UsersEntity.username eq username) and (UsersEntity.email eq email)
}.totalRecords > 0
}
override fun modifyUserCoins(username: String, amount: Int) {
database.update(UsersEntity) {
set(UsersEntity.nbCoins, UsersEntity.nbCoins - amount)
where { UsersEntity.username eq username }
}
}
}

@ -1,15 +1,11 @@
package allin.entities package allin.entities
import allin.database import allin.model.BetStatus
import allin.entities.ResponsesEntity.getResponse import allin.model.BetType
import allin.model.Bet
import allin.utils.Execute
import org.ktorm.dsl.*
import org.ktorm.entity.Entity import org.ktorm.entity.Entity
import org.ktorm.schema.* import org.ktorm.schema.*
import java.time.ZoneId import org.ktorm.support.postgresql.pgEnum
import java.time.ZonedDateTime import java.time.ZonedDateTime
import java.util.UUID.fromString
interface BetEntity : Entity<BetEntity> { interface BetEntity : Entity<BetEntity> {
@ -18,6 +14,8 @@ interface BetEntity : Entity<BetEntity> {
val endRegistration: ZonedDateTime val endRegistration: ZonedDateTime
val endBet: ZonedDateTime val endBet: ZonedDateTime
val isPrivate: Boolean val isPrivate: Boolean
val status: BetStatus
val type: BetType
val createdBy: String val createdBy: String
} }
@ -28,57 +26,7 @@ object BetsEntity : Table<BetEntity>("bet") {
val endRegistration = timestamp("endregistration") val endRegistration = timestamp("endregistration")
val endBet = timestamp("endbet") val endBet = timestamp("endbet")
val isPrivate = boolean("isprivate") val isPrivate = boolean("isprivate")
val status = pgEnum<BetStatus>("status").bindTo { it.status }
val type = pgEnum<BetType>("type").bindTo { it.type }
val createdBy = varchar("createdby") val createdBy = varchar("createdby")
fun getBets(): MutableList<Bet> {
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 getBetsNotFinished(): MutableList<Bet> {
val currentTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"))
return database.from(BetsEntity)
.select()
.where { endBet greaterEq currentTime.toInstant() }
.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))
}
} }

@ -1,12 +1,10 @@
package allin.entities package allin.entities
import allin.database
import allin.model.Participation
import allin.utils.Execute
import org.ktorm.dsl.*
import org.ktorm.entity.Entity import org.ktorm.entity.Entity
import org.ktorm.schema.* import org.ktorm.schema.Table
import java.util.* import org.ktorm.schema.int
import org.ktorm.schema.uuid
import org.ktorm.schema.varchar
interface ParticipationEntity : Entity<ParticipationEntity> { interface ParticipationEntity : Entity<ParticipationEntity> {
val id: String val id: String
@ -23,68 +21,4 @@ object ParticipationsEntity : Table<BetEntity>("participation") {
val username = varchar("username") val username = varchar("username")
val answer = varchar("answer") val answer = varchar("answer")
val stake = int("stake") val stake = int("stake")
fun createParticipationTable(){
val request="CREATE TABLE IF NOT EXISTS participation (id uuid PRIMARY KEY,bet uuid,username varchar(250),answer varchar(250),stake int);"
database.Execute(request)
}
fun addParticipationEntity(participation : Participation){
database.insert(ParticipationsEntity){
set(it.id, UUID.fromString(participation.id))
set(it.betId,UUID.fromString(participation.betId))
set(it.username,participation.username)
set(it.answer,participation.answer)
set(it.stake,participation.stake)
}
}
fun getParticipationEntityFromBetId(betid: String): MutableList<Participation> {
return database.from(ParticipationsEntity)
.select()
.where { betId eq UUID.fromString(betid) }
.map { row ->
Participation(
row[id].toString(),
row[betId].toString(),
row[username].toString(),
row[answer].toString(),
row[stake] ?: 0,
)
}.toMutableList()
}
fun getParticipationEntityFromUserId(user: String, betid: String): MutableList<Participation> {
return database.from(ParticipationsEntity)
.select()
.where { (betId eq UUID.fromString(betid)) and (username eq user) }
.map { row ->
Participation(
row[id].toString(),
row[betId].toString(),
row[username].toString(),
row[answer].toString(),
row[stake] ?: 0,
)
}.toMutableList()
}
fun getParticipationEntity(): MutableList<Participation> {
return database.from(ParticipationsEntity).select().map {
row -> Participation(
row[id].toString(),
row[betId].toString(),
row[username].toString(),
row[answer].toString(),
row[stake]?:0,
)
}.toMutableList()
}
fun deleteParticipation(participation: Participation): Boolean {
val deletedCount = database.delete(ParticipationsEntity) {
it.id eq UUID.fromString(participation.id)
}
return deletedCount > 0
}
} }

@ -1,8 +1,5 @@
package allin.entities package allin.entities
import allin.database
import allin.utils.Execute
import org.ktorm.dsl.*
import org.ktorm.entity.Entity import org.ktorm.entity.Entity
import org.ktorm.schema.Table import org.ktorm.schema.Table
import org.ktorm.schema.uuid import org.ktorm.schema.uuid
@ -10,6 +7,9 @@ import org.ktorm.schema.varchar
import java.util.* import java.util.*
const val YES_VALUE = "Yes"
const val NO_VALUE = "No"
interface ResponseEntity : Entity<ResponseEntity> { interface ResponseEntity : Entity<ResponseEntity> {
val betId: UUID val betId: UUID
val response: String val response: String
@ -18,24 +18,4 @@ interface ResponseEntity : Entity<ResponseEntity> {
object ResponsesEntity : Table<ResponseEntity>("response") { object ResponsesEntity : Table<ResponseEntity>("response") {
val id = uuid("id").primaryKey() val id = uuid("id").primaryKey()
val response = varchar("response").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<String> {
return database.from(ResponsesEntity)
.select(response)
.where { id eq idBet }
.map { it[response].toString() }.toMutableList()
}
fun addResponse(responses : MutableList<String>, idBet : UUID ) {
responses.forEach {selected ->
database.insert(ResponsesEntity) {
set(it.id, idBet)
set(it.response,selected)
}
}
}
} }

@ -1,16 +1,13 @@
package allin.entities package allin.entities
import allin.database import allin.database
import allin.dto.UserDTO
import allin.model.User
import allin.utils.Execute
import allin.utils.ExecuteWithResult import allin.utils.ExecuteWithResult
import org.ktorm.database.use import org.ktorm.database.use
import org.ktorm.dsl.* import org.ktorm.dsl.eq
import org.ktorm.entity.* import org.ktorm.dsl.update
import org.ktorm.entity.Entity
import org.ktorm.schema.* import org.ktorm.schema.*
import java.time.Instant.now import java.time.Instant
import java.util.UUID.fromString
interface UserEntity : Entity<UserEntity> { interface UserEntity : Entity<UserEntity> {
val username: String val username: String
@ -18,6 +15,7 @@ interface UserEntity : Entity<UserEntity> {
var password: String var password: String
var nbCoins: Int var nbCoins: Int
} }
object UsersEntity : Table<UserEntity>("utilisateur") { object UsersEntity : Table<UserEntity>("utilisateur") {
val id = uuid("id").primaryKey() val id = uuid("id").primaryKey()
val username = varchar("username") val username = varchar("username")
@ -25,73 +23,11 @@ object UsersEntity : Table<UserEntity>("utilisateur") {
val nbCoins = int("coins") val nbCoins = int("coins")
val email = varchar("email") val email = varchar("email")
val lastGift = timestamp("lastgift") val lastGift = timestamp("lastgift")
fun getUserToUserDTO(): MutableList<UserDTO> {
return database.from(UsersEntity).select().map {
row -> UserDTO(
row[id].toString(),
row[username].toString(),
row[email].toString(),
row[nbCoins]?:0,
null
)
}.toMutableList()
}
fun createUserTable(){
val request="CREATE TABLE IF not exists utilisateur ( id uuid PRIMARY KEY, username VARCHAR(255), password VARCHAR(255),coins numeric,email VARCHAR(255), lastgift timestamp)"
database.Execute(request)
}
fun modifyCoins(user: String, cost : Int){
val request = "UPDATE utilisateur SET coins = coins - $cost WHERE username = '$user';"
database.Execute(request)
} }
fun addCoinByUsername(username: String, coins : Int){
database.update(UsersEntity){
set(nbCoins,coins+ nbCoins)
where {it.username eq username}
}
}
fun getUserByUsernameAndPassword(login: String): Pair<UserDTO?, String?> {
return database.from(UsersEntity)
.select()
.where { (username eq login) /*and (password eq passwordParam)*/ }
.map { row ->
Pair(
UserDTO(
row[id].toString(),
row[username].toString(),
row[email].toString(),
row[nbCoins] ?: 0,
null
),
row[password].toString()
)
}
.firstOrNull() ?: Pair(null, null)
}
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)
set(it.email,user.email)
set(it.lastGift,now())
}
}
fun deleteUserByUsername(username: String): Boolean {
val deletedCount = database.delete(UsersEntity) {
it.username eq username
}
return deletedCount > 0
}
/*CREATE TABLE IF not exists utilisateur ( id uuid PRIMARY KEY, username VARCHAR(255), password VARCHAR(255),coins numeric,email VARCHAR(255), lastgift timestamp)*/
/*
fun canHaveDailyGift(username: String): Boolean { fun canHaveDailyGift(username: String): Boolean {
val request = "SELECT CASE WHEN NOW() - lastgift > INTERVAL '1 day' THEN true ELSE false END AS is_lastgift_greater_than_1_day FROM utilisateur WHERE username = '$username';" val request = "SELECT CASE WHEN NOW() - lastgift > INTERVAL '1 day' THEN true ELSE false END AS is_lastgift_greater_than_1_day FROM utilisateur WHERE username = '$username';"
val resultSet = database.ExecuteWithResult(request) val resultSet = database.ExecuteWithResult(request)
@ -101,7 +37,7 @@ object UsersEntity : Table<UserEntity>("utilisateur") {
val isDailyGift = resultSet.getBoolean("is_lastgift_greater_than_1_day") val isDailyGift = resultSet.getBoolean("is_lastgift_greater_than_1_day")
if (isDailyGift) { if (isDailyGift) {
database.update(UsersEntity) { database.update(UsersEntity) {
set(lastGift, now()) set(UsersEntity.lastGift, Instant.now())
where { it.username eq username } where { it.username eq username }
} }
} }
@ -110,8 +46,5 @@ object UsersEntity : Table<UserEntity>("utilisateur") {
} }
return false return false
} }
*/
}

@ -1,7 +1,7 @@
package allin.ext package allin.ext
import allin.data.UserDataSource
import allin.dto.UserDTO import allin.dto.UserDTO
import allin.entities.UsersEntity
import allin.model.ApiMessage import allin.model.ApiMessage
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
@ -10,15 +10,18 @@ import io.ktor.server.auth.jwt.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.util.pipeline.* import io.ktor.util.pipeline.*
suspend fun PipelineContext<*, ApplicationCall>.hasToken(content: suspend (principal: JWTPrincipal) -> Unit) = suspend fun PipelineContext<*, ApplicationCall>.hasToken(content: suspend (principal: JWTPrincipal) -> Unit) =
call.principal<JWTPrincipal>()?.let { content(it) } ?: call.respond(HttpStatusCode.Unauthorized) call.principal<JWTPrincipal>()?.let { content(it) } ?: call.respond(HttpStatusCode.Unauthorized)
suspend fun PipelineContext<*, ApplicationCall>.verifyUserFromToken( suspend fun PipelineContext<*, ApplicationCall>.verifyUserFromToken(
userDataSource: UserDataSource,
principal: JWTPrincipal, principal: JWTPrincipal,
content: suspend (user: UserDTO, password: String) -> Unit content: suspend (user: UserDTO, password: String) -> Unit
) { ) {
val username = principal.payload.getClaim("username").asString() val username = principal.payload.getClaim("username").asString()
val userPassword = UsersEntity.getUserByUsernameAndPassword(username) val userPassword = userDataSource.getUserByUsername(username)
userPassword.first?.let { content(it, userPassword.second ?: "") } userPassword.first?.let { content(it, userPassword.second ?: "") }
?: call.respond(HttpStatusCode.NotFound, ApiMessage.TokenUserNotFound) ?: call.respond(HttpStatusCode.NotFound, ApiMessage.TokenUserNotFound)
} }

@ -1,20 +1,21 @@
package allin.model package allin.model
import allin.serializer.UUIDSerializer import allin.model.BetStatus.IN_PROGRESS
import allin.serializer.ZonedDateTimeSerializer import allin.serializer.ZonedDateTimeSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import java.time.ZonedDateTime import java.time.ZonedDateTime
import java.util.*
@Serializable @Serializable
data class Bet( data class Bet(
val id: String = "", val id: String = "",
val theme: String, val theme: String,
val sentenceBet: String, val sentenceBet: String,
val status: BetStatus = IN_PROGRESS,
val type: BetType,
@Serializable(ZonedDateTimeSerializer::class) val endRegistration: ZonedDateTime, @Serializable(ZonedDateTimeSerializer::class) val endRegistration: ZonedDateTime,
@Serializable(ZonedDateTimeSerializer::class) var endBet: ZonedDateTime, @Serializable(ZonedDateTimeSerializer::class) var endBet: ZonedDateTime,
var isPrivate: Boolean, var isPrivate: Boolean,
var response: MutableList<String>, var response: List<String>,
val createdBy: String = "" val createdBy: String = ""
) )
@ -23,5 +24,5 @@ data class UpdatedBetData(
val id: String, val id: String,
@Serializable(ZonedDateTimeSerializer::class) val endBet: ZonedDateTime, @Serializable(ZonedDateTimeSerializer::class) val endBet: ZonedDateTime,
val isPrivate: Boolean, val isPrivate: Boolean,
val response: MutableList<String> val response: List<String>
) )

@ -0,0 +1,9 @@
package allin.model
enum class BetStatus {
IN_PROGRESS,
WAITING,
CLOSING,
FINISHED,
CANCELLED
}

@ -0,0 +1,7 @@
package allin.model
enum class BetType {
MATCH,
BINARY,
CUSTOM
}

@ -4,6 +4,7 @@ import io.ktor.server.application.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
fun Application.BasicRouting() { fun Application.BasicRouting() {
routing { routing {
get("/") { get("/") {

@ -1,8 +1,6 @@
package allin.routing package allin.routing
import allin.entities.BetsEntity.getBets import allin.dataSource
import allin.entities.ParticipationsEntity.getParticipationEntityFromBetId
import allin.entities.ParticipationsEntity.getParticipationEntityFromUserId
import allin.ext.hasToken import allin.ext.hasToken
import allin.ext.verifyUserFromToken import allin.ext.verifyUserFromToken
import allin.model.BetDetail import allin.model.BetDetail
@ -13,15 +11,20 @@ import io.ktor.server.auth.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
fun Application.BetDetailRouter() { fun Application.BetDetailRouter() {
val userDataSource = this.dataSource.userDataSource
val betDataSource = this.dataSource.betDataSource
val participationDataSource = this.dataSource.participationDataSource
routing { routing {
authenticate { authenticate {
get("/betdetail/get/{id}") { get("/betdetail/get/{id}") {
hasToken { principal -> hasToken { principal ->
verifyUserFromToken(principal) { user, _ -> verifyUserFromToken(userDataSource, principal) { user, _ ->
val id = call.parameters["id"].toString() val id = call.parameters["id"].toString()
val participations = getParticipationEntityFromBetId(id) val participations = participationDataSource.getParticipationFromBetId(id)
val selectedBet = getBets().find { it.id == id } val selectedBet = betDataSource.getBetById(id)
if (selectedBet != null) { if (selectedBet != null) {
call.respond( call.respond(
HttpStatusCode.Accepted, HttpStatusCode.Accepted,
@ -29,7 +32,7 @@ fun Application.BetDetailRouter() {
selectedBet, selectedBet,
getBetAnswerDetail(selectedBet, participations), getBetAnswerDetail(selectedBet, participations),
participations.toList(), participations.toList(),
getParticipationEntityFromUserId(user.username, id).lastOrNull() participationDataSource.getParticipationFromUserId(user.username, id).lastOrNull()
) )
) )
} else { } else {

@ -1,10 +1,6 @@
package allin.routing package allin.routing
import allin.entities.BetsEntity.addBetEntity import allin.dataSource
import allin.entities.BetsEntity.getBets
import allin.entities.BetsEntity.getBetsNotFinished
import allin.entities.ParticipationsEntity.getParticipationEntity
import allin.entities.ParticipationsEntity.getParticipationEntityFromUserId
import allin.ext.hasToken import allin.ext.hasToken
import allin.ext.verifyUserFromToken import allin.ext.verifyUserFromToken
import allin.model.ApiMessage import allin.model.ApiMessage
@ -21,7 +17,12 @@ import java.util.*
val tokenManagerBet = AppConfig.tokenManager val tokenManagerBet = AppConfig.tokenManager
fun Application.BetRouter() { fun Application.BetRouter() {
val userDataSource = this.dataSource.userDataSource
val betDataSource = this.dataSource.betDataSource
val participationDataSource = this.dataSource.participationDataSource
routing { routing {
route("/bets/add") { route("/bets/add") {
authenticate { authenticate {
@ -30,21 +31,11 @@ fun Application.BetRouter() {
val bet = call.receive<Bet>() val bet = call.receive<Bet>()
val id = UUID.randomUUID().toString() val id = UUID.randomUUID().toString()
val username = tokenManagerBet.getUsernameFromToken(principal) val username = tokenManagerBet.getUsernameFromToken(principal)
val bets = getBets() betDataSource.getBetById(id)?.let {
bets.find { it.id == id }?.let {
call.respond(HttpStatusCode.Conflict, ApiMessage.BetAlreadyExist) call.respond(HttpStatusCode.Conflict, ApiMessage.BetAlreadyExist)
} ?: run { } ?: run {
val betWithId = Bet( val betWithId = bet.copy(id = id, createdBy = username)
id, betDataSource.addBet(betWithId)
bet.theme,
bet.sentenceBet,
bet.endRegistration,
bet.endBet,
bet.isPrivate,
bet.response,
username
)
addBetEntity(betWithId)
call.respond(HttpStatusCode.Created, betWithId) call.respond(HttpStatusCode.Created, betWithId)
} }
} }
@ -57,17 +48,15 @@ fun Application.BetRouter() {
route("/bets/gets") { route("/bets/gets") {
get { get {
// if(bets.size>0) // if(bets.size>0)
val bets= getBets() call.respond(HttpStatusCode.Accepted, betDataSource.getAllBets())
call.respond(HttpStatusCode.Accepted, bets.toList())
// else call.respond(HttpStatusCode.NoContent) // else call.respond(HttpStatusCode.NoContent)
} }
} }
route("/bets/get/{id}") { route("/bets/get/{id}") {
get { get {
val bets= getBets()
val id = call.parameters["id"] ?: "" val id = call.parameters["id"] ?: ""
bets.find { it.id == id }?.let { bet -> betDataSource.getBetById(id)?.let { bet ->
call.respond(HttpStatusCode.Accepted, bet) call.respond(HttpStatusCode.Accepted, bet)
} ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound) } ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound)
} }
@ -75,35 +64,35 @@ fun Application.BetRouter() {
route("/bets/delete") { route("/bets/delete") {
post { post {
val idbet = call.receive<Map<String, String>>()["id"] val id = call.receive<Map<String, String>>()["id"] ?: ""
val bets= getBets() if (betDataSource.removeBet(id)) {
bets.find { it.id == idbet }?.let { findbet -> call.respond(HttpStatusCode.Accepted)
bets.remove(findbet) } else {
call.respond(HttpStatusCode.Accepted, findbet) call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound)
} ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound) }
} }
} }
route("bets/update") { route("bets/update") {
post { post {
val updatedBetData = call.receive<UpdatedBetData>() val updatedBetData = call.receive<UpdatedBetData>()
val bets= getBets() if (betDataSource.updateBet(updatedBetData)) {
bets.find { it.id == updatedBetData.id }?.let { findbet -> call.respond(HttpStatusCode.Accepted)
findbet.endBet = updatedBetData.endBet } else {
findbet.isPrivate = updatedBetData.isPrivate call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound)
findbet.response = updatedBetData.response }
call.respond(HttpStatusCode.Accepted, findbet)
} ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound)
} }
} }
authenticate { authenticate {
get("/bets/current") { get("/bets/current") {
hasToken { principal -> hasToken { principal ->
verifyUserFromToken(principal) { user, _ -> verifyUserFromToken(userDataSource, principal) { user, _ ->
val currentBets = getBetsNotFinished() val currentBets = betDataSource.getBetsNotFinished()
.filter { bet -> .filter { bet ->
val userParticipation = getParticipationEntityFromUserId(user.username, bet.id) val userParticipation =
userParticipation.isNotEmpty() || bet.createdBy == user.username participationDataSource.getParticipationFromUserId(user.username, bet.id)
userParticipation.isNotEmpty()
} }
call.respond(HttpStatusCode.OK, currentBets) call.respond(HttpStatusCode.OK, currentBets)

@ -1,9 +1,6 @@
package allin.routing package allin.routing
import allin.entities.ParticipationsEntity.addParticipationEntity import allin.dataSource
import allin.entities.ParticipationsEntity.deleteParticipation
import allin.entities.ParticipationsEntity.getParticipationEntity
import allin.entities.UsersEntity.modifyCoins
import allin.ext.hasToken import allin.ext.hasToken
import allin.ext.verifyUserFromToken import allin.ext.verifyUserFromToken
import allin.model.ApiMessage import allin.model.ApiMessage
@ -17,15 +14,20 @@ import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
import java.util.* import java.util.*
fun Application.ParticipationRouter() { fun Application.ParticipationRouter() {
val userDataSource = this.dataSource.userDataSource
val participationDataSource = this.dataSource.participationDataSource
routing { routing {
authenticate { authenticate {
post("/participations/add") { post("/participations/add") {
hasToken { principal -> hasToken { principal ->
val participation = call.receive<ParticipationRequest>() val participation = call.receive<ParticipationRequest>()
verifyUserFromToken(principal) { user, _ -> verifyUserFromToken(userDataSource, principal) { user, _ ->
if (user.nbCoins >= participation.stake) { if (user.nbCoins >= participation.stake) {
addParticipationEntity( participationDataSource.addParticipation(
Participation( Participation(
id = UUID.randomUUID().toString(), id = UUID.randomUUID().toString(),
betId = participation.betId, betId = participation.betId,
@ -34,7 +36,9 @@ fun Application.ParticipationRouter() {
stake = participation.stake stake = participation.stake
) )
) )
modifyCoins(user.username,participation.stake)
userDataSource.modifyUserCoins(username = user.username, amount = participation.stake)
call.respond(HttpStatusCode.Created) call.respond(HttpStatusCode.Created)
} else { } else {
call.respond(HttpStatusCode.Forbidden, ApiMessage.NotEnoughCoins) call.respond(HttpStatusCode.Forbidden, ApiMessage.NotEnoughCoins)
@ -43,14 +47,13 @@ fun Application.ParticipationRouter() {
} }
} }
delete("/participations/delete") { delete("/participations/delete") {
hasToken { principal -> hasToken {
val participationId = call.receive<String>() val participationId = call.receive<String>()
getParticipationEntity().find { it.id == participationId }?.let { participation -> if (participationDataSource.deleteParticipation(participationId)) {
verifyUserFromToken(principal) { _, _ ->
deleteParticipation(participation)
call.respond(HttpStatusCode.NoContent) call.respond(HttpStatusCode.NoContent)
} else {
call.respond(HttpStatusCode.NotFound, ApiMessage.ParticipationNotFound)
} }
} ?: call.respond(HttpStatusCode.NotFound, ApiMessage.ParticipationNotFound)
} }
} }
} }

@ -1,11 +1,6 @@
package allin.routing package allin.routing
import allin.entities.UsersEntity.addCoinByUsername import allin.dataSource
import allin.entities.UsersEntity.addUserEntity
import allin.entities.UsersEntity.canHaveDailyGift
import allin.entities.UsersEntity.deleteUserByUsername
import allin.entities.UsersEntity.getUserByUsernameAndPassword
import allin.entities.UsersEntity.getUserToUserDTO
import allin.ext.hasToken import allin.ext.hasToken
import allin.ext.verifyUserFromToken import allin.ext.verifyUserFromToken
import allin.model.* import allin.model.*
@ -22,8 +17,12 @@ val RegexCheckerUser = AppConfig.regexChecker
val CryptManagerUser = AppConfig.cryptManager val CryptManagerUser = AppConfig.cryptManager
val tokenManagerUser = AppConfig.tokenManager val tokenManagerUser = AppConfig.tokenManager
const val DEFAULT_COINS = 500 const val DEFAULT_COINS = 500
fun Application.UserRouter() { fun Application.UserRouter() {
val userDataSource = this.dataSource.userDataSource
routing { routing {
route("/users/register") { route("/users/register") {
post { post {
@ -31,10 +30,10 @@ fun Application.UserRouter() {
if (RegexCheckerUser.isEmailInvalid(tempUser.email)) { if (RegexCheckerUser.isEmailInvalid(tempUser.email)) {
call.respond(HttpStatusCode.Forbidden, ApiMessage.InvalidMail) call.respond(HttpStatusCode.Forbidden, ApiMessage.InvalidMail)
} }
val users = getUserToUserDTO() if (userDataSource.userExists(tempUser.username, tempUser.email)) {
users.find { it.username == tempUser.username || it.email == tempUser.email }?.let { _ ->
call.respond(HttpStatusCode.Conflict, ApiMessage.UserAlreadyExist) call.respond(HttpStatusCode.Conflict, ApiMessage.UserAlreadyExist)
} ?: run { }
val user = User( val user = User(
id = UUID.randomUUID().toString(), id = UUID.randomUUID().toString(),
username = tempUser.username, username = tempUser.username,
@ -45,16 +44,15 @@ fun Application.UserRouter() {
) )
CryptManagerUser.passwordCrypt(user) CryptManagerUser.passwordCrypt(user)
user.token = tokenManagerUser.generateOrReplaceJWTToken(user) user.token = tokenManagerUser.generateOrReplaceJWTToken(user)
addUserEntity(user) userDataSource.addUser(user)
call.respond(HttpStatusCode.Created, user) call.respond(HttpStatusCode.Created, user)
} }
} }
}
route("/users/login") { route("/users/login") {
post { post {
val checkUser = call.receive<CheckUser>() val checkUser = call.receive<CheckUser>()
val user = getUserByUsernameAndPassword(checkUser.login) val user = userDataSource.getUserByUsername(checkUser.login)
if (CryptManagerUser.passwordDecrypt(user.second ?: "", checkUser.password)) { if (CryptManagerUser.passwordDecrypt(user.second ?: "", checkUser.password)) {
user.first?.let { userDtoWithToken -> user.first?.let { userDtoWithToken ->
userDtoWithToken.token = tokenManagerUser.generateOrReplaceJWTToken(userDtoWithToken) userDtoWithToken.token = tokenManagerUser.generateOrReplaceJWTToken(userDtoWithToken)
@ -69,11 +67,10 @@ fun Application.UserRouter() {
authenticate { authenticate {
post("/users/delete") { post("/users/delete") {
hasToken { principal -> hasToken { principal ->
verifyUserFromToken(principal) { _, password -> verifyUserFromToken(userDataSource, principal) { _, password ->
val checkUser = call.receive<CheckUser>() val checkUser = call.receive<CheckUser>()
if (CryptManagerUser.passwordDecrypt(password, checkUser.password)) { if (CryptManagerUser.passwordDecrypt(password, checkUser.password)) {
if (!deleteUserByUsername(checkUser.login)) { if (!userDataSource.deleteUser(checkUser.login)) {
call.respond(HttpStatusCode.InternalServerError, "This user can't be delete now !") call.respond(HttpStatusCode.InternalServerError, "This user can't be delete now !")
} }
call.respond(HttpStatusCode.Accepted, password) call.respond(HttpStatusCode.Accepted, password)
@ -87,7 +84,7 @@ fun Application.UserRouter() {
get("/users/token") { get("/users/token") {
hasToken { principal -> hasToken { principal ->
verifyUserFromToken(principal) { userDto, _ -> verifyUserFromToken(userDataSource, principal) { userDto, _ ->
call.respond(HttpStatusCode.OK, userDto) call.respond(HttpStatusCode.OK, userDto)
} }
} }

@ -1,6 +1,5 @@
package allin.utils package allin.utils
import allin.database
import org.ktorm.database.Database import org.ktorm.database.Database
import java.sql.ResultSet import java.sql.ResultSet
@ -21,8 +20,8 @@ fun Database.ExecuteWithResult(request: String): ResultSet? {
} }
fun Database.Execute(request: String) { fun Database.Execute(request: String) {
if(!request.isNullOrEmpty()) if (request.isNotEmpty())
database.useTransaction { this.useTransaction {
val connection = it.connection val connection = it.connection
connection.prepareStatement(request).execute() connection.prepareStatement(request).execute()
connection.commit() connection.commit()

@ -0,0 +1,16 @@
package allin.utils
import kotlinx.coroutines.*
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
@OptIn(DelicateCoroutinesApi::class, ExperimentalTime::class)
fun kronJob(duration: Duration, action: () -> Unit) =
GlobalScope.launch {
withContext(Dispatchers.IO) {
while (true) {
runCatching { action() }
delay(duration.toLongMilliseconds())
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save