✨ restore git files
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
e3f6e59695
commit
2f4d5143f2
@ -0,0 +1,70 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: CI
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
|
||||
steps:
|
||||
- name: compilation
|
||||
image: maven:3-openjdk-11
|
||||
commands:
|
||||
- cd Sources
|
||||
- mvn clean package
|
||||
|
||||
|
||||
---
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: CD
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
steps:
|
||||
|
||||
- name: hadolint
|
||||
image: hadolint/hadolint:latest-alpine
|
||||
commands:
|
||||
- hadolint Sources/Dockerfile
|
||||
|
||||
- name: deploy-container-postgres
|
||||
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
|
||||
environment:
|
||||
IMAGENAME: postgres:latest
|
||||
CONTAINERNAME: postgresapi
|
||||
COMMAND: create
|
||||
OVERWRITE: false
|
||||
PRIVATE: false
|
||||
ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier
|
||||
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_PASSWORD:
|
||||
from_secret: db_root_password
|
||||
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_DB:
|
||||
from_secret: db_database
|
||||
CODEFIRST_CLIENTDRONE_ENV_POSTGRES_USER:
|
||||
from_secret: db_user
|
||||
|
||||
- name: docker-image
|
||||
image: plugins/docker
|
||||
settings:
|
||||
dockerfile: Sources/Dockerfile
|
||||
context: Sources
|
||||
registry: hub.codefirst.iut.uca.fr
|
||||
repo: hub.codefirst.iut.uca.fr/lucas.evard/api
|
||||
username:
|
||||
from_secret: SECRET_REGISTRY_USERNAME
|
||||
password:
|
||||
from_secret: SECRET_REGISTRY_PASSWORD
|
||||
|
||||
- name: deploy-container
|
||||
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
|
||||
environment:
|
||||
IMAGENAME: hub.codefirst.iut.uca.fr/lucas.evard/api:latest
|
||||
CONTAINERNAME: api
|
||||
COMMAND: create
|
||||
OVERWRITE: true
|
||||
ADMINS: lucasevard,emrekartal,arthurvalin,lucasdelanier
|
||||
depends_on: [docker-image]
|
||||
|
@ -0,0 +1,36 @@
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 116 KiB |
@ -0,0 +1,94 @@
|
||||
<div align = center>
|
||||
|
||||
<img src="Documentation/Images/Banner-AllIn.png" />
|
||||
|
||||
---
|
||||
|
||||
![Docker](https://img.shields.io/badge/Docker-2496ED.svg?style=for-the-badge&logo=Docker&logoColor=white)
|
||||
![Kotlin](https://img.shields.io/badge/Kotlin-7F52FF.svg?style=for-the-badge&logo=Kotlin&logoColor=white)
|
||||
![PostgreSQL](https://img.shields.io/badge/PostgreSQL-4169E1.svg?style=for-the-badge&logo=PostgreSQL&logoColor=white)
|
||||
![Swagger](https://img.shields.io/badge/Swagger-85EA2D.svg?style=for-the-badge&logo=Swagger&logoColor=black)
|
||||
|
||||
---
|
||||
|
||||
[Présentation](#api---all-in) | [Répartition du dépôt](#répartition-du-gitlab) | [Technologies](#technologies) | [Outils](#outils) | [Controllers](#controllers) | [Deploiement](#déploiement) | [Wiki](https://codefirst.iut.uca.fr/git/AllDev/Gestion_de_projet/wiki)
|
||||
|
||||
</div>
|
||||
|
||||
### API - ALL IN !
|
||||
|
||||
|
||||
**Contexte** : Api pour le projet universitaire de troisieme année (B.U.T Informatique de Clermont-Ferrand) intitulé *All In*.
|
||||
</br>
|
||||
|
||||
**Description** : Ce dépôt contient l'ensemble du code de l'API pour la partie back-end de l'application *ALL IN* et la connexion à la base de données.
|
||||
</br>
|
||||
|
||||
**Utilité** : :information_source: Son rôle est de simplifier le processus de développement des interfaces clients d'*All In*, que ce soit pour les applications iOS, Android ou tout autre futur client.
|
||||
</br>
|
||||
|
||||
# Répartition du gitlab
|
||||
|
||||
[**Sources**](Sources) : **Code de l'application**
|
||||
|
||||
[**Documentation**](Documentation) : **Documentation de l'application**
|
||||
|
||||
# Technologies
|
||||
|
||||
<img src="Documentation/Images/Ktor.png" width="50"/> **KTOR**
|
||||
|
||||
- L'API est réalisée avec le framework Ktor, en raison des nombreux avantages qu'il offre. Sa facilité de prise en main, sa légèreté en termes de code, son utilisation d'un langage moderne (*Kotlin*), ainsi qu'une documentation détaillée et complète du framework.
|
||||
|
||||
<img src="Documentation/Images/PostgreSQL.png" width="50"/> **PostgreSQL**
|
||||
|
||||
- Pour stocker les données des utilisateurs et des paris, nous utilisons une base de données PostgreSQL sur laquelle l'API s'appuie pour récupérer et enregistrer des données. En raison de sa conformité aux dernières normes SQL, garantissant une compatibilité et une évolutivité optimales, ainsi que de son efficacité à gérer un grand nombre de données.
|
||||
</br>
|
||||
|
||||
# Outils
|
||||
|
||||
Pour la partie API, nous utilisons plusieurs outils et méthodes :
|
||||
|
||||
### Swagger
|
||||
|
||||
L'utilisation d'un Swagger dans le développement d'une API facilite la gestion, la documentation et la compréhension des endpoints, optimisant ainsi le processus de création et favorisant une collaboration efficace entre les équipes.
|
||||
</br>
|
||||
|
||||
Lien vers le Swagger de l'API All In : [Swagger All IN]()
|
||||
|
||||
### JWT
|
||||
|
||||
Pour renforcer la sécurité en permettant une authentification et une autorisation fiables, nous utilisons la bibliothèque JWT (JSON Web Tokens). Cela garantit l'intégrité des données échangées et facilite la gestion efficace et décentralisée des sessions utilisateur.
|
||||
|
||||
### DTO et Mapper
|
||||
|
||||
Afin de garantir la sécurité des échanges d'informations entre notre application et la base de données, nous avons utiliser des mappers et des DTO.
|
||||
Ils sont essentiels pour une transmission sécurisée des données entre les différentes couches de l'application.
|
||||
Contribuent ainsi à maintenir l'intégrité et la cohérence des données tout au long du processus.
|
||||
|
||||
# Controllers
|
||||
|
||||
Notre API est organisée en utilisant une séparation logique des routes par le biais de controllers.
|
||||
Deux controllers principaux structurent notre application :
|
||||
|
||||
### Controller User :walking:
|
||||
|
||||
Ce controller est dédié à l'authentification et aux données liées à l'utilisateur.
|
||||
|
||||
### Controller BET :money_with_wings:
|
||||
|
||||
Le controller BET gère toutes les opérations liées aux paris. Il permet de récupérer, ajouter, modifier et supprimer des paris.
|
||||
|
||||
:white_check_mark: Cette séparation permet une gestion plus claire et modulaire des fonctionnalités de l'API, facilitant la maintenance et l'extension de notre système.
|
||||
|
||||
# Déploiement
|
||||
|
||||
Le déploiement est réalisé sur Code First via les services **Drone** et **Runner** ! :rocket:
|
||||
|
||||
Lien de l'API sur codefirst : [API All In](https://codefirst.iut.uca.fr/containers/AllDev-api)
|
||||
|
||||
|
||||
<div align = center>
|
||||
|
||||
© AllDev - API
|
||||
|
||||
</div>
|
@ -0,0 +1,12 @@
|
||||
FROM maven:3-openjdk-11 AS build
|
||||
COPY . /home/maven/src
|
||||
WORKDIR /home/maven/src
|
||||
RUN mvn clean package
|
||||
|
||||
FROM openjdk:11
|
||||
EXPOSE 8080
|
||||
|
||||
RUN mkdir /app
|
||||
|
||||
COPY --from=build /home/maven/src/target/*-with-dependencies.jar /app/ktor-docker-sample.jar
|
||||
ENTRYPOINT ["java", "-jar", "/app/ktor-docker-sample.jar"]
|
@ -0,0 +1,225 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>allin</groupId>
|
||||
<artifactId>allin-api</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<name>allin-api</name>
|
||||
<description>allin-api</description>
|
||||
<properties>
|
||||
<kotlin.version>1.9.10</kotlin.version>
|
||||
<serialization.version>1.5.0</serialization.version>
|
||||
<ktor_version>2.3.4</ktor_version>
|
||||
<kotlin.code.style>official</kotlin.code.style>
|
||||
<kotlin_version>1.9.10</kotlin_version>
|
||||
<logback_version>1.4.11</logback_version>
|
||||
<slf4j_version>2.0.9</slf4j_version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
|
||||
<main.class>allin.ApplicationKt</main.class>
|
||||
</properties>
|
||||
<repositories>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.mindrot</groupId>
|
||||
<artifactId>jbcrypt</artifactId>
|
||||
<version>0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-core-jvm</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-netty-jvm</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ktorm</groupId>
|
||||
<artifactId>ktorm-core</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-tests-jvm</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-core</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>2.2.224</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-content-negotiation-jvm</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-html-builder-jvm</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-serialization-kotlinx-json-jvm</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-client-content-negotiation-jvm</artifactId>
|
||||
<version>${ktor_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit</artifactId>
|
||||
<version>${kotlin_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-debug</artifactId>
|
||||
<version>1.6.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-serialization-core-jvm</artifactId>
|
||||
<version>1.5.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-auth-jvm</artifactId>
|
||||
<version>2.3.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.ktor</groupId>
|
||||
<artifactId>ktor-server-auth-jwt-jvm</artifactId>
|
||||
<version>2.3.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${project.basedir}/src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<version>${kotlin_version}</version>
|
||||
<configuration>
|
||||
<jvmTarget>1.8</jvmTarget>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>${main.class}</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>${main.class}</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>assemble-all</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<compilerPlugins>
|
||||
<plugin>kotlinx-serialization</plugin>
|
||||
</compilerPlugins>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-serialization</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,43 @@
|
||||
package allin
|
||||
|
||||
import allin.routing.BasicRouting
|
||||
import allin.routing.BetRouter
|
||||
import allin.routing.UserRouter
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.application.*
|
||||
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.*
|
||||
|
||||
fun main() {
|
||||
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
|
||||
extracted()
|
||||
}.start(wait = true)
|
||||
}
|
||||
|
||||
private fun Application.extracted() {
|
||||
val config=HoconApplicationConfig(ConfigFactory.load())
|
||||
val tokenManager= TokenManager(config)
|
||||
authentication {
|
||||
jwt {
|
||||
verifier(tokenManager.verifyJWTToken())
|
||||
realm=config.property("realm").getString()
|
||||
validate { jwtCredential ->
|
||||
if(jwtCredential.payload.getClaim("username").asString().isNotEmpty())
|
||||
JWTPrincipal(jwtCredential.payload)
|
||||
else null
|
||||
}
|
||||
}
|
||||
}
|
||||
install(ContentNegotiation) {
|
||||
json()
|
||||
}
|
||||
BasicRouting()
|
||||
UserRouter()
|
||||
BetRouter()
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
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)
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package allin.entities
|
||||
|
||||
import org.ktorm.schema.Table
|
||||
import org.ktorm.schema.int
|
||||
import org.ktorm.schema.varchar
|
||||
|
||||
object UserEntity : Table<Nothing>("user") {
|
||||
val id = int("id").primaryKey()
|
||||
val username = varchar("username")
|
||||
val password = varchar("password")
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package allin.model
|
||||
|
||||
import allin.serializer.DateSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.*
|
||||
|
||||
@Serializable
|
||||
data class Bet(val id: Int, val theme: String, val sentenceBet: String, @Serializable(DateSerializer::class) val endRegistration: Date, @Serializable(DateSerializer::class) var endBet : Date, var isPrivate : Boolean, var response : MutableList<String>)
|
||||
|
||||
@Serializable
|
||||
data class UpdatedBetData(val id: Int,@Serializable(DateSerializer::class) val endBet: Date, val isPrivate: Boolean, val response: MutableList<String>)
|
@ -0,0 +1,9 @@
|
||||
package allin.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class User(val username: String, val email: String, var password: String, var nbCoins: Int = 1000, var token: String? = null)
|
||||
|
||||
@Serializable
|
||||
data class CheckUser(val login: String,val password: String)
|
@ -0,0 +1,13 @@
|
||||
package allin.routing
|
||||
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Application.BasicRouting(){
|
||||
routing {
|
||||
get("/") {
|
||||
call.respond("Bienvenue sur l'API de AlLin!")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package allin.routing
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.routing.*
|
||||
import allin.model.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.response.*
|
||||
|
||||
val bets = mutableListOf<Bet>()
|
||||
fun Application.BetRouter(){
|
||||
routing{
|
||||
route("/bets/add"){
|
||||
post{
|
||||
val bet = call.receive<Bet>()
|
||||
val findbet = bets.find { it.id == bet.id }
|
||||
if(findbet==null){
|
||||
bets.add(bet)
|
||||
call.respond(HttpStatusCode.Created, bet)
|
||||
}
|
||||
call.respond(HttpStatusCode.Conflict,"Bet already exist")
|
||||
}
|
||||
}
|
||||
route("/bets/delete"){
|
||||
post{
|
||||
val idbet = call.receive<Map<String, Int>>()["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/update"){
|
||||
post{
|
||||
val updatedBetData = call.receive<UpdatedBetData>()
|
||||
val findbet = bets.find { it.id == updatedBetData.id }
|
||||
if (findbet == null) {
|
||||
call.respond(HttpStatusCode.NotFound, "Bet not found")
|
||||
} else {
|
||||
findbet.endBet = updatedBetData.endBet
|
||||
findbet.isPrivate = updatedBetData.isPrivate
|
||||
findbet.response = updatedBetData.response
|
||||
call.respond(HttpStatusCode.Accepted, findbet)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package allin.routing
|
||||
|
||||
import allin.dto.*
|
||||
import allin.model.CheckUser
|
||||
import allin.model.User
|
||||
import allin.utils.CryptManager
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import io.ktor.http.*
|
||||
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.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import allin.utils.RegexChecker
|
||||
import allin.utils.TokenManager
|
||||
|
||||
val users = mutableListOf<User>()
|
||||
val tokenManager= TokenManager(HoconApplicationConfig(ConfigFactory.load()))
|
||||
val RegexChecker= RegexChecker()
|
||||
val CryptManager= CryptManager()
|
||||
fun Application.UserRouter() {
|
||||
|
||||
routing {
|
||||
route("/users/register"){
|
||||
post {
|
||||
val TempUser = call.receive<User>()
|
||||
if (RegexChecker.isEmailInvalid(TempUser.email)){
|
||||
call.respond(HttpStatusCode.Forbidden,"Input a valid mail !")
|
||||
}
|
||||
val user = users.find { it.username == TempUser.username || it.email == TempUser.email }
|
||||
if(user == null) {
|
||||
CryptManager.passwordCrypt(TempUser)
|
||||
users.add(TempUser)
|
||||
call.respond(HttpStatusCode.Created, TempUser)
|
||||
}
|
||||
call.respond(HttpStatusCode.Conflict,"Mail or/and username already exist")
|
||||
}
|
||||
}
|
||||
|
||||
route("/users/login") {
|
||||
post {
|
||||
val checkUser = call.receive<CheckUser>()
|
||||
val user = users.find { it.username == checkUser.login || it.email == checkUser.login }
|
||||
if (user != null && CryptManager.passwordDecrypt(user,checkUser.password)) {
|
||||
user.token=tokenManager.generateOrReplaceJWTToken(user)
|
||||
call.respond(HttpStatusCode.OK, convertUserToUserDTOToken(user))
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound,"Login and/or password incorrect.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
route("/users/delete") {
|
||||
post {
|
||||
val checkUser = call.receive<CheckUser>()
|
||||
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 {
|
||||
get("/users/token") {
|
||||
val principal = call.principal<JWTPrincipal>()
|
||||
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 !")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package allin.serializer
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@Serializer(Date::class)
|
||||
class DateSerializer : KSerializer<Date> {
|
||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING)
|
||||
|
||||
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.FRANCE)
|
||||
|
||||
override fun deserialize(decoder: Decoder): Date {
|
||||
val dateString = decoder.decodeString()
|
||||
return formatter.parse(dateString)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Date) {
|
||||
val dateString = formatter.format(value)
|
||||
encoder.encodeString(dateString)
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package allin.utils
|
||||
|
||||
import allin.model.User
|
||||
import org.mindrot.jbcrypt.BCrypt
|
||||
|
||||
class CryptManager {
|
||||
val salt=BCrypt.gensalt()
|
||||
fun passwordCrypt(user: User){
|
||||
user.password=BCrypt.hashpw(user.password,salt)
|
||||
|
||||
}
|
||||
fun passwordDecrypt(user: User, password: String): Boolean{
|
||||
return BCrypt.hashpw(password,salt)==user.password
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package allin.utils
|
||||
|
||||
class RegexChecker {
|
||||
|
||||
private val emailRegex="^[A-Za-z0-9+_.-]+@(.+)$"
|
||||
|
||||
|
||||
fun isEmailInvalid(email: String): Boolean {
|
||||
val emailRegex = Regex(emailRegex)
|
||||
return !emailRegex.matches(email)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package allin.utils
|
||||
|
||||
import allin.model.User
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.JWTVerifier
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import io.ktor.server.config.*
|
||||
import java.util.*
|
||||
|
||||
class TokenManager (val config: HoconApplicationConfig){
|
||||
|
||||
val audience=config.property("audience").getString()
|
||||
val secret=config.property("secret").getString()
|
||||
val issuer=config.property("issuer").getString()
|
||||
private fun generateJWTToken(user : User): String {
|
||||
val expirationDate = System.currentTimeMillis() + 604800000 // une semaine en miliseconde
|
||||
|
||||
val token = JWT.create()
|
||||
.withAudience(audience)
|
||||
.withIssuer(issuer)
|
||||
.withClaim("username", user.username)
|
||||
.withExpiresAt(Date(expirationDate))
|
||||
.sign(Algorithm.HMAC256(secret))
|
||||
return token
|
||||
}
|
||||
|
||||
fun verifyJWTToken(): JWTVerifier {
|
||||
return JWT.require(Algorithm.HMAC256(secret))
|
||||
.withAudience(audience)
|
||||
.withIssuer(issuer)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun generateOrReplaceJWTToken(user: User): String {
|
||||
val userToken = getUserToken(user)
|
||||
if (userToken != null && !isTokenExpired(userToken)) {
|
||||
return userToken
|
||||
} else {
|
||||
return generateJWTToken(user)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isTokenExpired(token: String): Boolean {
|
||||
val expirationTime = JWT.decode(token).expiresAt.time
|
||||
return System.currentTimeMillis() > expirationTime
|
||||
}
|
||||
|
||||
private fun getUserToken(user: User): String? {
|
||||
return user.token
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
secret="secret"
|
||||
issuer="http://0.0.0.0:8080/"
|
||||
audience="http://0.0.0.0:8080/"
|
||||
realm="Access to main page"
|
@ -0,0 +1,12 @@
|
||||
<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>
|
@ -0,0 +1,4 @@
|
||||
package allin
|
||||
|
||||
class ApplicationTest {
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,4 @@
|
||||
secret="secret"
|
||||
issuer="http://0.0.0.0:8080/"
|
||||
audience="http://0.0.0.0:8080/"
|
||||
realm="Access to main page"
|
@ -0,0 +1,12 @@
|
||||
<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>
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,4 @@
|
||||
[ViewState]
|
||||
Mode=
|
||||
Vid=
|
||||
FolderType=Generic
|
Loading…
Reference in new issue