remove unused stuff

This commit is contained in:
gowthaman 2024-05-23 13:27:09 +05:30
parent ce622a118f
commit 0c9313b77c
5 changed files with 67 additions and 240 deletions

View File

@ -8,7 +8,7 @@ Authorization: {{auth-token}}
"number": "KA01HD6677",
"owner": "gowthaman"
},
"uniqueIdentifier": ""
"uniqueIdentifier": "KA01HD6677"
}
### create row
@ -52,7 +52,7 @@ GET http://localhost:9001/api/log/log-0000000001
Authorization: Bearer {{auth-token}}
### get row
GET http://localhost:9001/api/vehicle/KA01HD6667
GET http://localhost:9001/api/vehicle/KA01HD6677
Authorization: Bearer {{auth-token}}
### query row
@ -67,6 +67,15 @@ Authorization: {{set-auth-token}}
}
}
### search row
POST http://localhost:9001/api/vehicle/search
Content-Type: application/json
Authorization: {{auth-token}}
{
"number": "KA01HD6677"
}
### update field
PATCH http://localhost:9001/api/vehicle/KA01HD6667
Content-Type: application/json

View File

@ -300,17 +300,11 @@ fun main(args: Array<String>) {
)
}
}
post("/script/database/{name}", Entities::executeStoredProcedure, Roles(adminRole, Role.DbOps))
post("/script/{file}/{name}", Entities::executeScript, Roles(adminRole, Role.DbOps))
get("/{entity}/{id}", Entities::view, Roles(adminRole, viewRole))
post("/{entity}/query/{id}", Entities::sqlQueryById, Roles(adminRole, viewRole))
post("/{entity}/query", Entities::sqlQueryRaw, Roles(adminRole, viewRole))
post("/{entity}/search", Entities::search, Roles(adminRole, viewRole))
post("/{entity}", Entities::create, Roles(adminRole, createRole))
put("/{entity}/approve/{id}", Entities::approve, Roles(adminRole, approveOrRejectRole))
put("/{entity}/reject/{id}", Entities::reject, Roles(adminRole, approveOrRejectRole))
put("/{entity}/{action}/{id}", Entities::action, Roles(adminRole, Role.Entity))
put("/{entity}/{id}", Entities::update, Roles(adminRole, updateRole))
patch("/{entity}/{id}", Entities::patch, Roles(adminRole, updateRole))

View File

@ -1,74 +0,0 @@
package com.restapi
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.restapi.controllers.QueryParam
import com.restapi.controllers.RawQuery
class FDeserializer : JsonDeserializer<F>() {
override fun deserialize(p: JsonParser, p1: DeserializationContext?): F {
//custom logic to do thia
val node = p.readValueAsTree<JsonNode>()
if (node.isObject) {
if (node.has("name")) {
return F.P(name = node.get("name").textValue())
} else if (node.has("num")) {
return F.Q(num = node.get("num").textValue())
} else if (node.has("tag")) {
return F.D(tag = node.get("tag").textValue())
}
} else {
//incorrect
}
throw IllegalArgumentException()
}
}
val om = jacksonObjectMapper()
@JsonDeserialize(using = FDeserializer::class)
sealed interface F {
data class P(val name: String) : F
data class Q(val num: String) : F
data class D(val tag: String) : F
}
val j = """
{"name":"a"}
""".trimIndent()
val j2 = """
{"num":"a"}
""".trimIndent()
val j3 = """
{"tag":"a"}
""".trimIndent()
val j4 = """
{
"sql":"aaaa",
"params": {
"a":"b",
"c": {
"type":"STRING",
"value":"aaaa"
}
}
}
""".trimIndent()
fun main() {
println(om.readValue<F>(j))
println(om.readValue<F>(j2))
println(om.readValue<F>(j3))
println(om.readValue<RawQuery>(j4))
}

View File

