Compare commits
5 Commits
82fb57bd85
...
2b60e9cc29
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b60e9cc29 | ||
|
|
81afbdab49 | ||
|
|
2be4df0b6d | ||
|
|
e09ff4ce2b | ||
|
|
d506078804 |
9
.idea/misc.xml
generated
9
.idea/misc.xml
generated
@ -4,10 +4,13 @@
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="NimToolchainService">
|
||||
<option name="rootPaths">
|
||||
<list />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/../txn_workflow/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="workspaceImportForciblyTurnedOn" value="true" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
|
||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@ -3,5 +3,6 @@
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../rmc-modules-app" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/../txn_workflow" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
14
api.http
14
api.http
@ -24,7 +24,11 @@ Authorization: {{auth-token}}
|
||||
}
|
||||
|
||||
### get row
|
||||
GET http://localhost:9001/api/vehicle/TN38BA5009
|
||||
GET http://localhost:9001/api/log/log-0000000001
|
||||
Authorization: Bearer {{auth-token}}
|
||||
|
||||
### get row
|
||||
GET http://localhost:9001/api/vehicle/KA01HD6667
|
||||
Authorization: Bearer {{auth-token}}
|
||||
|
||||
### query row
|
||||
@ -40,7 +44,7 @@ Authorization: set-auth-token
|
||||
}
|
||||
|
||||
### update field
|
||||
PATCH http://localhost:9001/api/vehicle/KA01MU0556
|
||||
PATCH http://localhost:9001/api/vehicle/KA01HD6667
|
||||
Content-Type: application/json
|
||||
Authorization: {{auth-token}}
|
||||
|
||||
@ -51,9 +55,9 @@ Authorization: {{auth-token}}
|
||||
|
||||
|
||||
### upate a row
|
||||
PUT http://localhost:9001/api/vehicle/KA03HD6064
|
||||
PUT http://localhost:9001/api/vehicle/KA01HD6667
|
||||
Content-Type: application/json
|
||||
Authorization: set-auth-token
|
||||
Authorization: {{auth-token}}
|
||||
|
||||
{
|
||||
"number": "KA03HD6064",
|
||||
@ -62,5 +66,5 @@ Authorization: set-auth-token
|
||||
}
|
||||
|
||||
### delete a row
|
||||
DELETE http://localhost:9001/api/vehicle/KA01MU0556
|
||||
DELETE http://localhost:9001/api/vehicle/KA01HD6667
|
||||
Authorization: {{auth-token}}
|
||||
@ -12,10 +12,10 @@ app:
|
||||
cache:
|
||||
redis_uri: redis://127.0.0.1:6379/0
|
||||
iam:
|
||||
url: https://auth.compegence.com
|
||||
realm: forewarn-dev
|
||||
url: https://auth.readymixerp.com
|
||||
realm: rmc-dev
|
||||
client_redirect_uri: http://localhost:9001/auth/code
|
||||
client: forewarn
|
||||
client: rmc
|
||||
scripts:
|
||||
path: /Users/gowthaman.b/IdeaProjects/rmc_modules_api/src/main/resources/scripts
|
||||
security:
|
||||
|
||||
@ -34,6 +34,8 @@ dependencies {
|
||||
implementation("org.bouncycastle:bcprov-jdk18on:1.76")
|
||||
implementation("org.bouncycastle:bcpkix-jdk18on:1.76")
|
||||
implementation("org.yaml:snakeyaml:2.2")
|
||||
implementation("io.minio:minio:8.5.7")
|
||||
implementation("org.apache.httpcomponents:httpclient:4.5.14")
|
||||
api ("net.cactusthorn.config:config-core:0.81")
|
||||
api ("net.cactusthorn.config:config-yaml:0.81")
|
||||
kapt("net.cactusthorn.config:config-compiler:0.81")
|
||||
|
||||
@ -6,6 +6,7 @@ import com.restapi.config.AppConfig.Companion.appConfig
|
||||
import com.restapi.config.Auth.validateAuthToken
|
||||
import com.restapi.controllers.Entities
|
||||
import com.restapi.domain.DataNotFoundException
|
||||
import com.restapi.domain.Session
|
||||
import com.restapi.domain.Session.currentTenant
|
||||
import com.restapi.domain.Session.currentUser
|
||||
import com.restapi.domain.Session.objectMapper
|
||||
@ -15,7 +16,9 @@ import io.ebean.DataIntegrityException
|
||||
import io.ebean.DuplicateKeyException
|
||||
import io.javalin.Javalin
|
||||
import io.javalin.apibuilder.ApiBuilder.*
|
||||
import io.javalin.http.*
|
||||
import io.javalin.http.ContentType
|
||||
import io.javalin.http.Context
|
||||
import io.javalin.http.UnauthorizedResponse
|
||||
import io.javalin.http.util.NaiveRateLimit
|
||||
import io.javalin.http.util.RateLimitUtil
|
||||
import io.javalin.json.JavalinJackson
|
||||
@ -60,6 +63,7 @@ fun main(args: Array<String>) {
|
||||
}
|
||||
.routes {
|
||||
path("/auth") {
|
||||
|
||||
get("/endpoint", Auth::endPoint)
|
||||
get("/init", Auth::init)
|
||||
get("/code", Auth::code)
|
||||
@ -74,10 +78,10 @@ fun main(args: Array<String>) {
|
||||
TimeUnit.MINUTES
|
||||
)
|
||||
|
||||
val authToken = ctx.header("Authorization")
|
||||
?.replace("Bearer ", "")
|
||||
?.replace("Bearer: ", "")
|
||||
?.trim() ?: throw UnauthorizedResponse()
|
||||
val authToken = ctx.getAuthHeader() ?: throw UnauthorizedResponse()
|
||||
|
||||
|
||||
//there are 2 scenarios, 1) auth user for admin 2) non user for flow, we need to handle both
|
||||
|
||||
setAuthorizedUser(validateAuthToken(authToken = authToken))
|
||||
|
||||
@ -96,11 +100,12 @@ fun main(args: Array<String>) {
|
||||
it.header("X-Signature", signPayload(outEncoded))
|
||||
|
||||
if (appConfig.enforcePayloadEncryption()) {
|
||||
//todo:, encrypt and set the response back to user
|
||||
//todo: encrypt and send the response back to user
|
||||
}
|
||||
|
||||
}
|
||||
path("/api") {
|
||||
|
||||
post("/audit/{action}") {
|
||||
logger.warn("User ${currentUser()} of tenant ${currentTenant()} has performed ${it.pathParam("action")} @ ${LocalDateTime.now()}")
|
||||
it.json(mapOf("status" to true))
|
||||
@ -132,3 +137,8 @@ fun main(args: Array<String>) {
|
||||
.start(appConfig.portNumber())
|
||||
}
|
||||
|
||||
private fun Context.getAuthHeader() = header("Authorization")
|
||||
?.replace("Bearer ", "")
|
||||
?.replace("Bearer: ", "")
|
||||
?.trim()
|
||||
|
||||
|
||||
@ -81,6 +81,21 @@ interface AppConfig {
|
||||
@Key("app.security.public_key")
|
||||
fun publicKey(): Optional<String>
|
||||
|
||||
@Key("app.locate.api_key")
|
||||
fun locateApiKey(): Optional<String>
|
||||
|
||||
@Key("app.s3.url")
|
||||
fun s3Url(): Optional<String>
|
||||
|
||||
@Key("app.s3.bucket")
|
||||
fun s3Bucket(): Optional<String>
|
||||
|
||||
@Key("app.s3.access_key")
|
||||
fun s3AccessKey(): Optional<String>
|
||||
|
||||
@Key("app.s3.secret_key")
|
||||
fun s3SecretKey(): Optional<String>
|
||||
|
||||
companion object {
|
||||
val appConfig: AppConfig = ConfigFactory.builder().build().create(AppConfig::class.java)
|
||||
}
|
||||
|
||||
@ -63,7 +63,6 @@ object Auth {
|
||||
.setAllowedClockSkewInSeconds(30)
|
||||
.setRequireSubject()
|
||||
.setExpectedIssuer(getAuthEndpoint().issuer)
|
||||
.setExpectedAudience("account")
|
||||
.setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri)))
|
||||
.build()
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.time.LocalDateTime
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.jvm.optionals.getOrDefault
|
||||
|
||||
|
||||
@ -137,7 +138,27 @@ object Session {
|
||||
|
||||
|
||||
}
|
||||
fun a(){
|
||||
val a = HashMap<String,String>()
|
||||
a.put("a", "b");
|
||||
a.put("a", "b");
|
||||
a.put("a", "b");
|
||||
a.put("a", "b");
|
||||
|
||||
val b = HashMap<String,String>().apply {
|
||||
put("a", "b");
|
||||
put("a", "b");
|
||||
put("a", "b");
|
||||
put("a", "b");
|
||||
}
|
||||
|
||||
val c: String? = ""
|
||||
val x = c?.get(1)
|
||||
|
||||
c?.apply {
|
||||
//will work only when c is not null
|
||||
}
|
||||
}
|
||||
private val sc = DatabaseConfig().apply {
|
||||
loadFromProperties(Properties().apply {
|
||||
setProperty("datasource.db.username", appConfig.dbUser())
|
||||
@ -180,7 +201,7 @@ object Session {
|
||||
val s = database
|
||||
.sqlQuery("SELECT nextval('${seqName(entity)}');")
|
||||
.findOne()?.getLong("nextval") ?: throw DataNotFoundException
|
||||
return String.format("%s-%s", entity, "$s".padStart(10, '0'))
|
||||
return "$entity-${"$s".padStart(10, '0')}"
|
||||
}
|
||||
|
||||
val redis = JedisPooled(appConfig.redisUri().getOrDefault("redis://localhost:6739/0"))
|
||||
|
||||
@ -5,17 +5,8 @@ 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.DbDefault
|
||||
import io.ebean.annotation.DbJsonB
|
||||
import io.ebean.annotation.*
|
||||
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.*
|
||||
|
||||
@ -48,7 +39,6 @@ abstract class BaseModel : Model() {
|
||||
var modifiedAt: LocalDateTime? = null
|
||||
|
||||
|
||||
|
||||
@WhoCreated
|
||||
var createdBy: String = ""
|
||||
|
||||
@ -61,6 +51,7 @@ abstract class BaseModel : Model() {
|
||||
|
||||
@DbDefault("0")
|
||||
var currentApprovalLevel: Int = 0
|
||||
|
||||
@DbDefault("0")
|
||||
var requiredApprovalLevels: Int = 0
|
||||
|
||||
@ -110,11 +101,17 @@ open class AuditLog : BaseTenantModel() {
|
||||
var uniqueIdentifier: String = ""
|
||||
|
||||
@DbJsonB
|
||||
@Index(definition = "create index audit_log_values_idx on audit_log using GIN (data)", platforms = [Platform.POSTGRES])
|
||||
@Index(
|
||||
definition = "create index audit_log_values_idx on audit_log using GIN (data)",
|
||||
platforms = [Platform.POSTGRES]
|
||||
)
|
||||
var data: Map<String, Any> = hashMapOf()
|
||||
|
||||
@DbJsonB
|
||||
@Index(definition = "create index audit_log_changes_idx on audit_log using GIN (changes)", platforms = [Platform.POSTGRES])
|
||||
@Index(
|
||||
definition = "create index audit_log_changes_idx on audit_log using GIN (changes)",
|
||||
platforms = [Platform.POSTGRES]
|
||||
)
|
||||
var changes: Map<String, Any> = hashMapOf()
|
||||
}
|
||||
|
||||
@ -181,6 +178,7 @@ open class SqlModel : BaseTenantModel(){
|
||||
@Column(columnDefinition = "text")
|
||||
var sql: String = ""
|
||||
}
|
||||
|
||||
@Entity
|
||||
open class JobModel : BaseTenantModel() {
|
||||
@Index(unique = true)
|
||||
@ -216,6 +214,19 @@ open class DataModel : BaseTenantModel() {
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Index(unique = true, name = "unique_session_id", columnNames = ["session_id"])
|
||||
open class AnonSession : BaseTenantModel() {
|
||||
|
||||
var sessionId: String? = null
|
||||
var ip: String? = null
|
||||
var firstSeenAt: LocalDateTime? = null
|
||||
var lastSeenAt: LocalDateTime? = null
|
||||
|
||||
@DbJsonB
|
||||
var headerMap: Map<String, String> = hashMapOf()
|
||||
}
|
||||
|
||||
class SafeStringDeserializer : JsonDeserializer<String>() {
|
||||
private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
|
||||
|
||||
|
||||
190
src/main/kotlin/com/restapi/integ/ExternalAPI.kt
Normal file
190
src/main/kotlin/com/restapi/integ/ExternalAPI.kt
Normal file
@ -0,0 +1,190 @@
|
||||
package com.restapi.integ
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.restapi.config.AppConfig
|
||||
import io.minio.MinioClient
|
||||
import io.minio.UploadObjectArgs
|
||||
import org.apache.http.client.methods.HttpGet
|
||||
import org.apache.http.client.utils.URIBuilder
|
||||
import org.apache.http.impl.client.HttpClients
|
||||
import org.apache.http.message.BasicNameValuePair
|
||||
import org.apache.http.util.EntityUtils
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
|
||||
val logger = LoggerFactory.getLogger("ExternalAPI")
|
||||
|
||||
object S3 {
|
||||
private val s3Url = AppConfig.appConfig.s3Url().orElse("s3.amazonaws.com")
|
||||
private val minioClient: MinioClient by lazy {
|
||||
MinioClient.builder()
|
||||
.endpoint("https://$s3Url")
|
||||
.credentials(
|
||||
AppConfig.appConfig.s3AccessKey().orElseThrow(),
|
||||
AppConfig.appConfig.s3SecretKey().orElseThrow()
|
||||
).build()
|
||||
}
|
||||
|
||||
fun uploadFilesToS3(f: File, name: String): Result<String> {
|
||||
val objStore: String = AppConfig.appConfig.s3Bucket().orElseThrow()
|
||||
logger.warn("Trying to upload Object ${f.absolutePath} -> $objStore")
|
||||
|
||||
try {
|
||||
minioClient.uploadObject(
|
||||
UploadObjectArgs.builder()
|
||||
.bucket(objStore)
|
||||
.`object`(name)
|
||||
.filename(f.absolutePath)
|
||||
.build()
|
||||
)
|
||||
return Result.success("https://${objStore}.${s3Url}/$name")
|
||||
} catch (e: Exception) {
|
||||
logger.warn("Error in file Upload ${f.absolutePath} ==> ${e.message} => Objstore[${objStore}]")
|
||||
return Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
data class LoqateFullAddrResponse(
|
||||
@JsonProperty("Items")
|
||||
val items: List<Item>
|
||||
) {
|
||||
data class Item(
|
||||
@JsonProperty("AdminAreaCode")
|
||||
val adminAreaCode: String,
|
||||
@JsonProperty("AdminAreaName")
|
||||
val adminAreaName: String,
|
||||
@JsonProperty("Barcode")
|
||||
val barcode: String,
|
||||
@JsonProperty("Block")
|
||||
val block: String,
|
||||
@JsonProperty("BuildingName")
|
||||
val buildingName: String,
|
||||
@JsonProperty("BuildingNumber")
|
||||
val buildingNumber: String,
|
||||
@JsonProperty("City")
|
||||
val city: String,
|
||||
@JsonProperty("Company")
|
||||
val company: String,
|
||||
@JsonProperty("CountryIso2")
|
||||
val countryIso2: String,
|
||||
@JsonProperty("CountryIso3")
|
||||
val countryIso3: String,
|
||||
@JsonProperty("CountryIsoNumber")
|
||||
val countryIsoNumber: String,
|
||||
@JsonProperty("CountryName")
|
||||
val countryName: String,
|
||||
@JsonProperty("DataLevel")
|
||||
val dataLevel: String,
|
||||
@JsonProperty("Department")
|
||||
val department: String,
|
||||
@JsonProperty("District")
|
||||
val district: String,
|
||||
@JsonProperty("DomesticId")
|
||||
val domesticId: String,
|
||||
@JsonProperty("Field1")
|
||||
val field1: String,
|
||||
@JsonProperty("Field10")
|
||||
val field10: String,
|
||||
@JsonProperty("Field11")
|
||||
val field11: String,
|
||||
@JsonProperty("Field12")
|
||||
val field12: String,
|
||||
@JsonProperty("Field13")
|
||||
val field13: String,
|
||||
@JsonProperty("Field14")
|
||||
val field14: String,
|
||||
@JsonProperty("Field15")
|
||||
val field15: String,
|
||||
@JsonProperty("Field16")
|
||||
val field16: String,
|
||||
@JsonProperty("Field17")
|
||||
val field17: String,
|
||||
@JsonProperty("Field18")
|
||||
val field18: String,
|
||||
@JsonProperty("Field19")
|
||||
val field19: String,
|
||||
@JsonProperty("Field2")
|
||||
val field2: String,
|
||||
@JsonProperty("Field20")
|
||||
val field20: String,
|
||||
@JsonProperty("Field3")
|
||||
val field3: String,
|
||||
@JsonProperty("Field4")
|
||||
val field4: String,
|
||||
@JsonProperty("Field5")
|
||||
val field5: String,
|
||||
@JsonProperty("Field6")
|
||||
val field6: String,
|
||||
@JsonProperty("Field7")
|
||||
val field7: String,
|
||||
@JsonProperty("Field8")
|
||||
val field8: String,
|
||||
@JsonProperty("Field9")
|
||||
val field9: String,
|
||||
@JsonProperty("Id")
|
||||
val id: String,
|
||||
@JsonProperty("Label")
|
||||
val label: String,
|
||||
@JsonProperty("Language")
|
||||
val language: String,
|
||||
@JsonProperty("LanguageAlternatives")
|
||||
val languageAlternatives: String,
|
||||
@JsonProperty("Line1")
|
||||
val line1: String,
|
||||
@JsonProperty("Line2")
|
||||
val line2: String,
|
||||
@JsonProperty("Line3")
|
||||
val line3: String,
|
||||
@JsonProperty("Line4")
|
||||
val line4: String,
|
||||
@JsonProperty("Line5")
|
||||
val line5: String,
|
||||
@JsonProperty("Neighbourhood")
|
||||
val neighbourhood: String,
|
||||
@JsonProperty("POBoxNumber")
|
||||
val pOBoxNumber: String,
|
||||
@JsonProperty("PostalCode")
|
||||
val postalCode: String,
|
||||
@JsonProperty("Province")
|
||||
val province: String,
|
||||
@JsonProperty("ProvinceCode")
|
||||
val provinceCode: String,
|
||||
@JsonProperty("ProvinceName")
|
||||
val provinceName: String,
|
||||
@JsonProperty("SecondaryStreet")
|
||||
val secondaryStreet: String,
|
||||
@JsonProperty("SortingNumber1")
|
||||
val sortingNumber1: String,
|
||||
@JsonProperty("SortingNumber2")
|
||||
val sortingNumber2: String,
|
||||
@JsonProperty("Street")
|
||||
val street: String,
|
||||
@JsonProperty("SubBuilding")
|
||||
val subBuilding: String,
|
||||
@JsonProperty("Type")
|
||||
val type: String
|
||||
)
|
||||
}
|
||||
|
||||
object LoqateAPI {
|
||||
//todo: add search?
|
||||
fun findFullAddr(id: String): LoqateFullAddrResponse {
|
||||
//https://api.addressy.com/Capture/Interactive/Retrieve/v1.2/
|
||||
return HttpClients.createDefault().use { h ->
|
||||
val key = AppConfig.appConfig.locateApiKey().orElseThrow()
|
||||
val ub = URIBuilder("https://api.addressy.com/Capture/Interactive/Retrieve/v1.2/json3.ws")
|
||||
.setParameters(
|
||||
BasicNameValuePair("Key", key),
|
||||
BasicNameValuePair("Id", id)
|
||||
).build()
|
||||
h.execute(HttpGet(ub)).use {
|
||||
jacksonObjectMapper().readValue(EntityUtils.toString(it.entity))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/main/resources/dbmigration/1.1.sql
Normal file
27
src/main/resources/dbmigration/1.1.sql
Normal file
@ -0,0 +1,27 @@
|
||||
-- apply changes
|
||||
create table anon_session (
|
||||
sys_pk bigint generated by default as identity not null,
|
||||
deleted_on timestamp,
|
||||
current_approval_level integer default 0 not null,
|
||||
required_approval_levels integer default 0 not null,
|
||||
first_seen_at timestamp,
|
||||
last_seen_at timestamp,
|
||||
deleted boolean default false not null,
|
||||
version integer default 1 not null,
|
||||
created_at timestamp default 'now()' not null,
|
||||
modified_at timestamp default 'now()' not null,
|
||||
deleted_by varchar(255),
|
||||
approval_status varchar(8) default 'APPROVED' not null,
|
||||
tags varchar[] default '{}' not null,
|
||||
comments jsonb default '[]' not null,
|
||||
tenant_id varchar(255) not null,
|
||||
session_id varchar(255),
|
||||
ip varchar(255),
|
||||
header_map jsonb not null,
|
||||
created_by varchar(255) not null,
|
||||
modified_by varchar(255) not null,
|
||||
constraint ck_anon_session_approval_status check ( approval_status in ('PENDING','APPROVED','REJECTED')),
|
||||
constraint unique_session_id unique (session_id),
|
||||
constraint pk_anon_session primary key (sys_pk)
|
||||
);
|
||||
|
||||
28
src/main/resources/dbmigration/model/1.1.model.xml
Normal file
28
src/main/resources/dbmigration/model/1.1.model.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
<createTable name="anon_session" pkName="pk_anon_session">
|
||||
<column name="sys_pk" type="bigint" primaryKey="true"/>
|
||||
<column name="deleted_on" type="localdatetime"/>
|
||||
<column name="deleted_by" type="varchar"/>
|
||||
<column name="current_approval_level" type="integer" defaultValue="0" notnull="true"/>
|
||||
<column name="required_approval_levels" type="integer" defaultValue="0" notnull="true"/>
|
||||
<column name="approval_status" type="varchar(8)" defaultValue="'APPROVED'" notnull="true" checkConstraint="check ( approval_status in ('PENDING','APPROVED','REJECTED'))" checkConstraintName="ck_anon_session_approval_status"/>
|
||||
<column name="tags" type="varchar[]" defaultValue="'{}'" notnull="true"/>
|
||||
<column name="comments" type="jsonb" defaultValue="'[]'" notnull="true"/>
|
||||
<column name="tenant_id" type="varchar" notnull="true"/>
|
||||
<column name="session_id" type="varchar"/>
|
||||
<column name="ip" type="varchar"/>
|
||||
<column name="first_seen_at" type="localdatetime"/>
|
||||
<column name="last_seen_at" type="localdatetime"/>
|
||||
<column name="header_map" type="jsonb" notnull="true"/>
|
||||
<column name="deleted" type="boolean" defaultValue="false" notnull="true"/>
|
||||
<column name="version" type="integer" defaultValue="1" notnull="true"/>
|
||||
<column name="created_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||
<column name="modified_at" type="localdatetime" defaultValue="'now()'" notnull="true"/>
|
||||
<column name="created_by" type="varchar" notnull="true"/>
|
||||
<column name="modified_by" type="varchar" notnull="true"/>
|
||||
<uniqueConstraint name="unique_session_id" columnNames="session_id" oneToOne="false" nullableColumns="session_id"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
</migration>
|
||||
Loading…
x
Reference in New Issue
Block a user