Merge pull request 'Link_Database' (#3) from Link_Database into master
continuous-integration/drone/push Build is passing Details

Reviewed-on: #3
pull/4/head
Lucas EVARD 1 year ago
commit 63599de591

@ -39,12 +39,14 @@ steps:
OVERWRITE: false OVERWRITE: false
PRIVATE: false PRIVATE: false
ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_PASSWORD: CODEFIRST_CLIENTDRONE_ENV_POSTGRES_ROOT_PASSWORD:
from_secret: db_root_password from_secret: db_root_password
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_DB: CODEFIRST_CLIENTDRONE_ENV_POSTGRES_DB:
from_secret: db_database from_secret: db_database
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_USER: CODEFIRST_CLIENTDRONE_ENV_POSTGRES_USER:
from_secret: db_user from_secret: db_user
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_PASSWORD:
from_secret: db_password
- name: docker-image - name: docker-image
image: plugins/docker image: plugins/docker
@ -65,6 +67,12 @@ steps:
CONTAINERNAME: api CONTAINERNAME: api
COMMAND: create COMMAND: create
OVERWRITE: true 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 ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier
depends_on: [docker-image] depends_on: [docker-image]

2
.gitignore vendored

@ -34,3 +34,5 @@ out/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
!**/src/target/**

@ -32,6 +32,11 @@
<artifactId>ktor-server-core-jvm</artifactId> <artifactId>ktor-server-core-jvm</artifactId>
<version>${ktor_version}</version> <version>${ktor_version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.1</version>
</dependency>
<dependency> <dependency>
<groupId>io.ktor</groupId> <groupId>io.ktor</groupId>
<artifactId>ktor-server-netty-jvm</artifactId> <artifactId>ktor-server-netty-jvm</artifactId>

@ -1,19 +1,28 @@
package allin package allin
import allin.model.User import allin.entities.UsersEntity
import allin.routing.BasicRouting import allin.routing.BasicRouting
import allin.routing.BetRouter import allin.routing.BetRouter
import allin.routing.ParticipationRouter
import allin.routing.UserRouter import allin.routing.UserRouter
import allin.utils.*
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.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.config.* 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 allin.utils.TokenManager import org.ktorm.database.Database
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.* 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() { fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") { embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
@ -27,9 +36,9 @@ private fun Application.extracted() {
authentication { authentication {
jwt { jwt {
verifier(tokenManager.verifyJWTToken()) verifier(tokenManager.verifyJWTToken())
realm=config.property("realm").getString() realm = config.property("realm").getString()
validate { jwtCredential -> validate { jwtCredential ->
if(jwtCredential.payload.getClaim("username").asString().isNotEmpty()) if (jwtCredential.payload.getClaim("username").asString().isNotEmpty())
JWTPrincipal(jwtCredential.payload) JWTPrincipal(jwtCredential.payload)
else null else null
} }
@ -41,4 +50,6 @@ private fun Application.extracted() {
BasicRouting() BasicRouting()
UserRouter() UserRouter()
BetRouter() BetRouter()
ParticipationRouter()
UsersEntity.createUserTable()
} }

@ -1,15 +1,4 @@
package allin.dto package allin.dto
import allin.model.User
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class UserDTO(val username: String,val email: String, val nbCoins: Int) data class UserDTO(val username: String, val email: String, val nbCoins: Double, var token:String?)
@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)
}

@ -1,11 +1,79 @@
package allin.entities 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.Table
import org.ktorm.schema.double
import org.ktorm.schema.int import org.ktorm.schema.int
import org.ktorm.schema.varchar import org.ktorm.schema.varchar
object UserEntity : Table<Nothing>("user") { interface UserEntity : Entity<UserEntity> {
val username: String
var email: String
var password: String
var nbCoins: Double
}
object UsersEntity : Table<UserEntity>("utilisateur") {
val id = int("id").primaryKey() val id = int("id").primaryKey()
val username = varchar("username") val username = varchar("username")
val password = varchar("password") val password = varchar("password")
val nbCoins = double("coins")
val email = varchar("email")
fun getUserToUserDTO(): MutableList<UserDTO> {
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<UserDTO?, String?> {
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
}
} }

@ -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<JWTPrincipal>()?.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)
}

@ -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."
}

@ -1,19 +1,36 @@
package allin.model package allin.model
import allin.dto.UserDTOWithToken import allin.serializer.ZonedDateTimeSerializer
import allin.serializer.DateSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import java.util.* import java.time.ZonedDateTime
@Serializable @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<String>, 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<String>,
val createdBy: String
)
@Serializable @Serializable
data class UpdatedBetData(val id: Int,@Serializable(DateSerializer::class) val endBet: Date, val isPrivate: Boolean, val response: MutableList<String>) data class UpdatedBetData(
val id: String,
@Serializable(ZonedDateTimeSerializer::class) val endBet: ZonedDateTime,
val isPrivate: Boolean,
val response: MutableList<String>
)
@Serializable @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<String>, val createdBy : String) data class BetWithoutId(
val theme: String,
fun convertBetWithoutIdToBet(betWithoutId: BetWithoutId,id : Int, username : String): Bet { val sentenceBet: String,
return Bet(id,betWithoutId.theme,betWithoutId.sentenceBet,betWithoutId.endRegistration, betWithoutId.endBet, betWithoutId.isPrivate, betWithoutId.response, username) @Serializable(ZonedDateTimeSerializer::class) val endRegistration: ZonedDateTime,
} @Serializable(ZonedDateTimeSerializer::class) var endBet: ZonedDateTime,
var isPrivate: Boolean,
var response: MutableList<String>,
val createdBy: String
)

@ -1,5 +1,5 @@
package allin.model 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 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)

@ -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
)

@ -1,10 +1,27 @@
package allin.model package allin.model
import allin.dto.UserDTO
import kotlinx.serialization.Serializable 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 @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 @Serializable
data class CheckUser(val login: String,val password: String) data class CheckUser(
val login: String,
val password: String
)

@ -1,65 +1,95 @@
package allin.routing package allin.routing
import io.ktor.server.application.*
import io.ktor.server.request.* import allin.ext.hasToken
import io.ktor.server.routing.* import allin.ext.verifyUserFromToken
import allin.model.* import allin.model.ApiMessage
import allin.model.Bet
import allin.model.UpdatedBetData
import allin.utils.AppConfig import allin.utils.AppConfig
import io.ktor.http.* 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.response.*
import io.ktor.server.routing.*
import java.util.*
val bets = mutableListOf<Bet>() val bets = mutableListOf<Bet>()
val tokenManagerBet= AppConfig.tokenManager val tokenManagerBet = AppConfig.tokenManager
fun CreateId() : Int{ fun Application.BetRouter() {
return bets.size routing {
} route("/bets/add") {
post {
fun Application.BetRouter(){ val bet = call.receive<Bet>()
routing{ val id = UUID.randomUUID().toString()
route("/bets/add"){
post{
val bet = call.receive<BetWithoutId>()
val id = CreateId()
val username = tokenManagerBet.getUsernameFromToken(bet.createdBy) val username = tokenManagerBet.getUsernameFromToken(bet.createdBy)
val findbet = bets.find { it.id == id } bets.find { it.id == id }?.let {
if(findbet==null){ call.respond(HttpStatusCode.Conflict, ApiMessage.BetAlreadyExist)
val betWithId = convertBetWithoutIdToBet(bet,id,username) } ?: run {
val betWithId = Bet(
id,
bet.theme,
bet.sentenceBet,
bet.endRegistration,
bet.endBet,
bet.isPrivate,
bet.response,
username
)
bets.add(betWithId) bets.add(betWithId)
call.respond(HttpStatusCode.Created, betWithId) call.respond(HttpStatusCode.Created, betWithId)
} }
call.respond(HttpStatusCode.Conflict,"Bet already exist")
} }
} }
route("/bets/gets"){
get{ route("/bets/gets") {
// if(bets.size>0) get {
call.respond(HttpStatusCode.Accepted, bets.toList()) // if(bets.size>0)
// else call.respond(HttpStatusCode.NoContent) call.respond(HttpStatusCode.Accepted, bets.toList())
// else call.respond(HttpStatusCode.NoContent)
} }
} }
route("/bets/delete"){
post{ route("/bets/get/{id}") {
val idbet = call.receive<Map<String, Int>>()["id"] get {
val findbet = bets.find { it.id == idbet } val id = call.parameters["id"] ?: ""
if(findbet==null){ bets.find { it.id == id }?.let { bet ->
call.respond(HttpStatusCode.NotFound, "Bet doesnt find") call.respond(HttpStatusCode.Accepted, bet)
} } ?: call.respond(HttpStatusCode.NotFound, ApiMessage.BetNotFound)
bets.remove(findbet)
findbet as Bet
call.respond(HttpStatusCode.Accepted, findbet)
} }
} }
route("bets/update"){
post{ route("/bets/delete") {
post {
val idbet = call.receive<Map<String, String>>()["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 {
val updatedBetData = call.receive<UpdatedBetData>() val updatedBetData = call.receive<UpdatedBetData>()
val findbet = bets.find { it.id == updatedBetData.id } bets.find { it.id == updatedBetData.id }?.let { findbet ->
if (findbet == null) {
call.respond(HttpStatusCode.NotFound, "Bet not found")
} else {
findbet.endBet = updatedBetData.endBet findbet.endBet = updatedBetData.endBet
findbet.isPrivate = updatedBetData.isPrivate findbet.isPrivate = updatedBetData.isPrivate
findbet.response = updatedBetData.response findbet.response = updatedBetData.response
call.respond(HttpStatusCode.Accepted, findbet) 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)
}
} }
} }
} }

@ -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<Participation>()
fun Application.ParticipationRouter() {
routing {
authenticate {
post("/participations/add") {
hasToken { principal ->
val participation = call.receive<ParticipationRequest>()
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<String>()
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)
}
}
}
}
}

@ -1,81 +1,99 @@
package allin.routing 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.CheckUser
import allin.model.User import allin.model.User
import allin.model.UserRequest
import allin.utils.AppConfig import allin.utils.AppConfig
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.auth.* import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.request.* import io.ktor.server.request.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
import org.ktorm.database.Database
import java.util.*
val users = mutableListOf<User>() val RegexCheckerUser = AppConfig.regexChecker
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
fun Application.UserRouter() { fun Application.UserRouter() {
routing { routing {
route("/users/register"){ route("/users/register") {
post { post {
val TempUser = call.receive<User>() val tempUser = call.receive<UserRequest>()
if (RegexCheckerUser.isEmailInvalid(TempUser.email)){ if (RegexCheckerUser.isEmailInvalid(tempUser.email)) {
call.respond(HttpStatusCode.Forbidden,"Input a valid mail !") call.respond(HttpStatusCode.Forbidden, ApiMessage.InvalidMail)
} }
val user = users.find { it.username == TempUser.username || it.email == TempUser.email } val users = getUserToUserDTO()
if(user == null) { users.find { it.username == tempUser.username || it.email == tempUser.email }?.let { user ->
CryptManagerUser.passwordCrypt(TempUser) call.respond(HttpStatusCode.Conflict, ApiMessage.UserAlreadyExist)
TempUser.token=tokenManagerUser.generateOrReplaceJWTToken(TempUser) } ?: run {
users.add(TempUser) val user = User(
call.respond(HttpStatusCode.Created, TempUser) 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") { route("/users/login") {
post { post {
val checkUser = call.receive<CheckUser>() val checkUser = call.receive<CheckUser>()
val user = users.find { it.username == checkUser.login || it.email == checkUser.login } val user = getUserByUsernameAndPassword(checkUser.login)
if (user != null && CryptManagerUser.passwordDecrypt(user,checkUser.password)) { if (CryptManagerUser.passwordDecrypt(user.second ?: "", checkUser.password)) {
user.token=tokenManagerUser.generateOrReplaceJWTToken(user) user.first?.let { userDtoWithToken ->
call.respond(HttpStatusCode.OK, convertUserToUserDTOToken(user)) userDtoWithToken.token = tokenManagerUser.generateOrReplaceJWTToken(userDtoWithToken)
call.respond(HttpStatusCode.OK, userDtoWithToken)
} ?: call.respond(HttpStatusCode.NotFound, ApiMessage.UserNotFound)
} else { } else {
call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.") call.respond(HttpStatusCode.NotFound, ApiMessage.IncorrectLoginPassword)
} }
} }
} }
route("/users/delete") { authenticate {
post { post("/users/delete") {
val checkUser = call.receive<CheckUser>() hasToken { principal ->
val user = users.find { it.username == checkUser.login || it.email == checkUser.login } verifyUserFromToken(principal) { _, password ->
if (user != null && user.password == checkUser.password) { val checkUser = call.receive<CheckUser>()
users.remove(user)
call.respond(HttpStatusCode.Accepted,convertUserToUserDTO(user)) if (CryptManagerUser.passwordDecrypt(password, checkUser.password)) {
} else { if (!deleteUserByUsername(checkUser.login)) {
call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.") 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") { get("/users/token") {
val principal = call.principal<JWTPrincipal>() hasToken { principal ->
val username = principal!!.payload.getClaim("username").asString() verifyUserFromToken(principal) { userDto, _ ->
val user = users.find { it.username == username } call.respond(HttpStatusCode.OK, userDto)
if (user != null) { }
call.respond(HttpStatusCode.OK,convertUserToUserDTO(user))
} else {
call.respond(HttpStatusCode.NotFound, "User not found with the valid token !")
} }
} }
} }
} }
} }

@ -6,22 +6,22 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import java.text.SimpleDateFormat import java.time.ZonedDateTime
import java.util.* import java.time.format.DateTimeFormatter
@Serializer(Date::class) @Serializer(ZonedDateTime::class)
class DateSerializer : KSerializer<Date> { object ZonedDateTimeSerializer : KSerializer<ZonedDateTime> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING) 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 { override fun serialize(encoder: Encoder, value: ZonedDateTime) {
val dateString = decoder.decodeString() encoder.encodeString(formatter.format(value))
return formatter.parse(dateString)
} }
override fun serialize(encoder: Encoder, value: Date) { override fun deserialize(decoder: Decoder): ZonedDateTime {
val dateString = formatter.format(value) val dateString = decoder.decodeString()
encoder.encodeString(dateString) return ZonedDateTime.parse(dateString, formatter)
} }
} }

@ -4,12 +4,18 @@ import allin.model.User
import org.mindrot.jbcrypt.BCrypt import org.mindrot.jbcrypt.BCrypt
class CryptManager { 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){ 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{ fun passwordDecrypt(password: String, passwordClear: String): Boolean{
return BCrypt.hashpw(password,salt)==user.password return BCrypt.hashpw(passwordClear,"\$2a\$10\$42wsdBeoLKaF6SM9oADONe")==password
}
fun CheckPassword(hashed: String, clear: String): Boolean{
return BCrypt.checkpw(hashed,clear)
} }
} }

@ -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()
}
}

@ -1,5 +1,6 @@
package allin.utils package allin.utils
import allin.dto.UserDTO
import allin.model.User import allin.model.User
import com.auth0.jwt.JWT import com.auth0.jwt.JWT
import com.auth0.jwt.JWTVerifier import com.auth0.jwt.JWTVerifier
@ -10,19 +11,18 @@ import java.util.*
class TokenManager private constructor(val config: HoconApplicationConfig) { class TokenManager private constructor(val config: HoconApplicationConfig) {
val audience=config.property("audience").getString() val audience = config.property("audience").getString()
val secret=config.property("secret").getString() val secret = config.property("secret").getString()
val issuer=config.property("issuer").getString() val issuer = config.property("issuer").getString()
fun generateJWTToken(user : User): String { fun generateJWTToken(user: User): String {
val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde
val token = JWT.create() return JWT.create()
.withAudience(audience) .withAudience(audience)
.withIssuer(issuer) .withIssuer(issuer)
.withClaim("username", user.username) .withClaim("username", user.username)
.withExpiresAt(Date(expirationDate)) .withExpiresAt(Date(expirationDate))
.sign(Algorithm.HMAC256(secret)) .sign(Algorithm.HMAC256(secret))
return token
} }
fun verifyJWTToken(): JWTVerifier { fun verifyJWTToken(): JWTVerifier {
@ -34,26 +34,47 @@ class TokenManager private constructor(val config: HoconApplicationConfig) {
fun generateOrReplaceJWTToken(user: User): String { fun generateOrReplaceJWTToken(user: User): String {
val userToken = getUserToken(user) val userToken = getUserToken(user)
if (userToken != null && !isTokenExpired(userToken)) { return if (userToken != null && !isTokenExpired(userToken)) {
return userToken userToken
} else { } 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 { fun isTokenExpired(token: String): Boolean {
val expirationTime = JWT.decode(token).expiresAt.time val expirationTime = JWT.decode(token).expiresAt.time
return System.currentTimeMillis() > expirationTime return System.currentTimeMillis() > expirationTime
} }
fun getUserToken(user: User): String? { fun getUserToken(user: User): String? = user.token
return 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) val decodedJWT: DecodedJWT = JWT.decode(token)
return decodedJWT.getClaim("username").asString() return decodedJWT.getClaim("username").asString()
} }
companion object { companion object {
private var instance: TokenManager? = null private var instance: TokenManager? = null
fun getInstance(config: HoconApplicationConfig): TokenManager { fun getInstance(config: HoconApplicationConfig): TokenManager {

@ -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"

@ -1,12 +0,0 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="io.netty" level="INFO"/>
</configuration>
Loading…
Cancel
Save