simple api model
This commit is contained in:
75
src/main/kotlin/com/restapi/domain/db.kt
Normal file
75
src/main/kotlin/com/restapi/domain/db.kt
Normal file
@@ -0,0 +1,75 @@
|
||||
package com.restapi.domain
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.Module
|
||||
import com.fasterxml.jackson.databind.SerializationFeature
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.restapi.config.AppConfig.Companion.appConfig
|
||||
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
|
||||
import java.util.*
|
||||
|
||||
data class CurrentUser(
|
||||
val anon: Boolean = true,
|
||||
val userId: String = "",
|
||||
val tenantId: String = ""
|
||||
)
|
||||
|
||||
|
||||
object Session {
|
||||
private val currentUser = object : ThreadLocal<CurrentUser>() {
|
||||
override fun initialValue(): CurrentUser {
|
||||
return CurrentUser()
|
||||
}
|
||||
}
|
||||
private val sc = DatabaseConfig().apply {
|
||||
loadFromProperties(Properties().apply {
|
||||
setProperty("datasource.db.username", appConfig.dbUser())
|
||||
setProperty("datasource.db.password", appConfig.dbPass())
|
||||
setProperty("datasource.db.url", appConfig.dbUrl())
|
||||
setProperty("ebean.migration.run", appConfig.dbRunMigration().toString())
|
||||
})
|
||||
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
|
||||
|
||||
fun Database.findByEntityAndId(entity: String, id: String): DataModel {
|
||||
return find(DataModel::class.java)
|
||||
.where()
|
||||
.eq("uniqueIdentifier", id)
|
||||
.eq("entityName", entity)
|
||||
.findOne() ?: throw DataNotFoundException
|
||||
}
|
||||
|
||||
private fun seqName(entity: String) = "sequence_$entity"
|
||||
fun creatSeq(entity: String): Int {
|
||||
return database.sqlUpdate("CREATE SEQUENCE IF NOT EXISTS ${seqName(entity)} START 1;").execute()
|
||||
}
|
||||
|
||||
fun nextUniqId(entity: String): String {
|
||||
val s = database
|
||||
.sqlQuery("SELECT nextval('${seqName(entity)}');")
|
||||
.findOne()?.getLong("nextval") ?: throw DataNotFoundException
|
||||
return String.format("%s-%s", entity, "$s".padStart(10, '0'))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object DataNotFoundException : Exception() {
|
||||
private fun readResolve(): Any = DataNotFoundException
|
||||
}
|
||||
19
src/main/kotlin/com/restapi/domain/migration.kt
Normal file
19
src/main/kotlin/com/restapi/domain/migration.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.restapi.domain
|
||||
|
||||
import io.ebean.annotation.Platform
|
||||
import io.ebean.dbmigration.DbMigration
|
||||
|
||||
|
||||
object DBMigration {
|
||||
private fun create(){
|
||||
val dbMigration: DbMigration = DbMigration.create()
|
||||
dbMigration.setPlatform(Platform.POSTGRES)
|
||||
|
||||
dbMigration.generateMigration()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
create()
|
||||
}
|
||||
}
|
||||
91
src/main/kotlin/com/restapi/domain/models.kt
Normal file
91
src/main/kotlin/com/restapi/domain/models.kt
Normal file
@@ -0,0 +1,91 @@
|
||||
package com.restapi.domain
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser
|
||||
import com.fasterxml.jackson.databind.DeserializationContext
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||
import io.ebean.Model
|
||||
import io.ebean.annotation.DbArray
|
||||
import io.ebean.annotation.DbJsonB
|
||||
import io.ebean.annotation.Index
|
||||
import io.ebean.annotation.Platform
|
||||
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 sysPk: 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: String = ""
|
||||
|
||||
@WhoCreated
|
||||
var createdBy: String = ""
|
||||
|
||||
@WhoModified
|
||||
var modifiedBy: String? = null
|
||||
|
||||
var deletedOn: LocalDateTime? = null
|
||||
|
||||
var deletedBy: String? = null
|
||||
|
||||
@DbArray
|
||||
var tags: MutableList<String> = arrayListOf()
|
||||
|
||||
@DbJsonB
|
||||
var comments: MutableList<Comments> = arrayListOf()
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Index(unique = true, name = "entity_unique_id", columnNames = ["entity_name", "unique_identifier", "tenant_id"])
|
||||
open class DataModel : BaseModel() {
|
||||
|
||||
@JsonDeserialize(using = SafeStringDeserializer::class)
|
||||
var uniqueIdentifier: String = ""
|
||||
|
||||
@JsonDeserialize(using = SafeStringDeserializer::class)
|
||||
var entityName: String = ""
|
||||
|
||||
@Index(definition = "create index data_jsonb_idx on data_model using GIN (data) ", platforms = [Platform.POSTGRES])
|
||||
@DbJsonB
|
||||
var data: MutableMap<String, Any> = hashMapOf()
|
||||
|
||||
}
|
||||
|
||||
class SafeStringDeserializer : JsonDeserializer<String>() {
|
||||
private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
|
||||
|
||||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): String {
|
||||
|
||||
val text = p.text
|
||||
if (!regex.matches(text)) throw IllegalArgumentException()
|
||||
return text
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user