diff --git a/.drone.yml b/.drone.yml index ec4c05c..a468b58 100644 --- a/.drone.yml +++ b/.drone.yml @@ -39,12 +39,14 @@ steps: OVERWRITE: false PRIVATE: false ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier - CODEFIRST_CLIENTDRONE_ENV_POSTGRES_PASSWORD: + CODEFIRST_CLIENTDRONE_ENV_POSTGRES_ROOT_PASSWORD: from_secret: db_root_password CODEFIRST_CLIENTDRONE_ENV_POSTGRES_DB: from_secret: db_database CODEFIRST_CLIENTDRONE_ENV_POSTGRES_USER: from_secret: db_user + CODEFIRST_CLIENTDRONE_ENV_POSTGRES_PASSWORD: + from_secret: db_password - name: docker-image image: plugins/docker @@ -65,6 +67,12 @@ steps: CONTAINERNAME: api COMMAND: create OVERWRITE: true + CODEFIRST_CLIENTDRONE_ENV_POSTGRES_DB: + from_secret: db_database + CODEFIRST_CLIENTDRONE_ENV_POSTGRES_USER: + from_secret: db_user + CODEFIRST_CLIENTDRONE_ENV_POSTGRES_PASSWORD: + from_secret: db_password ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier depends_on: [docker-image] diff --git a/.gitignore b/.gitignore index c426c32..b3f8ec6 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,6 @@ out/ /.nb-gradle/ ### VS Code ### -.vscode/ \ No newline at end of file +.vscode/ + +!**/src/target/** \ No newline at end of file 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..bd62889 100644 --- a/Sources/src/main/kotlin/allin/Application.kt +++ b/Sources/src/main/kotlin/allin/Application.kt @@ -1,19 +1,28 @@ package allin -import allin.model.User +import allin.entities.UsersEntity import allin.routing.BasicRouting import allin.routing.BetRouter +import allin.routing.ParticipationRouter import allin.routing.UserRouter +import allin.utils.* import com.typesafe.config.ConfigFactory import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* +import io.ktor.server.auth.* +import io.ktor.server.auth.jwt.* import io.ktor.server.config.* import io.ktor.server.engine.* import io.ktor.server.netty.* import io.ktor.server.plugins.contentnegotiation.* -import allin.utils.TokenManager -import io.ktor.server.auth.* -import io.ktor.server.auth.jwt.* +import org.ktorm.database.Database + +val db_database=System.getenv().get("POSTGRES_DB") +val db_user=System.getenv().get("POSTGRES_USER") +val db_password=System.getenv().get("POSTGRES_PASSWORD") +val db_host=System.getenv().get("POSTGRES_HOST") + +val database = Database.connect("jdbc:postgresql://AllDev-postgresapi/$db_database", user = db_user, password = db_password) fun main() { embeddedServer(Netty, port = 8080, host = "0.0.0.0") { @@ -27,9 +36,9 @@ private fun Application.extracted() { authentication { jwt { verifier(tokenManager.verifyJWTToken()) - realm=config.property("realm").getString() + realm = config.property("realm").getString() validate { jwtCredential -> - if(jwtCredential.payload.getClaim("username").asString().isNotEmpty()) + if (jwtCredential.payload.getClaim("username").asString().isNotEmpty()) JWTPrincipal(jwtCredential.payload) else null } @@ -41,4 +50,6 @@ private fun Application.extracted() { BasicRouting() UserRouter() BetRouter() + ParticipationRouter() + UsersEntity.createUserTable() } 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 d8f0996..765c0a3 100644 --- a/Sources/src/main/kotlin/allin/entities/UserEntity.kt +++ b/Sources/src/main/kotlin/allin/entities/UserEntity.kt @@ -1,11 +1,79 @@ package allin.entities +import allin.database +import allin.dto.UserDTO +import allin.model.User +import allin.utils.Execute +import org.ktorm.dsl.* +import org.ktorm.entity.* +import org.ktorm.expression.SqlExpression import org.ktorm.schema.Table +import org.ktorm.schema.double import org.ktorm.schema.int import org.ktorm.schema.varchar -object UserEntity : Table("user") { +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") -} \ No newline at end of file + val nbCoins = double("coins") + 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 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))" + database.Execute(request) + } + + + 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/ext/PipelineContextExt.kt b/Sources/src/main/kotlin/allin/ext/PipelineContextExt.kt new file mode 100644 index 0000000..e111f9b --- /dev/null +++ b/Sources/src/main/kotlin/allin/ext/PipelineContextExt.kt @@ -0,0 +1,24 @@ +package allin.ext + +import allin.dto.UserDTO +import allin.entities.UsersEntity +import allin.model.ApiMessage +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.auth.* +import io.ktor.server.auth.jwt.* +import io.ktor.server.response.* +import io.ktor.util.pipeline.* + +suspend fun PipelineContext<*, ApplicationCall>.hasToken(content: suspend (principal: JWTPrincipal) -> Unit) = + call.principal()?.let { content(it) } ?: call.respond(HttpStatusCode.Unauthorized) + +suspend fun PipelineContext<*, ApplicationCall>.verifyUserFromToken( + principal: JWTPrincipal, + content: suspend (user: UserDTO, password: String) -> Unit +) { + val username = principal.payload.getClaim("username").asString() + 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 new file mode 100644 index 0000000..9f47ea3 --- /dev/null +++ b/Sources/src/main/kotlin/allin/model/ApiMessage.kt @@ -0,0 +1,14 @@ +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." + const val UserAlreadyExist = "Mail and/or username already exists." + const val InvalidMail = "Invalid mail." + const val ParticipationNotFound = "Participation not found." + const val NotEnoughCoins = "Not enough coins." +} \ No newline at end of file diff --git a/Sources/src/main/kotlin/allin/model/Bet.kt b/Sources/src/main/kotlin/allin/model/Bet.kt index 5d4bc13..16d7bb1 100644 --- a/Sources/src/main/kotlin/allin/model/Bet.kt +++ b/Sources/src/main/kotlin/allin/model/Bet.kt @@ -1,19 +1,36 @@ package allin.model -import allin.dto.UserDTOWithToken -import allin.serializer.DateSerializer +import allin.serializer.ZonedDateTimeSerializer import kotlinx.serialization.Serializable -import java.util.* +import java.time.ZonedDateTime @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) +data class Bet( + 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 +) @Serializable -data class UpdatedBetData(val id: Int,@Serializable(DateSerializer::class) val endBet: Date, val isPrivate: Boolean, val response: MutableList) +data class UpdatedBetData( + val id: String, + @Serializable(ZonedDateTimeSerializer::class) val endBet: ZonedDateTime, + val isPrivate: Boolean, + val response: MutableList +) @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 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/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/Participation.kt b/Sources/src/main/kotlin/allin/model/Participation.kt new file mode 100644 index 0000000..b2e8495 --- /dev/null +++ b/Sources/src/main/kotlin/allin/model/Participation.kt @@ -0,0 +1,19 @@ +package allin.model + +import kotlinx.serialization.Serializable + +@Serializable +data class Participation( + val id: String, + val betId: String, + val username: String, + val answer: String, + val stake: Int +) + +@Serializable +data class ParticipationRequest( + val betId: String, + val answer: String, + val stake: Int +) \ 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..ac0122e 100644 --- a/Sources/src/main/kotlin/allin/model/User.kt +++ b/Sources/src/main/kotlin/allin/model/User.kt @@ -1,10 +1,27 @@ package allin.model -import allin.dto.UserDTO import kotlinx.serialization.Serializable + +@Serializable +data class User( + val id: String, + val username: String, + val email: String, + var password: String, + var nbCoins: Int = 500, + var token: String? = null +) + @Serializable -data class User(val username: String, val email: String, var password: String, var nbCoins: Int = 1000, var token: String? = null) +data class UserRequest( + val username: String, + val email: String, + var password: String +) @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 +) \ No newline at end of file diff --git a/Sources/src/main/kotlin/allin/routing/BetRouter.kt b/Sources/src/main/kotlin/allin/routing/BetRouter.kt index 997cee5..e54e685 100644 --- a/Sources/src/main/kotlin/allin/routing/BetRouter.kt +++ b/Sources/src/main/kotlin/allin/routing/BetRouter.kt @@ -1,65 +1,95 @@ 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.UpdatedBetData import allin.utils.AppConfig import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.auth.* +import io.ktor.server.request.* import io.ktor.server.response.* +import io.ktor.server.routing.* +import java.util.* val bets = mutableListOf() -val tokenManagerBet= AppConfig.tokenManager +val tokenManagerBet = AppConfig.tokenManager -fun CreateId() : Int{ - return bets.size -} - -fun Application.BetRouter(){ - routing{ - route("/bets/add"){ - post{ - val bet = call.receive() - val id = CreateId() +fun Application.BetRouter() { + routing { + route("/bets/add") { + post { + val bet = call.receive() + val id = UUID.randomUUID().toString() val username = tokenManagerBet.getUsernameFromToken(bet.createdBy) - val findbet = bets.find { it.id == id } - if(findbet==null){ - val betWithId = convertBetWithoutIdToBet(bet,id,username) + bets.find { it.id == id }?.let { + call.respond(HttpStatusCode.Conflict, ApiMessage.BetAlreadyExist) + } ?: run { + val betWithId = Bet( + id, + bet.theme, + bet.sentenceBet, + bet.endRegistration, + bet.endBet, + bet.isPrivate, + bet.response, + username + ) bets.add(betWithId) call.respond(HttpStatusCode.Created, betWithId) } - call.respond(HttpStatusCode.Conflict,"Bet already exist") } } - route("/bets/gets"){ - get{ - // if(bets.size>0) - call.respond(HttpStatusCode.Accepted, bets.toList()) - // else call.respond(HttpStatusCode.NoContent) + + route("/bets/gets") { + get { + // if(bets.size>0) + call.respond(HttpStatusCode.Accepted, bets.toList()) + // 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>()["id"] - val findbet = bets.find { it.id == idbet } - if(findbet==null){ - call.respond(HttpStatusCode.NotFound, "Bet doesnt find") - } - bets.remove(findbet) - findbet as Bet - call.respond(HttpStatusCode.Accepted, findbet) + + route("/bets/delete") { + post { + val idbet = call.receive>()["id"] + bets.find { it.id == idbet }?.let { findbet -> + bets.remove(findbet) + call.respond(HttpStatusCode.Accepted, findbet) + } ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound) } } - route("bets/update"){ - post{ + route("bets/update") { + post { val updatedBetData = call.receive() - val findbet = bets.find { it.id == updatedBetData.id } - if (findbet == null) { - call.respond(HttpStatusCode.NotFound, "Bet not found") - } else { + bets.find { it.id == updatedBetData.id }?.let { findbet -> findbet.endBet = updatedBetData.endBet findbet.isPrivate = updatedBetData.isPrivate findbet.response = updatedBetData.response call.respond(HttpStatusCode.Accepted, findbet) + } ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound) + } + } + + authenticate { + get("/bets/current") { + hasToken { principal -> + verifyUserFromToken(principal) { user, _ -> + val bets = participations + .filter { it.username == user.username } + .mapNotNull { itParticipation -> bets.find { it.id == itParticipation.betId } } + call.respond(HttpStatusCode.OK, bets) + } } } } diff --git a/Sources/src/main/kotlin/allin/routing/ParticipationRouter.kt b/Sources/src/main/kotlin/allin/routing/ParticipationRouter.kt new file mode 100644 index 0000000..16106b3 --- /dev/null +++ b/Sources/src/main/kotlin/allin/routing/ParticipationRouter.kt @@ -0,0 +1,56 @@ +package allin.routing + +import allin.ext.hasToken +import allin.ext.verifyUserFromToken +import allin.model.ApiMessage +import allin.model.Participation +import allin.model.ParticipationRequest +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.auth.* +import io.ktor.server.request.* +import io.ktor.server.response.* +import io.ktor.server.routing.* +import java.util.* + +val participations = mutableListOf() + +fun Application.ParticipationRouter() { + routing { + authenticate { + post("/participations/add") { + hasToken { principal -> + val participation = call.receive() + verifyUserFromToken(principal) { user, _ -> + if (user.nbCoins >= participation.stake) { + participations.add( + Participation( + id = UUID.randomUUID().toString(), + betId = participation.betId, + username = user.username, + answer = participation.answer, + stake = participation.stake + ) + ) + call.respond(HttpStatusCode.Created) + } else { + call.respond(HttpStatusCode.Forbidden, ApiMessage.NotEnoughCoins) + } + } + } + } + delete("/participations/delete") { + hasToken { principal -> + val participationId = call.receive() + participations.find { it.id == participationId }?.let { participation -> + verifyUserFromToken(principal) { user, _ -> + // user.nbCoins += participation.stake + participations.remove(participation) + call.respond(HttpStatusCode.NoContent) + } + } ?: call.respond(HttpStatusCode.NotFound, ApiMessage.ParticipationNotFound) + } + } + } + } +} \ No newline at end of file diff --git a/Sources/src/main/kotlin/allin/routing/UserRouter.kt b/Sources/src/main/kotlin/allin/routing/UserRouter.kt index 18489be..4a70e06 100644 --- a/Sources/src/main/kotlin/allin/routing/UserRouter.kt +++ b/Sources/src/main/kotlin/allin/routing/UserRouter.kt @@ -1,81 +1,99 @@ package allin.routing -import allin.dto.* +import allin.entities.UsersEntity.addUserEntity +import allin.entities.UsersEntity.deleteUserByUsername +import allin.entities.UsersEntity.getUserByUsernameAndPassword +import allin.entities.UsersEntity.getUserToUserDTO +import allin.ext.hasToken +import allin.ext.verifyUserFromToken +import allin.model.ApiMessage import allin.model.CheckUser import allin.model.User +import allin.model.UserRequest import allin.utils.AppConfig import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.auth.* -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 +import java.util.* -val users = mutableListOf() -val RegexCheckerUser= AppConfig.regexChecker -val CryptManagerUser= AppConfig.cryptManager -val tokenManagerUser=AppConfig.tokenManager - - +val RegexCheckerUser = AppConfig.regexChecker +val CryptManagerUser = AppConfig.cryptManager +val tokenManagerUser = AppConfig.tokenManager +const val DEFAULT_COINS = 500 fun Application.UserRouter() { routing { - route("/users/register"){ + route("/users/register") { post { - val TempUser = call.receive() - if (RegexCheckerUser.isEmailInvalid(TempUser.email)){ - call.respond(HttpStatusCode.Forbidden,"Input a valid mail !") + val tempUser = call.receive() + if (RegexCheckerUser.isEmailInvalid(tempUser.email)) { + call.respond(HttpStatusCode.Forbidden, ApiMessage.InvalidMail) } - 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) + val users = getUserToUserDTO() + users.find { it.username == tempUser.username || it.email == tempUser.email }?.let { user -> + call.respond(HttpStatusCode.Conflict, ApiMessage.UserAlreadyExist) + } ?: run { + val user = User( + id = UUID.randomUUID().toString(), + username = tempUser.username, + email = tempUser.email, + password = tempUser.password, + nbCoins = DEFAULT_COINS, + token = null + ) + CryptManagerUser.passwordCrypt(user) + user.token = tokenManagerUser.generateOrReplaceJWTToken(user) + addUserEntity(user) + call.respond(HttpStatusCode.Created, user) } - call.respond(HttpStatusCode.Conflict,"Mail or/and username already exist") } } 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 ?: "", checkUser.password)) { + user.first?.let { userDtoWithToken -> + userDtoWithToken.token = tokenManagerUser.generateOrReplaceJWTToken(userDtoWithToken) + call.respond(HttpStatusCode.OK, userDtoWithToken) + } ?: call.respond(HttpStatusCode.NotFound, ApiMessage.UserNotFound) } else { - call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.") + call.respond(HttpStatusCode.NotFound, ApiMessage.IncorrectLoginPassword) } } } - 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)) - } else { - call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.") + authenticate { + post("/users/delete") { + hasToken { principal -> + verifyUserFromToken(principal) { _, password -> + val checkUser = call.receive() + + if (CryptManagerUser.passwordDecrypt(password, checkUser.password)) { + if (!deleteUserByUsername(checkUser.login)) { + call.respond(HttpStatusCode.InternalServerError, "This user can't be delete now !") + } + call.respond(HttpStatusCode.Accepted, password) + } else { + call.respond(HttpStatusCode.NotFound, "Login and/or password incorrect.") + } + + } } } - } - authenticate { 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)) - } else { - call.respond(HttpStatusCode.NotFound, "User not found with the valid token !") + hasToken { principal -> + verifyUserFromToken(principal) { userDto, _ -> + call.respond(HttpStatusCode.OK, userDto) + } } } } - } } 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/DatabaseUtil.kt b/Sources/src/main/kotlin/allin/utils/DatabaseUtil.kt new file mode 100644 index 0000000..033afe4 --- /dev/null +++ b/Sources/src/main/kotlin/allin/utils/DatabaseUtil.kt @@ -0,0 +1,13 @@ +package allin.utils + +import allin.database +import org.ktorm.database.Database + +fun Database.Execute(request: String){ + if(!request.isNullOrEmpty()) + database.useTransaction { + val connection = it.connection + connection.prepareStatement(request).execute() + connection.commit() + } +} \ 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..86f2073 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 @@ -10,19 +11,18 @@ import java.util.* class TokenManager private constructor(val config: HoconApplicationConfig) { - val audience=config.property("audience").getString() - val secret=config.property("secret").getString() - val issuer=config.property("issuer").getString() - fun generateJWTToken(user : User): String { + val audience = config.property("audience").getString() + val secret = config.property("secret").getString() + val issuer = config.property("issuer").getString() + fun generateJWTToken(user: User): String { val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde - val token = JWT.create() + return JWT.create() .withAudience(audience) .withIssuer(issuer) .withClaim("username", user.username) .withExpiresAt(Date(expirationDate)) .sign(Algorithm.HMAC256(secret)) - return token } fun verifyJWTToken(): JWTVerifier { @@ -34,26 +34,47 @@ class TokenManager private constructor(val config: HoconApplicationConfig) { fun generateOrReplaceJWTToken(user: User): String { val userToken = getUserToken(user) - if (userToken != null && !isTokenExpired(userToken)) { - return userToken + return if (userToken != null && !isTokenExpired(userToken)) { + userToken } else { - return generateJWTToken(user) + generateJWTToken(user) } } + + fun generateOrReplaceJWTToken(user: UserDTO): String { + val userToken = getUserToken(user) + return if (userToken != null && !isTokenExpired(userToken)) { + userToken + } else { + generateJWTToken(user) + } + } + + fun generateJWTToken(user: UserDTO): String { + val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde + return JWT.create() + .withAudience(audience) + .withIssuer(issuer) + .withClaim("username", user.username) + .withExpiresAt(Date(expirationDate)) + .sign(Algorithm.HMAC256(secret)) + } + + fun isTokenExpired(token: String): Boolean { val expirationTime = JWT.decode(token).expiresAt.time return System.currentTimeMillis() > expirationTime } - fun getUserToken(user: User): String? { - return user.token - } + fun getUserToken(user: User): String? = user.token + fun getUserToken(user: UserDTO): String? = user.token - fun getUsernameFromToken(token: String) : String{ + fun getUsernameFromToken(token: String): String { val decodedJWT: DecodedJWT = JWT.decode(token) return decodedJWT.getClaim("username").asString() } + companion object { private var instance: TokenManager? = null fun getInstance(config: HoconApplicationConfig): TokenManager { diff --git a/Sources/target/classes/META-INF/allin-api.kotlin_module b/Sources/target/classes/META-INF/allin-api.kotlin_module deleted file mode 100644 index 800390e..0000000 Binary files a/Sources/target/classes/META-INF/allin-api.kotlin_module and /dev/null differ diff --git a/Sources/target/classes/allin/ApplicationKt$extracted$1$1$1.class b/Sources/target/classes/allin/ApplicationKt$extracted$1$1$1.class deleted file mode 100644 index a8eff44..0000000 Binary files a/Sources/target/classes/allin/ApplicationKt$extracted$1$1$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/ApplicationKt$extracted$1$1.class b/Sources/target/classes/allin/ApplicationKt$extracted$1$1.class deleted file mode 100644 index 9d2dbac..0000000 Binary files a/Sources/target/classes/allin/ApplicationKt$extracted$1$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/ApplicationKt$extracted$1.class b/Sources/target/classes/allin/ApplicationKt$extracted$1.class deleted file mode 100644 index 2e3a1cf..0000000 Binary files a/Sources/target/classes/allin/ApplicationKt$extracted$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/ApplicationKt$extracted$2.class b/Sources/target/classes/allin/ApplicationKt$extracted$2.class deleted file mode 100644 index 54f0916..0000000 Binary files a/Sources/target/classes/allin/ApplicationKt$extracted$2.class and /dev/null differ diff --git a/Sources/target/classes/allin/ApplicationKt$main$1.class b/Sources/target/classes/allin/ApplicationKt$main$1.class deleted file mode 100644 index ccafde6..0000000 Binary files a/Sources/target/classes/allin/ApplicationKt$main$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/ApplicationKt.class b/Sources/target/classes/allin/ApplicationKt.class deleted file mode 100644 index a845276..0000000 Binary files a/Sources/target/classes/allin/ApplicationKt.class and /dev/null differ diff --git a/Sources/target/classes/allin/dto/UserDTO$$serializer.class b/Sources/target/classes/allin/dto/UserDTO$$serializer.class deleted file mode 100644 index 9eee0f2..0000000 Binary files a/Sources/target/classes/allin/dto/UserDTO$$serializer.class and /dev/null differ diff --git a/Sources/target/classes/allin/dto/UserDTO$Companion.class b/Sources/target/classes/allin/dto/UserDTO$Companion.class deleted file mode 100644 index d9c38c8..0000000 Binary files a/Sources/target/classes/allin/dto/UserDTO$Companion.class and /dev/null differ diff --git a/Sources/target/classes/allin/dto/UserDTO.class b/Sources/target/classes/allin/dto/UserDTO.class deleted file mode 100644 index 864d973..0000000 Binary files a/Sources/target/classes/allin/dto/UserDTO.class and /dev/null differ diff --git a/Sources/target/classes/allin/dto/UserDTOKt.class b/Sources/target/classes/allin/dto/UserDTOKt.class deleted file mode 100644 index 36801ca..0000000 Binary files a/Sources/target/classes/allin/dto/UserDTOKt.class and /dev/null differ diff --git a/Sources/target/classes/allin/dto/UserDTOWithToken$$serializer.class b/Sources/target/classes/allin/dto/UserDTOWithToken$$serializer.class deleted file mode 100644 index be21eba..0000000 Binary files a/Sources/target/classes/allin/dto/UserDTOWithToken$$serializer.class and /dev/null differ diff --git a/Sources/target/classes/allin/dto/UserDTOWithToken$Companion.class b/Sources/target/classes/allin/dto/UserDTOWithToken$Companion.class deleted file mode 100644 index 363fed4..0000000 Binary files a/Sources/target/classes/allin/dto/UserDTOWithToken$Companion.class and /dev/null differ diff --git a/Sources/target/classes/allin/dto/UserDTOWithToken.class b/Sources/target/classes/allin/dto/UserDTOWithToken.class deleted file mode 100644 index 00325c5..0000000 Binary files a/Sources/target/classes/allin/dto/UserDTOWithToken.class and /dev/null differ diff --git a/Sources/target/classes/allin/entities/UserEntity.class b/Sources/target/classes/allin/entities/UserEntity.class deleted file mode 100644 index d77e537..0000000 Binary files a/Sources/target/classes/allin/entities/UserEntity.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/Bet$$serializer.class b/Sources/target/classes/allin/model/Bet$$serializer.class deleted file mode 100644 index b24930a..0000000 Binary files a/Sources/target/classes/allin/model/Bet$$serializer.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/Bet$Companion.class b/Sources/target/classes/allin/model/Bet$Companion.class deleted file mode 100644 index 76f393c..0000000 Binary files a/Sources/target/classes/allin/model/Bet$Companion.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/Bet.class b/Sources/target/classes/allin/model/Bet.class deleted file mode 100644 index c8f6ea0..0000000 Binary files a/Sources/target/classes/allin/model/Bet.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/CheckUser$$serializer.class b/Sources/target/classes/allin/model/CheckUser$$serializer.class deleted file mode 100644 index 5b18949..0000000 Binary files a/Sources/target/classes/allin/model/CheckUser$$serializer.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/CheckUser$Companion.class b/Sources/target/classes/allin/model/CheckUser$Companion.class deleted file mode 100644 index 82cf4d4..0000000 Binary files a/Sources/target/classes/allin/model/CheckUser$Companion.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/CheckUser.class b/Sources/target/classes/allin/model/CheckUser.class deleted file mode 100644 index e2c1143..0000000 Binary files a/Sources/target/classes/allin/model/CheckUser.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/UpdatedBetData$$serializer.class b/Sources/target/classes/allin/model/UpdatedBetData$$serializer.class deleted file mode 100644 index 39e6f80..0000000 Binary files a/Sources/target/classes/allin/model/UpdatedBetData$$serializer.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/UpdatedBetData$Companion.class b/Sources/target/classes/allin/model/UpdatedBetData$Companion.class deleted file mode 100644 index 2c6d0ca..0000000 Binary files a/Sources/target/classes/allin/model/UpdatedBetData$Companion.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/UpdatedBetData.class b/Sources/target/classes/allin/model/UpdatedBetData.class deleted file mode 100644 index c65c0cf..0000000 Binary files a/Sources/target/classes/allin/model/UpdatedBetData.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/User$$serializer.class b/Sources/target/classes/allin/model/User$$serializer.class deleted file mode 100644 index 2027405..0000000 Binary files a/Sources/target/classes/allin/model/User$$serializer.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/User$Companion.class b/Sources/target/classes/allin/model/User$Companion.class deleted file mode 100644 index d87162d..0000000 Binary files a/Sources/target/classes/allin/model/User$Companion.class and /dev/null differ diff --git a/Sources/target/classes/allin/model/User.class b/Sources/target/classes/allin/model/User.class deleted file mode 100644 index 9979ceb..0000000 Binary files a/Sources/target/classes/allin/model/User.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1$1.class b/Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1$1.class deleted file mode 100644 index 61755ef..0000000 Binary files a/Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1.class b/Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1.class deleted file mode 100644 index ef08c2c..0000000 Binary files a/Sources/target/classes/allin/routing/BasicRoutingKt$BasicRouting$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BasicRoutingKt.class b/Sources/target/classes/allin/routing/BasicRoutingKt.class deleted file mode 100644 index 64dd93b..0000000 Binary files a/Sources/target/classes/allin/routing/BasicRoutingKt.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1$1.class b/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1$1.class deleted file mode 100644 index 524aa64..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1.class b/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1.class deleted file mode 100644 index 864d955..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2$1.class b/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2$1.class deleted file mode 100644 index 4c67bbe..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2.class b/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2.class deleted file mode 100644 index 40545f3..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$2.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3$1.class b/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3$1.class deleted file mode 100644 index 274e3cc..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3.class b/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3.class deleted file mode 100644 index 8f02977..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1$3.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1.class b/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1.class deleted file mode 100644 index 02b4638..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt$BetRouter$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/BetRouterKt.class b/Sources/target/classes/allin/routing/BetRouterKt.class deleted file mode 100644 index a7e3313..0000000 Binary files a/Sources/target/classes/allin/routing/BetRouterKt.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1$1.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1$1.class deleted file mode 100644 index 1538916..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1.class deleted file mode 100644 index c99cc1c..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2$1.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2$1.class deleted file mode 100644 index f71e2f6..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2.class deleted file mode 100644 index 5a9aec3..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$2.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3$1.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3$1.class deleted file mode 100644 index 1e3c24f..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3.class deleted file mode 100644 index f4e022e..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$3.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4$1.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4$1.class deleted file mode 100644 index 195cd40..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4.class deleted file mode 100644 index 06fc7df..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1$4.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1.class b/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1.class deleted file mode 100644 index 634940f..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt$UserRouter$1.class and /dev/null differ diff --git a/Sources/target/classes/allin/routing/UserRouterKt.class b/Sources/target/classes/allin/routing/UserRouterKt.class deleted file mode 100644 index 1b2e451..0000000 Binary files a/Sources/target/classes/allin/routing/UserRouterKt.class and /dev/null differ diff --git a/Sources/target/classes/allin/serializer/DateSerializer.class b/Sources/target/classes/allin/serializer/DateSerializer.class deleted file mode 100644 index b3567d9..0000000 Binary files a/Sources/target/classes/allin/serializer/DateSerializer.class and /dev/null differ diff --git a/Sources/target/classes/allin/utils/CryptManager.class b/Sources/target/classes/allin/utils/CryptManager.class deleted file mode 100644 index 30d34fd..0000000 Binary files a/Sources/target/classes/allin/utils/CryptManager.class and /dev/null differ diff --git a/Sources/target/classes/allin/utils/RegexChecker.class b/Sources/target/classes/allin/utils/RegexChecker.class deleted file mode 100644 index fc9cecf..0000000 Binary files a/Sources/target/classes/allin/utils/RegexChecker.class and /dev/null differ diff --git a/Sources/target/classes/allin/utils/TokenManager.class b/Sources/target/classes/allin/utils/TokenManager.class deleted file mode 100644 index 9612b21..0000000 Binary files a/Sources/target/classes/allin/utils/TokenManager.class and /dev/null differ diff --git a/Sources/target/classes/application.conf b/Sources/target/classes/application.conf deleted file mode 100644 index 1b4a12c..0000000 --- a/Sources/target/classes/application.conf +++ /dev/null @@ -1,4 +0,0 @@ -secret="secret" -issuer="http://0.0.0.0:8080/" -audience="http://0.0.0.0:8080/" -realm="Access to main page" \ No newline at end of file diff --git a/Sources/target/classes/logback.xml b/Sources/target/classes/logback.xml deleted file mode 100644 index 3e11d78..0000000 --- a/Sources/target/classes/logback.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/Sources/target/test-classes/META-INF/allin-api.kotlin_module b/Sources/target/test-classes/META-INF/allin-api.kotlin_module deleted file mode 100644 index 1e9f2ca..0000000 Binary files a/Sources/target/test-classes/META-INF/allin-api.kotlin_module and /dev/null differ diff --git a/Sources/target/test-classes/allin/ApplicationTest.class b/Sources/target/test-classes/allin/ApplicationTest.class deleted file mode 100644 index 07af2a7..0000000 Binary files a/Sources/target/test-classes/allin/ApplicationTest.class and /dev/null differ