[no_ci] Add routes for inject,get and remove image of a user. Update pom.xml dependencies.
continuous-integration/drone/push Build is passing Details

pull/17/head
luevard 9 months ago
parent 3e198b7605
commit e291e0064b

@ -10,7 +10,7 @@
<properties> <properties>
<kotlin.version>1.9.10</kotlin.version> <kotlin.version>1.9.10</kotlin.version>
<serialization.version>1.5.0</serialization.version> <serialization.version>1.5.0</serialization.version>
<ktor_version>2.3.4</ktor_version> <ktor_version>2.3.11</ktor_version>
<kotlin.code.style>official</kotlin.code.style> <kotlin.code.style>official</kotlin.code.style>
<logback_version>1.4.14</logback_version> <logback_version>1.4.14</logback_version>
<slf4j_version>2.0.9</slf4j_version> <slf4j_version>2.0.9</slf4j_version>
@ -34,7 +34,7 @@
<dependency> <dependency>
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
<version>42.7.1</version> <version>42.7.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.ktor</groupId> <groupId>io.ktor</groupId>
@ -44,7 +44,7 @@
<dependency> <dependency>
<groupId>io.github.smiley4</groupId> <groupId>io.github.smiley4</groupId>
<artifactId>ktor-swagger-ui</artifactId> <artifactId>ktor-swagger-ui</artifactId>
<version>2.7.4</version> <version>2.10.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.ktor</groupId> <groupId>io.ktor</groupId>
@ -142,12 +142,12 @@
<dependency> <dependency>
<groupId>io.ktor</groupId> <groupId>io.ktor</groupId>
<artifactId>ktor-server-auth-jwt-jvm</artifactId> <artifactId>ktor-server-auth-jwt-jvm</artifactId>
<version>2.3.4</version> <version>2.3.11</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.swagger.codegen.v3</groupId> <groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-generators</artifactId> <artifactId>swagger-codegen-generators</artifactId>
<version>1.0.38</version> <version>1.0.50</version>
</dependency> </dependency>
<dependency> <dependency>
@ -155,6 +155,12 @@
<artifactId>hamcrest-core</artifactId> <artifactId>hamcrest-core</artifactId>
<version>1.3</version> <version>1.3</version>
</dependency> </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory> <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>

@ -27,6 +27,8 @@ val BET_VERIFY_DELAY = 1.minutes
val data_source = System.getenv()["DATA_SOURCE"] val data_source = System.getenv()["DATA_SOURCE"]
val isCodeFirstContainer = System.getenv()["CODEFIRST_CONTAINER"].orEmpty() val isCodeFirstContainer = System.getenv()["CODEFIRST_CONTAINER"].orEmpty()
val hostIP = "0.0.0.0"
val hostPort = 8080
private val allInDataSource: AllInDataSource = when (data_source) { private val allInDataSource: AllInDataSource = when (data_source) {
"mock" -> MockDataSource() "mock" -> MockDataSource()
@ -38,7 +40,7 @@ val Application.dataSource: AllInDataSource
get() = allInDataSource get() = allInDataSource
fun main() { fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") { embeddedServer(Netty, port = hostPort, host = hostIP) {
extracted() extracted()
}.start(wait = true) }.start(wait = true)
} }

@ -12,4 +12,7 @@ interface UserDataSource {
fun userExists(username: String): Boolean fun userExists(username: String): Boolean
fun emailExists(email: String): Boolean fun emailExists(email: String): Boolean
fun canHaveDailyGift(username: String): Boolean fun canHaveDailyGift(username: String): Boolean
fun addImage(userid: String, image: ByteArray)
fun removeImage(userid: String)
fun getImage(userid: String): ByteArray?
} }

@ -3,8 +3,6 @@ package allin.data.mock
import allin.data.UserDataSource import allin.data.UserDataSource
import allin.dto.UserDTO import allin.dto.UserDTO
import allin.model.User import allin.model.User
import org.ktorm.dsl.eq
import org.ktorm.dsl.or
import java.time.ZonedDateTime import java.time.ZonedDateTime
class MockUserDataSource(private val mockData: MockDataSource.MockData) : UserDataSource { class MockUserDataSource(private val mockData: MockDataSource.MockData) : UserDataSource {
@ -57,4 +55,17 @@ class MockUserDataSource(private val mockData: MockDataSource.MockData) : UserDa
lastGifts[username] = ZonedDateTime.now() lastGifts[username] = ZonedDateTime.now()
return value return value
} }
override fun addImage(userid: String, image: ByteArray) {
TODO("Not yet implemented")
}
override fun removeImage(userid: String) {
TODO("Not yet implemented")
}
override fun getImage(userid: String): ByteArray? {
TODO("Not yet implemented")
}
} }

@ -1,9 +1,7 @@
package allin.data.postgres package allin.data.postgres
import allin.data.UserDataSource import allin.data.UserDataSource
import allin.data.postgres.entities.UserEntity import allin.data.postgres.entities.*
import allin.data.postgres.entities.UsersEntity
import allin.data.postgres.entities.users
import allin.dto.UserDTO import allin.dto.UserDTO
import allin.ext.executeWithResult import allin.ext.executeWithResult
import allin.model.User import allin.model.User
@ -83,4 +81,18 @@ class PostgresUserDataSource(private val database: Database) : UserDataSource {
return false return false
} }
override fun addImage(userid: String, image: ByteArray) {
database.usersimage.add(UserImageEntity {
id = userid
this.image = image
})
}
override fun removeImage(userid: String) {
database.usersimage.removeIf { it.id eq userid }
}
override fun getImage(userid: String): ByteArray? =
database.usersimage.find { it.id eq userid }?.image
} }

