simple api model
This commit is contained in:
106
src/main/kotlin/com/readymixerp/Main.kt
Normal file
106
src/main/kotlin/com/readymixerp/Main.kt
Normal file
@@ -0,0 +1,106 @@
|
||||
package com.readymixerp
|
||||
|
||||
import com.readymixerp.domain.DataModel
|
||||
import com.readymixerp.domain.Session
|
||||
import com.readymixerp.domain.Session.database
|
||||
import io.ebean.DuplicateKeyException
|
||||
import io.ebean.RawSql
|
||||
import io.ebean.RawSqlBuilder
|
||||
import io.javalin.Javalin
|
||||
import io.javalin.apibuilder.ApiBuilder.before
|
||||
import io.javalin.apibuilder.ApiBuilder.get
|
||||
import io.javalin.apibuilder.ApiBuilder.post
|
||||
import io.javalin.apibuilder.ApiBuilder.delete
|
||||
import io.javalin.apibuilder.ApiBuilder.path
|
||||
import io.javalin.apibuilder.ApiBuilder.put
|
||||
import io.javalin.apibuilder.ApiBuilder.patch
|
||||
import io.javalin.http.*
|
||||
import io.javalin.json.JavalinJackson
|
||||
import io.javalin.plugin.bundled.CorsContainer
|
||||
import java.time.LocalDateTime
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Javalin
|
||||
.create { cfg ->
|
||||
cfg.http.generateEtags = true
|
||||
cfg.plugins.enableCors { container ->
|
||||
container.add {
|
||||
it.allowHost(
|
||||
"http://localhost:5173",
|
||||
"https://www.readymixerp.com",
|
||||
"https://app.readymixerp.com"
|
||||
)
|
||||
}
|
||||
}
|
||||
cfg.http.defaultContentType = ContentType.JSON
|
||||
cfg.compression.gzipOnly()
|
||||
cfg.jsonMapper(JavalinJackson(Session.objectMapper))
|
||||
}
|
||||
.routes {
|
||||
before("/*") {
|
||||
//validate, auth token
|
||||
}
|
||||
path("/api") {
|
||||
get("/{entity}/{id}") {
|
||||
it.json(
|
||||
database.find(DataModel::class.java, it.pathParam("id")) ?: throw NotFoundResponse()
|
||||
)
|
||||
}
|
||||
post("/{entity}/query") {
|
||||
val sql = it.bodyAsClass<Query>()
|
||||
it.json(
|
||||
database.find(DataModel::class.java)
|
||||
.setRawSql(
|
||||
RawSqlBuilder.parse(sql.sql).create()
|
||||
).apply {
|
||||
sql.params.forEach { (t, u) ->
|
||||
setParameter(t, u)
|
||||
}
|
||||
}
|
||||
.findList()
|
||||
)
|
||||
|
||||
}
|
||||
post("/{entity}") {
|
||||
database.save(
|
||||
it.bodyAsClass<DataModel>()
|
||||
)
|
||||
}
|
||||
put("/{entity}/{id}") {
|
||||
val e = database.find(DataModel::class.java, it.pathParam("id")) ?: throw NotFoundResponse()
|
||||
val newData = it.bodyAsClass<Map<String,Any>>()
|
||||
e.data.putAll(newData)
|
||||
e.update()
|
||||
}
|
||||
patch("/{entity}/{id}") {
|
||||
val e = database.find(DataModel::class.java, it.pathParam("id")) ?: throw NotFoundResponse()
|
||||
val pv = it.bodyAsClass<PatchValue>()
|
||||
e.data[pv.key] = pv.value;
|
||||
e.update()
|
||||
}
|
||||
delete("/{entity}/{id}") {
|
||||
val id = it.pathParam("id")
|
||||
val e = database.find(DataModel::class.java, id) ?: throw NotFoundResponse()
|
||||
e.deletedBy = Session.currentUser()
|
||||
e.deletedOn = LocalDateTime.now()
|
||||
e.update()
|
||||
e.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
.exception(DuplicateKeyException::class.java) { _, ctx ->
|
||||
ctx.json(
|
||||
mapOf(
|
||||
"error" to "Duplicate Data"
|
||||
)
|
||||
).status(HttpStatus.CONFLICT)
|
||||
}
|
||||
.start(9001)
|
||||
}
|
||||
|
||||
data class Query(
|
||||
val sql: String,
|
||||
val params: Map<String, Any>
|
||||
)
|
||||
|
||||
data class PatchValue(val key: String, val value: Any)
|
||||
39
src/main/kotlin/com/readymixerp/domain/db.kt
Normal file
39
src/main/kotlin/com/readymixerp/domain/db.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.readymixerp.domain
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.SerializationFeature
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import io.ebean.Database
|
||||
import io.ebean.DatabaseFactory
|
||||
import io.ebean.config.CurrentTenantProvider
|
||||
import io.ebean.config.CurrentUserProvider
|
||||
import io.ebean.config.DatabaseConfig
|
||||
import io.ebean.config.TenantMode
|
||||
|
||||
data class CurrentUser(
|
||||
val anon: Boolean = true,
|
||||
val userId:Long = 0,
|
||||
val tenantId: Long = 0
|
||||
)
|
||||
object Session {
|
||||
private val currentUser = object: ThreadLocal<CurrentUser>() {
|
||||
override fun initialValue(): CurrentUser {
|
||||
return CurrentUser()
|
||||
}
|
||||
}
|
||||
private val sc = DatabaseConfig().apply {
|
||||
loadFromProperties()
|
||||
tenantMode = TenantMode.PARTITION
|
||||
currentTenantProvider = CurrentTenantProvider { currentUser.get().tenantId }
|
||||
currentUserProvider = CurrentUserProvider { currentUser.get().userId }
|
||||
}
|
||||
|
||||
val database: Database = DatabaseFactory.create(sc)
|
||||
val objectMapper = jacksonObjectMapper().apply {
|
||||
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
|
||||
findAndRegisterModules()
|
||||
}
|
||||
fun currentUser() = currentUser.get().userId
|
||||
|
||||
}
|
||||
19
src/main/kotlin/com/readymixerp/domain/migration.kt
Normal file
19
src/main/kotlin/com/readymixerp/domain/migration.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.readymixerp.domain
|
||||
|
||||
import io.ebean.annotation.Platform
|
||||
import io.ebean.dbmigration.DbMigration
|
||||
|
||||
|
||||
object DBMigration {
|
||||
fun create(){
|
||||
val dbMigration: DbMigration = DbMigration.create()
|
||||
dbMigration.setPlatform(Platform.POSTGRES)
|
||||
|
||||
dbMigration.generateMigration()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
create()
|
||||
}
|
||||
}
|
||||
69
src/main/kotlin/com/readymixerp/domain/models.kt
Normal file
69
src/main/kotlin/com/readymixerp/domain/models.kt
Normal file
@@ -0,0 +1,69 @@
|
||||
package com.readymixerp.domain
|
||||
|
||||
import io.ebean.Model
|
||||
import io.ebean.annotation.DbArray
|
||||
import io.ebean.annotation.DbJsonB
|
||||
import io.ebean.annotation.SoftDelete
|
||||
import io.ebean.annotation.TenantId
|
||||
import io.ebean.annotation.WhenCreated
|
||||
import io.ebean.annotation.WhenModified
|
||||
import io.ebean.annotation.WhoCreated
|
||||
import io.ebean.annotation.WhoModified
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.Entity
|
||||
import javax.persistence.GeneratedValue
|
||||
import javax.persistence.Id
|
||||
import javax.persistence.MappedSuperclass
|
||||
import javax.persistence.Version
|
||||
|
||||
data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now())
|
||||
|
||||
@MappedSuperclass
|
||||
abstract class BaseModel : Model() {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
var id: Long = 0
|
||||
|
||||
@SoftDelete
|
||||
var deleted: Boolean = false
|
||||
|
||||
@Version
|
||||
var version: Int = 0
|
||||
|
||||
@WhenCreated
|
||||
var createdAt: LocalDateTime = LocalDateTime.now()
|
||||
|
||||
@WhenModified
|
||||
var modifiedAt: LocalDateTime? = null
|
||||
|
||||
@TenantId
|
||||
var tenantId: Long = 0L
|
||||
|
||||
@WhoCreated
|
||||
var createdBy: Long = 0L
|
||||
|
||||
@WhoModified
|
||||
var modifiedBy: Long? = null
|
||||
|
||||
var deletedOn: LocalDateTime? = null
|
||||
|
||||
var deletedBy: Long? = null
|
||||
|
||||
@DbJsonB
|
||||
var data: MutableMap<String, Any> = hashMapOf()
|
||||
|
||||
@DbArray
|
||||
var tags: MutableList<String> = arrayListOf()
|
||||
|
||||
@DbJsonB
|
||||
var comments: MutableList<Comments> = arrayListOf()
|
||||
}
|
||||
|
||||
@Entity
|
||||
open class DataModel : BaseModel() {
|
||||
|
||||
var uniqueIdentifier: String = ""
|
||||
var entityName: String = ""
|
||||
|
||||
|
||||
}
|
||||
32
src/main/resources/dbmigration/1.0__initial.sql
Normal file
32
src/main/resources/dbmigration/1.0__initial.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
-- apply changes
|
||||
create table data_model
|
||||
(
|
||||
id bigint generated by default as identity not null,
|
||||
tenant_id bigint not null,
|
||||
deleted_on timestamp,
|
||||
deleted_by bigint,
|
||||
deleted boolean default false not null,
|
||||
version integer not null,
|
||||
created_at timestamp not null,
|
||||
modified_at timestamp not null,
|
||||
created_by bigint not null,
|
||||
modified_by bigint not null,
|
||||
data jsonb not null,
|
||||
tags varchar[] not null,
|
||||
comments jsonb not null,
|
||||
unique_identifier varchar(255) not null,
|
||||
entity_name varchar(255) not null,
|
||||
constraint pk_data_model primary key (id)
|
||||
);
|
||||
|
||||
create unique index data_model_uniq_identifier on data_model (unique_identifier);
|
||||
create index data_json_jdx on data_model using GIN (data);
|
||||
create index data_json_meta_data on data_model (tenant_id,
|
||||
deleted,
|
||||
version,
|
||||
created_at,
|
||||
modified_at,
|
||||
created_by,
|
||||
modified_by,
|
||||
entity_name
|
||||
);
|
||||
22
src/main/resources/dbmigration/model/1.0__initial.model.xml
Normal file
22
src/main/resources/dbmigration/model/1.0__initial.model.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
<createTable name="data_model" pkName="pk_data_model">
|
||||
<column name="id" type="bigint" primaryKey="true"/>
|
||||
<column name="tenant_id" type="bigint" notnull="true"/>
|
||||
<column name="deleted_on" type="localdatetime"/>
|
||||
<column name="deleted_by" type="bigint"/>
|
||||
<column name="data" type="jsonb" notnull="true"/>
|
||||
<column name="tags" type="varchar[]" notnull="true"/>
|
||||
<column name="comments" type="jsonb" notnull="true"/>
|
||||
<column name="unique_identifier" type="varchar" notnull="true"/>
|
||||
<column name="entity_name" type="varchar" notnull="true"/>
|
||||
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||
<column name="version" type="integer" notnull="true"/>
|
||||
<column name="created_at" type="localdatetime" notnull="true"/>
|
||||
<column name="modified_at" type="localdatetime" notnull="true"/>
|
||||
<column name="created_by" type="bigint" notnull="true"/>
|
||||
<column name="modified_by" type="bigint" notnull="true"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
</migration>
|
||||
4
src/main/resources/ebean.mf
Normal file
4
src/main/resources/ebean.mf
Normal file
@@ -0,0 +1,4 @@
|
||||
entity-packages: com.readymixerp.domain
|
||||
querybean-packages: com.readymixerp.domain
|
||||
transactional-packages: com.readymixerp
|
||||
profile-location: true
|
||||
Reference in New Issue
Block a user