feature #6: implement PostgresJson
add Article, Citien and User Entities implement Article.findById()
This commit is contained in:
19
.idea/modules/dcproject.main.iml
generated
19
.idea/modules/dcproject.main.iml
generated
File diff suppressed because one or more lines are too long
21
.idea/modules/dcproject.test.iml
generated
21
.idea/modules/dcproject.test.iml
generated
File diff suppressed because one or more lines are too long
@@ -4,6 +4,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|||||||
val ktor_version: String by project
|
val ktor_version: String by project
|
||||||
val kotlin_version: String by project
|
val kotlin_version: String by project
|
||||||
val logback_version: String by project
|
val logback_version: String by project
|
||||||
|
val koinVersion: String by project
|
||||||
|
val postgresjson_version: String by project
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
application
|
application
|
||||||
@@ -32,6 +34,8 @@ dependencies {
|
|||||||
compile("io.ktor:ktor-auth:$ktor_version")
|
compile("io.ktor:ktor-auth:$ktor_version")
|
||||||
compile("io.ktor:ktor-auth-jwt:$ktor_version")
|
compile("io.ktor:ktor-auth-jwt:$ktor_version")
|
||||||
compile("io.ktor:ktor-gson:$ktor_version")
|
compile("io.ktor:ktor-gson:$ktor_version")
|
||||||
|
compile("org.koin:koin-ktor:$koinVersion")
|
||||||
|
compile("fr.postgresjson:postgresjson:$postgresjson_version")
|
||||||
testCompile("io.ktor:ktor-server-tests:$ktor_version")
|
testCompile("io.ktor:ktor-server-tests:$ktor_version")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,5 @@ ktor_version=1.2.2
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
kotlin_version=1.3.40
|
kotlin_version=1.3.40
|
||||||
logback_version=1.2.1
|
logback_version=1.2.1
|
||||||
|
postgresjson_version=0.1
|
||||||
|
koinVersion=2.0.1
|
||||||
|
|||||||
@@ -7,3 +7,15 @@ ktor {
|
|||||||
modules = [ fr.dcproject.ApplicationKt.module ]
|
modules = [ fr.dcproject.ApplicationKt.module ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app {
|
||||||
|
envName = prod
|
||||||
|
}
|
||||||
|
|
||||||
|
db {
|
||||||
|
host = localhost
|
||||||
|
database = dc-project
|
||||||
|
username = dc-project
|
||||||
|
password = dc-project
|
||||||
|
port = 5432
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
-- drop function if exists find_article_by_id(uuid, out json);
|
-- drop function if exists find_article_by_id(uuid, out json);
|
||||||
|
|
||||||
|
select find_article_by_id('12fed2f3-2a7d-434b-87e6-5a9895f9d12d')
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package fr.dcproject
|
|
||||||
|
|
||||||
import fr.dcproject.routes.article
|
|
||||||
import io.ktor.application.Application
|
|
||||||
import io.ktor.application.install
|
|
||||||
import io.ktor.auth.Authentication
|
|
||||||
import io.ktor.features.ContentNegotiation
|
|
||||||
import io.ktor.gson.gson
|
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
|
||||||
import io.ktor.locations.Locations
|
|
||||||
import io.ktor.routing.Routing
|
|
||||||
|
|
||||||
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
|
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
|
||||||
@Suppress("unused") // Referenced in application.conf
|
|
||||||
@kotlin.jvm.JvmOverloads
|
|
||||||
fun Application.module(testing: Boolean = false) {
|
|
||||||
install(Locations) {
|
|
||||||
}
|
|
||||||
|
|
||||||
install(Authentication) {
|
|
||||||
}
|
|
||||||
|
|
||||||
install(ContentNegotiation) {
|
|
||||||
gson {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
install(Routing) {
|
|
||||||
article()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
68
src/fr/dcproject/Application.kt
Normal file
68
src/fr/dcproject/Application.kt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package fr.dcproject
|
||||||
|
|
||||||
|
import fr.dcproject.entity.Article
|
||||||
|
import fr.dcproject.routes.article
|
||||||
|
import io.ktor.application.Application
|
||||||
|
import io.ktor.application.install
|
||||||
|
import io.ktor.auth.Authentication
|
||||||
|
import io.ktor.features.ContentNegotiation
|
||||||
|
import io.ktor.features.DataConversion
|
||||||
|
import io.ktor.gson.gson
|
||||||
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
|
import io.ktor.locations.Locations
|
||||||
|
import io.ktor.routing.Routing
|
||||||
|
import io.ktor.util.KtorExperimentalAPI
|
||||||
|
import org.koin.ktor.ext.Koin
|
||||||
|
import org.koin.ktor.ext.get
|
||||||
|
import java.util.*
|
||||||
|
import fr.dcproject.repository.Article as RepositoryArticle
|
||||||
|
|
||||||
|
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
|
||||||
|
|
||||||
|
@KtorExperimentalAPI
|
||||||
|
@KtorExperimentalLocationsAPI
|
||||||
|
@Suppress("unused") // Referenced in application.conf
|
||||||
|
fun Application.module() {
|
||||||
|
install(Koin) {
|
||||||
|
// Slf4jLog()
|
||||||
|
modules(Module)
|
||||||
|
}
|
||||||
|
|
||||||
|
install(DataConversion) {
|
||||||
|
convert<UUID> {
|
||||||
|
decode { values, _ ->
|
||||||
|
values.singleOrNull()?.let { UUID.fromString(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
encode { value ->
|
||||||
|
when (value) {
|
||||||
|
null -> listOf()
|
||||||
|
is UUID -> listOf(value.toString())
|
||||||
|
else -> throw InternalError("Cannot convert $value as UUID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
convert<Article> {
|
||||||
|
decode { values, _ ->
|
||||||
|
val id = values.singleOrNull()?.let { UUID.fromString(it) }
|
||||||
|
?: throw InternalError("Cannot convert $values to Article")
|
||||||
|
get<RepositoryArticle>().findById(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
install(Locations) {
|
||||||
|
}
|
||||||
|
|
||||||
|
install(Authentication) {
|
||||||
|
}
|
||||||
|
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
gson {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
install(Routing) {
|
||||||
|
article()
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/fr/dcproject/Configuration.kt
Normal file
14
src/fr/dcproject/Configuration.kt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package fr.dcproject
|
||||||
|
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
private var config = ConfigFactory.load()
|
||||||
|
val envName: String = config.getString("app.envName")
|
||||||
|
|
||||||
|
val host: String = config.getString("db.host")
|
||||||
|
val database: String = config.getString("db.database")
|
||||||
|
val username: String = config.getString("db.username")
|
||||||
|
val password: String = config.getString("db.password")
|
||||||
|
val port: Int = config.getInt("db.port")
|
||||||
|
}
|
||||||
25
src/fr/dcproject/Module.kt
Normal file
25
src/fr/dcproject/Module.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package fr.dcproject
|
||||||
|
|
||||||
|
import fr.postgresjson.connexion.Requester
|
||||||
|
import io.ktor.util.KtorExperimentalAPI
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import java.io.File
|
||||||
|
import fr.dcproject.repository.Article as ArticleRepository
|
||||||
|
|
||||||
|
@KtorExperimentalAPI
|
||||||
|
val Module = module {
|
||||||
|
val config = Config()
|
||||||
|
|
||||||
|
single { config }
|
||||||
|
|
||||||
|
single { Requester.RequesterFactory(
|
||||||
|
host = config.host,
|
||||||
|
database = config.database,
|
||||||
|
username = config.username,
|
||||||
|
password = config.password,
|
||||||
|
port = config.port,
|
||||||
|
functionsDirectory = File(this::class.java.getResource("/sql/functions").toURI())
|
||||||
|
).createRequester() }
|
||||||
|
|
||||||
|
single { ArticleRepository(get<Requester>()) }
|
||||||
|
}
|
||||||
18
src/fr/dcproject/entity/Article.kt
Normal file
18
src/fr/dcproject/entity/Article.kt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package fr.dcproject.entity
|
||||||
|
import fr.postgresjson.entity.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
class Article(
|
||||||
|
id: UUID,
|
||||||
|
var versionId: UUID,
|
||||||
|
var versionNumber: Int,
|
||||||
|
var title: String,
|
||||||
|
var annonymous: Boolean,
|
||||||
|
var content: String,
|
||||||
|
var description: String,
|
||||||
|
var tags: List<String>
|
||||||
|
):
|
||||||
|
UuidEntity(id),
|
||||||
|
EntityCreatedAt by EntityCreatedAtImp(),
|
||||||
|
CreatedBy<User> by EntityCreatedByImp()
|
||||||
24
src/fr/dcproject/entity/Citizen.kt
Normal file
24
src/fr/dcproject/entity/Citizen.kt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.postgresjson.entity.EntityCreatedAt
|
||||||
|
import fr.postgresjson.entity.EntityCreatedAtImp
|
||||||
|
import fr.postgresjson.entity.UuidEntity
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
class Citizen(
|
||||||
|
id: UUID,
|
||||||
|
var name: Name,
|
||||||
|
var birthday: String,
|
||||||
|
var userId: String,
|
||||||
|
var voteAnnonymous: Boolean,
|
||||||
|
var followAnnonymous: Boolean,
|
||||||
|
var user: User
|
||||||
|
) : UuidEntity(id),
|
||||||
|
EntityCreatedAt by EntityCreatedAtImp() {
|
||||||
|
data class Name(
|
||||||
|
var civility: String,
|
||||||
|
var lastName: String,
|
||||||
|
var firstName: String
|
||||||
|
)
|
||||||
|
}
|
||||||
17
src/fr/dcproject/entity/User.kt
Normal file
17
src/fr/dcproject/entity/User.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package fr.dcproject.entity
|
||||||
|
|
||||||
|
import fr.postgresjson.entity.*
|
||||||
|
import fr.postgresjson.entity.User
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class User(
|
||||||
|
id: UUID?,
|
||||||
|
var username: String,
|
||||||
|
var blockedAt: DateTime?,
|
||||||
|
override var createdAt: DateTime?,
|
||||||
|
override var updatedAt: DateTime?
|
||||||
|
) : UuidEntity(id),
|
||||||
|
EntityCreatedAt by EntityCreatedAtImp(),
|
||||||
|
EntityUpdatedAt by EntityUpdatedAtImp(),
|
||||||
|
User<UUID?>
|
||||||
22
src/fr/dcproject/repository/Article.kt
Normal file
22
src/fr/dcproject/repository/Article.kt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package fr.dcproject.repository
|
||||||
|
|
||||||
|
import fr.postgresjson.connexion.Requester
|
||||||
|
import fr.postgresjson.entity.EntitiesCollections
|
||||||
|
import fr.postgresjson.repository.RepositoryI
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import fr.dcproject.entity.Article as ArticleEntity
|
||||||
|
|
||||||
|
class Article(override var requester: Requester) : RepositoryI<ArticleEntity> {
|
||||||
|
override val entityName: KClass<fr.dcproject.entity.Article> = ArticleEntity::class
|
||||||
|
|
||||||
|
fun findById(id: UUID): ArticleEntity? {
|
||||||
|
val function = requester.getFunction("find_article_by_id")
|
||||||
|
return when (val e = EntitiesCollections().get(id) as ArticleEntity?) {
|
||||||
|
null -> {
|
||||||
|
function.selectOne("id" to id)
|
||||||
|
}
|
||||||
|
else -> e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package fr.dcproject.routes
|
package fr.dcproject.routes
|
||||||
|
|
||||||
import Paths
|
import Paths
|
||||||
|
import fr.postgresjson.serializer.serialize
|
||||||
import io.ktor.application.call
|
import io.ktor.application.call
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
import io.ktor.locations.get
|
import io.ktor.locations.get
|
||||||
@@ -12,4 +13,7 @@ fun Route.article() {
|
|||||||
get<Paths.ArticlesRequest> {
|
get<Paths.ArticlesRequest> {
|
||||||
call.respondText("todo")
|
call.respondText("todo")
|
||||||
}
|
}
|
||||||
|
get<Paths.ArticleRequest> {
|
||||||
|
call.respondText(it.article.serialize())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
import fr.dcproject.entity.Article
|
||||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||||
import io.ktor.locations.Location
|
import io.ktor.locations.Location
|
||||||
|
|
||||||
@KtorExperimentalLocationsAPI
|
@KtorExperimentalLocationsAPI
|
||||||
object Paths {
|
object Paths {
|
||||||
@Location("/articles") class ArticlesRequest
|
@Location("/articles") class ArticlesRequest
|
||||||
|
@Location("/articles/{article}") class ArticleRequest(val article: Article)
|
||||||
@Location("/articles") class PostArticleRequest
|
@Location("/articles") class PostArticleRequest
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user