@ -0,0 +1,29 @@
package allin.data.postgres.entities
import allin.model.UserImage
import org.ktorm.database.Database
import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table
import org.ktorm.schema.bytes
import org.ktorm.schema.varchar
interface UserImageEntity : Entity<UserImageEntity> {
companion object : Entity.Factory<UserImageEntity>()
var id: String
var image: ByteArray
fun toUserImage() =
UserImage(
id = id,
image = image,
)
}
object UsersImageEntity : Table<UserImageEntity>("userimage") {
val id = varchar("user_id").primaryKey().bindTo { it.id }
val image = bytes("image").bindTo { it.image }
}
val Database.usersimage get() = this.sequenceOf(UsersImageEntity)

@ -9,4 +9,4 @@ data class UserDTO(
val email: String, val email: String,
val nbCoins: Int, val nbCoins: Int,
var token: String? var token: String?
) )

@ -27,4 +27,10 @@ data class UserRequest(
data class CheckUser( data class CheckUser(
val login: String, val login: String,
val password: String val password: String
)
@Serializable
data class UserImage(
val id: String,
val image: ByteArray,
) )

@ -4,17 +4,11 @@ import allin.model.ApiMessage
import io.github.smiley4.ktorswaggerui.dsl.get import io.github.smiley4.ktorswaggerui.dsl.get
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
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 kotlinx.serialization.Serializable
import java.io.File
import java.util.*
@Serializable
data class ImageResponse(val url: String)
fun Application.basicRouter() { fun Application.basicRouter() {
routing { routing {
get("/", { get("/", {
description = "Hello World of Allin API" description = "Hello World of Allin API"
@ -29,28 +23,5 @@ fun Application.basicRouter() {
}) { }) {
call.respond(ApiMessage.WELCOME) call.respond(ApiMessage.WELCOME)
} }
post("/image") {
val base64Image = call.receiveText()
val imageBytes = Base64.getDecoder().decode(base64Image)
val fileName = "${UUID.randomUUID()}.png"
val file = File("uploads/$fileName")
file.parentFile.mkdirs()
file.writeBytes(imageBytes)
val imageUrl = "https://codefirst.iut.uca.fr/containers/AllDev-api/images/$fileName"
call.respond(HttpStatusCode.OK, ImageResponse(imageUrl))
}
get("/images/{fileName}") {
val fileName = call.parameters["fileName"]
val file = File("uploads/$fileName")
if (file.exists()) {
call.respondFile(file)
} else {
call.respond(HttpStatusCode.NotFound, "File not found")
}
}
} }
} }

@ -4,6 +4,9 @@ import allin.dataSource
import allin.dto.UserDTO import allin.dto.UserDTO
import allin.ext.hasToken import allin.ext.hasToken
import allin.ext.verifyUserFromToken import allin.ext.verifyUserFromToken
import allin.hostIP
import allin.hostPort
import allin.isCodeFirstContainer
import allin.model.* import allin.model.*
import allin.utils.AppConfig import allin.utils.AppConfig
import io.github.smiley4.ktorswaggerui.dsl.get import io.github.smiley4.ktorswaggerui.dsl.get
@ -15,6 +18,7 @@ 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 java.io.File
import java.util.* import java.util.*
val RegexCheckerUser = AppConfig.regexChecker val RegexCheckerUser = AppConfig.regexChecker
@ -107,6 +111,23 @@ fun Application.userRouter() {
} }
} }
get("/users/images/{fileName}") {
val fileName = call.parameters["fileName"]
val file = File("images/$fileName.png")
if (file.exists()) {
call.respondFile(file)
} else {
val imageBytes = userDataSource.getImage(fileName.toString())
if (imageBytes != null) {
file.parentFile.mkdirs()
file.writeBytes(imageBytes)
call.respondFile(file)
} else {
call.respond(HttpStatusCode.NotFound, "File not found")
}
}
}
authenticate { authenticate {
post("/users/delete", { post("/users/delete", {
description = "Allow you to delete your account" description = "Allow you to delete your account"
@ -198,6 +219,47 @@ fun Application.userRouter() {
} }
} }
} }
post("/users/image", {
description = "Allow you to add a profil image"
request {
headerParameter<JWTPrincipal>("JWT token of the logged user")
body<CheckUser> {
description = "User information"
}
}
response {
HttpStatusCode.Accepted to {
description = "Image added"
}
HttpStatusCode.NotFound to {
description = "User not found"
body(ApiMessage.INCORRECT_LOGIN_PASSWORD)
}
}
}) {
hasToken { principal ->
verifyUserFromToken(userDataSource, principal) { user , _ ->
val base64Image = call.receiveText()
val imageBytes = Base64.getDecoder().decode(base64Image)
val urlfile = "images/${user.id}"
val file = File("${urlfile}.png")
file.parentFile.mkdirs()
file.writeBytes(imageBytes)
userDataSource.removeImage(user.id)
userDataSource.addImage(user.id,imageBytes)
if(isCodeFirstContainer.isEmpty()){
call.respond(HttpStatusCode.OK, "http://${hostIP}:${hostPort}/users/${urlfile}")
}
else call.respond(HttpStatusCode.OK, "${isCodeFirstContainer}/${urlfile}")
}
}
}
} }
} }
} }

@ -1,4 +1,5 @@
package allin package allin
class ApplicationTest { class ApplicationTest {
} }

Loading…
Cancel
Save