add more stuff
This commit is contained in:
parent
82fb57bd85
commit
d506078804
9
.idea/misc.xml
generated
9
.idea/misc.xml
generated
@ -4,10 +4,13 @@
|
|||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
<component name="FrameworkDetectionExcludesConfiguration">
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
<file type="web" url="file://$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="NimToolchainService">
|
<component name="MavenProjectsManager">
|
||||||
<option name="rootPaths">
|
<option name="originalFiles">
|
||||||
<list />
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/../txn_workflow/pom.xml" />
|
||||||
|
</list>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="workspaceImportForciblyTurnedOn" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
|||||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@ -3,5 +3,6 @@
|
|||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$/../rmc-modules-app" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/../rmc-modules-app" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/../txn_workflow" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@ -5,12 +5,15 @@ import com.restapi.config.*
|
|||||||
import com.restapi.config.AppConfig.Companion.appConfig
|
import com.restapi.config.AppConfig.Companion.appConfig
|
||||||
import com.restapi.config.Auth.validateAuthToken
|
import com.restapi.config.Auth.validateAuthToken
|
||||||
import com.restapi.controllers.Entities
|
import com.restapi.controllers.Entities
|
||||||
|
import com.restapi.domain.AnonSession
|
||||||
import com.restapi.domain.DataNotFoundException
|
import com.restapi.domain.DataNotFoundException
|
||||||
|
import com.restapi.domain.Session
|
||||||
import com.restapi.domain.Session.currentTenant
|
import com.restapi.domain.Session.currentTenant
|
||||||
import com.restapi.domain.Session.currentUser
|
import com.restapi.domain.Session.currentUser
|
||||||
import com.restapi.domain.Session.objectMapper
|
import com.restapi.domain.Session.objectMapper
|
||||||
import com.restapi.domain.Session.setAuthorizedUser
|
import com.restapi.domain.Session.setAuthorizedUser
|
||||||
import com.restapi.domain.Session.signPayload
|
import com.restapi.domain.Session.signPayload
|
||||||
|
import com.restapi.domain.TenantModel
|
||||||
import io.ebean.DataIntegrityException
|
import io.ebean.DataIntegrityException
|
||||||
import io.ebean.DuplicateKeyException
|
import io.ebean.DuplicateKeyException
|
||||||
import io.javalin.Javalin
|
import io.javalin.Javalin
|
||||||
@ -60,6 +63,43 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
.routes {
|
.routes {
|
||||||
path("/auth") {
|
path("/auth") {
|
||||||
|
get("/session") {
|
||||||
|
//a simple session to keep track of anon users
|
||||||
|
val at = it.getAuthHeader()
|
||||||
|
val tenant = Session.database.find(TenantModel::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("domain",it.host())
|
||||||
|
.findOne() ?: throw UnauthorizedResponse()
|
||||||
|
|
||||||
|
if(at == null){
|
||||||
|
//new session
|
||||||
|
val s = AnonSession().apply {
|
||||||
|
sessionId = UUID.randomUUID().toString()
|
||||||
|
firstSeenAt = LocalDateTime.now()
|
||||||
|
lastSeenAt = LocalDateTime.now()
|
||||||
|
tenantId = tenant.name
|
||||||
|
headerMap = it.headerMap()
|
||||||
|
}
|
||||||
|
Session.database.save(s)
|
||||||
|
it.json(s)
|
||||||
|
} else {
|
||||||
|
val s = Session.database.find(AnonSession::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("sessionId", at)
|
||||||
|
.findOne() ?: throw UnauthorizedResponse()
|
||||||
|
|
||||||
|
|
||||||
|
Session.database.save(
|
||||||
|
s.apply {
|
||||||
|
lastSeenAt = LocalDateTime.now()
|
||||||
|
headerMap = it.headerMap()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
it.json(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
get("/endpoint", Auth::endPoint)
|
get("/endpoint", Auth::endPoint)
|
||||||
get("/init", Auth::init)
|
get("/init", Auth::init)
|
||||||
get("/code", Auth::code)
|
get("/code", Auth::code)
|
||||||
@ -74,10 +114,10 @@ fun main(args: Array<String>) {
|
|||||||
TimeUnit.MINUTES
|
TimeUnit.MINUTES
|
||||||
)
|
)
|
||||||
|
|
||||||
val authToken = ctx.header("Authorization")
|
val authToken = ctx.getAuthHeader() ?: throw UnauthorizedResponse()
|
||||||
?.replace("Bearer ", "")
|
|
||||||
?.replace("Bearer: ", "")
|
|
||||||
?.trim() ?: 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))
|
setAuthorizedUser(validateAuthToken(authToken = authToken))
|
||||||
|
|
||||||
@ -96,11 +136,12 @@ fun main(args: Array<String>) {
|
|||||||
it.header("X-Signature", signPayload(outEncoded))
|
it.header("X-Signature", signPayload(outEncoded))
|
||||||
|
|
||||||
if (appConfig.enforcePayloadEncryption()) {
|
if (appConfig.enforcePayloadEncryption()) {
|
||||||
//todo:, encrypt and set the response back to user
|
//todo: encrypt and send the response back to user
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
path("/api") {
|
path("/api") {
|
||||||
|
|
||||||
post("/audit/{action}") {
|
post("/audit/{action}") {
|
||||||
logger.warn("User ${currentUser()} of tenant ${currentTenant()} has performed ${it.pathParam("action")} @ ${LocalDateTime.now()}")
|
logger.warn("User ${currentUser()} of tenant ${currentTenant()} has performed ${it.pathParam("action")} @ ${LocalDateTime.now()}")
|
||||||
it.json(mapOf("status" to true))
|
it.json(mapOf("status" to true))
|
||||||
@ -132,3 +173,8 @@ fun main(args: Array<String>) {
|
|||||||
.start(appConfig.portNumber())
|
.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")
|
@Key("app.security.public_key")
|
||||||
fun publicKey(): Optional<String>
|
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 {
|
companion object {
|
||||||
val appConfig: AppConfig = ConfigFactory.builder().build().create(AppConfig::class.java)
|
val appConfig: AppConfig = ConfigFactory.builder().build().create(AppConfig::class.java)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.restapi.config
|
|||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.restapi.config.AppConfig.Companion.appConfig
|
import com.restapi.config.AppConfig.Companion.appConfig
|
||||||
|
import com.restapi.domain.AnonSession
|
||||||
import com.restapi.domain.Session
|
import com.restapi.domain.Session
|
||||||
import com.restapi.domain.Session.objectMapper
|
import com.restapi.domain.Session.objectMapper
|
||||||
import io.javalin.http.BadRequestResponse
|
import io.javalin.http.BadRequestResponse
|
||||||
@ -74,6 +75,23 @@ object Auth {
|
|||||||
|
|
||||||
fun validateAuthToken(authToken: String, skipValidate: Boolean = false): AuthUser {
|
fun validateAuthToken(authToken: String, skipValidate: Boolean = false): AuthUser {
|
||||||
|
|
||||||
|
|
||||||
|
//check if this is anon session
|
||||||
|
val anonSession = Session.database.find(AnonSession::class.java)
|
||||||
|
.where()
|
||||||
|
.eq("sessionId", authToken)
|
||||||
|
.findOne()
|
||||||
|
|
||||||
|
if (anonSession != null) {
|
||||||
|
return AuthUser(
|
||||||
|
userName = authToken,
|
||||||
|
tenant = anonSession.tenantId,
|
||||||
|
roles = emptyList(),
|
||||||
|
token = authToken,
|
||||||
|
expiry = LocalDateTime.now().plusDays(1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Validate the JWT and process it to the Claims
|
// Validate the JWT and process it to the Claims
|
||||||
val jwtClaims = if (skipValidate) jwtConsumerSkipValidate.process(authToken) else jwtConsumer.process(authToken)
|
val jwtClaims = if (skipValidate) jwtConsumerSkipValidate.process(authToken) else jwtConsumer.process(authToken)
|
||||||
val userId = jwtClaims.jwtClaims.claimsMap["preferred_username"] as String
|
val userId = jwtClaims.jwtClaims.claimsMap["preferred_username"] as String
|
||||||
|
|||||||
@ -5,17 +5,8 @@ import com.fasterxml.jackson.databind.DeserializationContext
|
|||||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||||
import io.ebean.Model
|
import io.ebean.Model
|
||||||
import io.ebean.annotation.DbArray
|
import io.ebean.annotation.*
|
||||||
import io.ebean.annotation.DbDefault
|
|
||||||
import io.ebean.annotation.DbJsonB
|
|
||||||
import io.ebean.annotation.Index
|
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 java.time.LocalDateTime
|
||||||
import javax.persistence.*
|
import javax.persistence.*
|
||||||
|
|
||||||
@ -48,7 +39,6 @@ abstract class BaseModel : Model() {
|
|||||||
var modifiedAt: LocalDateTime? = null
|
var modifiedAt: LocalDateTime? = null
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@WhoCreated
|
@WhoCreated
|
||||||
var createdBy: String = ""
|
var createdBy: String = ""
|
||||||
|
|
||||||
@ -61,6 +51,7 @@ abstract class BaseModel : Model() {
|
|||||||
|
|
||||||
@DbDefault("0")
|
@DbDefault("0")
|
||||||
var currentApprovalLevel: Int = 0
|
var currentApprovalLevel: Int = 0
|
||||||
|
|
||||||
@DbDefault("0")
|
@DbDefault("0")
|
||||||
var requiredApprovalLevels: Int = 0
|
var requiredApprovalLevels: Int = 0
|
||||||
|
|
||||||
@ -110,11 +101,17 @@ open class AuditLog : BaseTenantModel() {
|
|||||||
var uniqueIdentifier: String = ""
|
var uniqueIdentifier: String = ""
|
||||||
|
|
||||||
@DbJsonB
|
@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()
|
var data: Map<String, Any> = hashMapOf()
|
||||||
|
|
||||||
@DbJsonB
|
@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()
|
var changes: Map<String, Any> = hashMapOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +168,7 @@ enum class JobType {
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Index(unique = true, name = "sql_unique_id", columnNames = ["entity_name", "sql_id", "tenant_id"])
|
@Index(unique = true, name = "sql_unique_id", columnNames = ["entity_name", "sql_id", "tenant_id"])
|
||||||
open class SqlModel : BaseTenantModel(){
|
open class SqlModel : BaseTenantModel() {
|
||||||
|
|
||||||
@JsonDeserialize(using = SafeStringDeserializer::class)
|
@JsonDeserialize(using = SafeStringDeserializer::class)
|
||||||
var sqlId: String = ""
|
var sqlId: String = ""
|
||||||
@ -181,6 +178,7 @@ open class SqlModel : BaseTenantModel(){
|
|||||||
@Column(columnDefinition = "text")
|
@Column(columnDefinition = "text")
|
||||||
var sql: String = ""
|
var sql: String = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
open class JobModel : BaseTenantModel() {
|
open class JobModel : BaseTenantModel() {
|
||||||
@Index(unique = true)
|
@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>() {
|
class SafeStringDeserializer : JsonDeserializer<String>() {
|
||||||
private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user