@ -6,82 +6,81 @@ import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.restapi.domain.*
import com.restapi.domain.Session.currentUser
import com.restapi.domain.Session.database
import com.restapi.domain.Session.findDataModelByEntityAndUniqId
import com.restapi.integ.Scripting
import io.ebean.CallableSql
import io.ebean.RawSqlBuilder
import io.javalin.http.*
import io.javalin.http.BadRequestResponse
import io.javalin.http.Context
import io.javalin.http.bodyAsClass
import org.slf4j.LoggerFactory
import java.sql.Types
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
enum class QueryParamType {
STRING, NUMBER, DATETIME, DATE
}
data class RawQuery(
val sql: String,
val params: Map<String, QueryParam>
)
data class QueryById(
val params: List<QueryParam>
)
@JsonDeserialize(using = QueryByIdParamsDeSerializer::class)
@JsonDeserialize(using = QueryParamDeSerializer::class)
sealed class QueryParam {
data class Simple(val simple: String) : QueryParam()
data class Complex(val type: QueryParamType, val value: String) : QueryParam() {
data class StrParam(val str: String) : QueryParam()
data class NumberParam(val nbr: Number) : QueryParam()
data class ComplexParam(val type: QueryParamType, val value: String) : QueryParam() {
fun getValueComplex(): Any {
return when (type) {
QueryParamType.STRING -> value
QueryParamType.NUMBER -> if (value.matches(Regex("\\d+"))) value.toLong() else value.toDouble()
QueryParamType.DATETIME -> LocalDateTime.parse(
value,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
)
QueryParamType.NUMBER -> (if (value.matches(Regex("\\d+"))) value.toLongOrNull() else value.toDoubleOrNull())
?: throw IllegalArgumentException("$value is not a number")
QueryParamType.DATE -> LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
QueryParamType.DATETIME -> try {
LocalDateTime.parse(
value,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
)
} catch (e: DateTimeParseException) {
throw IllegalArgumentException("unable to parse $value as datetime")
}
QueryParamType.DATE -> try {
LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
} catch (e: DateTimeParseException) {
throw IllegalArgumentException("unable to parse $value as date")
}
}
}
}
fun getValue(): Any {
return when (this) {
is Complex -> getValueComplex()
is Simple -> simple
else -> {}
is ComplexParam -> getValueComplex()
is StrParam -> str
is NumberParam -> nbr
}
}
}
class QueryByIdParamsDeSerializer : JsonDeserializer<QueryParam>() {
class QueryParamDeSerializer : JsonDeserializer<QueryParam>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): QueryParam {
val node = p.readValueAsTree<JsonNode>()
return if (node.isTextual) {
QueryParam.Simple(node.asText())
} else {
QueryParam.Complex(
QueryParam.StrParam(node.asText())
} else if (node.isNumber) {
QueryParam.NumberParam(node.numberValue())
} else if (node.isObject) {
QueryParam.ComplexParam(
QueryParamType.valueOf(node.get("type").textValue()),
node.get("value").textValue(),
)
} else {
throw BadRequestResponse("unable to find valid query param for $node")
}
}
}
enum class ResultType {
INTEGER, DECIMAL, STRING, DATETIME, ARRAY, OBJECT
}
data class RejectAction(val reason: String)
data class StoredProcedure(val input: Map<String, Any>, val output: Map<String, ResultType> = hashMapOf())
object Entities {
private val logger = LoggerFactory.getLogger("Entities")
@ -116,108 +115,22 @@ object Entities {
e.update()
}
fun action(ctx: Context) {}
fun approve(ctx: Context) {
approveOrReject(ctx, ApprovalStatus.APPROVED)
}
fun reject(ctx: Context) {
approveOrReject(ctx, ApprovalStatus.REJECTED)
}
private fun approveOrReject(ctx: Context, rejected: ApprovalStatus) {
val e = database.findDataModelByEntityAndUniqId(ctx.pathParam("entity"), ctx.pathParam("id"))
val reject = ctx.bodyAsClass<RejectAction>()
e.approvalStatus = rejected
e.comments.add(Comments(text = reject.reason, by = currentUser()))
e.save()
}
fun executeScript(ctx: Context) {
val name = ctx.pathParam("name")
val file = ctx.pathParam("file")
val params = ctx.bodyAsClass<Map<String, Any>>()
ctx.json(
Scripting.execute(file, name, params)
)
}
fun executeStoredProcedure(ctx: Context) {
val name = ctx.pathParam("name")
val sp = ctx.bodyAsClass<StoredProcedure>()
val inputParams = sp.input.entries.toList()
val outputParams = sp.output.entries.toList()
val placeholders = (0..inputParams.size + 1).joinToString(",") { "?" }
val sql = "{call $name($placeholders)}"
val cs: CallableSql = database.createCallableSql(sql)
inputParams.forEachIndexed { index, entry ->
cs.setParameter(index + 1, entry.value)
}
cs.setParameter(inputParams.size + 1, Session.currentTenant())
outputParams.forEachIndexed { idx, entry ->
when (entry.value) {
ResultType.INTEGER -> cs.registerOut(idx + 1, Types.INTEGER)
ResultType.DECIMAL -> cs.registerOut(idx + 1, Types.DOUBLE)
ResultType.STRING -> cs.registerOut(idx + 1, Types.VARCHAR)
ResultType.DATETIME -> cs.registerOut(idx + 1, Types.DATE)
ResultType.ARRAY -> cs.registerOut(idx + 1, Types.ARRAY)
ResultType.OBJECT -> cs.registerOut(idx + 1, Types.JAVA_OBJECT)
}
}
val done = database.execute(cs)
val output = outputParams.mapIndexed { index, entry ->
Pair(entry.key, cs.getObject(index + 1))
}.toMap()
ctx.json(
mapOf(
"done" to done,
"output" to output
)
)
}
fun sqlQueryRaw(ctx: Context) {
val sql = ctx.bodyAsClass<RawQuery>()
logger.warn("running sql ${sql.sql}, with params ${sql.params}")
ctx.json(
database.find(DataModel::class.java)
.setRawSql(
RawSqlBuilder.parse(sql.sql).create()
).apply {
sql.params.forEach { (t, u) ->
setParameter(t, u.getValue())
}
}
.findList()
)
}
fun sqlQueryById(ctx: Context) {
val sql = ctx.bodyAsClass<QueryById>()
val sqlId = ctx.pathParam("id")
logger.warn("running sqlId $sqlId, with params ${sql.params}")
fun search(ctx: Context) {
val sql = ctx.bodyAsClass<SearchParams>()
val entity = ctx.pathParam("entity")
val query = database.find(SqlModel::class.java)
.where()
.eq("entityName", entity)
.eq("sqlId", sqlId)
.findOne() ?: throw NotFoundResponse("sql not found for $entity, $sqlId")
ctx.json(
database.find(DataModel::class.java)
.setRawSql(RawSqlBuilder.parse(query.sql).create())
.where()
.eq("entityName", entity)
.apply {
sql.params.forEachIndexed { index, entry ->
setParameter(index + 1, entry.getValue())
sql.forEach { (t, u) ->
if (!SafeStringDeserializer.isSafe(t)) {
throw IllegalArgumentException()
}
eq("data->>'$t'", u.getValue())
}
}
.findList()
@ -225,6 +138,7 @@ object Entities {
}
fun view(it: Context) {
database.save(
AuditLog().apply {
@ -317,18 +231,7 @@ object Entities {
}
}
}
if (!setupEntity.preSaveScript.isNullOrEmpty()) {
val ok = Scripting.execute(setupEntity.preSaveScript!!, "preSave", this) as Boolean
if (!ok) {
throw BadRequestResponse("PreSave Failed")
}
}
if (setupEntity.approvalLevels > 0) {
this.approvalStatus = ApprovalStatus.PENDING
this.requiredApprovalLevels = setupEntity.approvalLevels
}
}
}
@ -371,5 +274,7 @@ object Entities {
}
}
typealias SearchParams = Map<String, QueryParam>
data class SequenceNumber(val number: String)

View File

@ -179,18 +179,6 @@ enum class JobType {
SCRIPT, DB
}
@Entity
@Index(unique = true, name = "sql_unique_id", columnNames = ["entity_name", "sql_id", "tenant_id"])
open class SqlModel : BaseTenantModel() {
@JsonDeserialize(using = SafeStringDeserializer::class)
var sqlId: String = ""
var entityName: String = ""
@Column(columnDefinition = "text")
var sql: String = ""
}
@Entity
open class JobModel : BaseTenantModel() {
@ -242,12 +230,17 @@ open class AnonSession : BaseTenantModel() {
}
class SafeStringDeserializer : JsonDeserializer<String>() {
private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
companion object {
private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
fun isSafe(s: String) = regex.matches(s)
}
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): String {
val text = p.text
if (!regex.matches(text)) throw IllegalArgumentException()
if (!isSafe(text)) throw IllegalArgumentException()
return text
}
}