add plant integ

This commit is contained in:
gowthaman.b 2024-03-20 14:01:22 +05:30
parent fc361e3133
commit ce1f5f9b04
6 changed files with 122 additions and 191 deletions

View File

@ -18,6 +18,8 @@ app:
client: rmc
scripts:
path: /Users/gowthaman.b/IdeaProjects/rmc_modules_api/src/main/resources/scripts
integration:
rmc: https://www.readymixerp.com
security:
enforce_role_restriction: 'true'
private_key: |-

View File

@ -9,6 +9,7 @@ import com.restapi.domain.DataNotFoundException
import com.restapi.domain.ReminderLog
import com.restapi.domain.Session.currentTenant
import com.restapi.domain.Session.currentUser
import com.restapi.domain.Session.currentUserPlants
import com.restapi.domain.Session.objectMapper
import com.restapi.domain.Session.setAuthorizedUser
import com.restapi.domain.Session.signPayload
@ -43,15 +44,13 @@ fun main(args: Array<String>) {
//ratelimit based on IP Only
RateLimitUtil.keyFunction = { ctx -> ctx.header("X-Forwarded-For")?.split(",")?.get(0) ?: ctx.ip() }
Javalin
.create { cfg ->
Javalin.create { cfg ->
cfg.http.generateEtags = true
if (appConfig.corsEnabled()) {
cfg.plugins.enableCors { container ->
container.add {
it.allowHost(
"http://localhost:5173",
*appConfig.corsHosts().toTypedArray()
"http://localhost:5173", *appConfig.corsHosts().toTypedArray()
)
}
}
@ -60,8 +59,7 @@ fun main(args: Array<String>) {
cfg.compression.gzipOnly()
cfg.jsonMapper(JavalinJackson(objectMapper))
cfg.accessManager(AppAccessManager())
}
.routes {
}.routes {
path("/auth") {
get("/endpoint", Auth::endPoint)
@ -73,9 +71,7 @@ fun main(args: Array<String>) {
before("/api/*") { ctx ->
NaiveRateLimit.requestPerTimeUnit(
ctx,
appConfig.rateLimit().getOrDefault(30),
TimeUnit.MINUTES
ctx, appConfig.rateLimit().getOrDefault(30), TimeUnit.MINUTES
)
val authToken = ctx.getAuthHeader() ?: throw UnauthorizedResponse()
@ -106,6 +102,9 @@ fun main(args: Array<String>) {
}
path("/api") {
get("/plants") {
it.json(currentUserPlants())
}
post("/audit/{action}") {
logger.warn("User ${currentUser()} of tenant ${currentTenant()} has performed ${it.pathParam("action")} @ ${LocalDateTime.now()}")
it.json(mapOf("status" to true))
@ -117,14 +116,10 @@ fun main(args: Array<String>) {
post("/batch", VendorCtrl::createBatch, Roles(Role.Explicit("ROLE_VENDOR_CREATE")))
get("/{id}", VendorCtrl::get, Roles(Role.Explicit("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE")))
post(
"/getAll",
VendorCtrl::getAll,
Roles(Role.Explicit("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE"))
"/getAll", VendorCtrl::getAll, Roles(Role.Explicit("ROLE_VENDOR_VIEW", "ROLE_VENDOR_CREATE"))
)
get(
"quotes/{id}",
VendorCtrl::getQuotes,
Roles(Role.Explicit("ROLE_QUOTE_VIEW", "ROLE_QUOTE_CREATE", "ROLE_VENDOR_VIEW"))
"quotes/{id}", VendorCtrl::getQuotes, Roles(Role.Explicit("ROLE_QUOTE_VIEW", "ROLE_QUOTE_CREATE", "ROLE_VENDOR_VIEW"))
)
get("pos/{id}", VendorCtrl::getPos, Roles(Role.Explicit("ROLE_PO_VIEW", "ROLE_PO_CREATE`")))
put("/rate/{id}/{rating}", VendorCtrl::rate, Roles(Role.Explicit("ROLE_VENDOR_CREATE")))
@ -134,59 +129,43 @@ fun main(args: Array<String>) {
post("", IncomingInventoryCtrl::create, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
get("/next", IncomingInventoryCtrl::getNextNum, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
get(
"/{id}",
IncomingInventoryCtrl::get,
Roles(Role.Explicit("ROLE_INVENTORY_VIEW", "ROLE_INVENTORY_CREATE"))
"/{id}", IncomingInventoryCtrl::get, Roles(Role.Explicit("ROLE_INVENTORY_VIEW", "ROLE_INVENTORY_CREATE"))
)
put("/{id}", IncomingInventoryCtrl::update, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
post(
"/getAll",
IncomingInventoryCtrl::getAll,
Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW"))
"/getAll", IncomingInventoryCtrl::getAll, Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW"))
)
}
path("/outgoing") {
post("", OutgoingInventoryCtrl::create, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
get("/next", OutgoingInventoryCtrl::getNextNum, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
get(
"/{id}",
OutgoingInventoryCtrl::get,
Roles(Role.Explicit("ROLE_INVENTORY_VIEW", "ROLE_INVENTORY_CREATE"))
"/{id}", OutgoingInventoryCtrl::get, Roles(Role.Explicit("ROLE_INVENTORY_VIEW", "ROLE_INVENTORY_CREATE"))
)
put("/{id}", OutgoingInventoryCtrl::update, Roles(Role.Explicit("ROLE_INVENTORY_CREATE")))
post(
"/getAll",
OutgoingInventoryCtrl::getAll,
Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW"))
"/getAll", OutgoingInventoryCtrl::getAll, Roles(Role.Explicit("ROLE_INVENTORY_CREATE", "ROLE_INVENTORY_VIEW"))
)
}
path("/invoice") {
post("", InvoiceCtrl::create, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
get("/next", InvoiceCtrl::getNextNum, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
get(
"/{id}",
InvoiceCtrl::get,
Roles(Role.Explicit("ROLE_INVOICE_VIEW", "ROLE_INVOICE_CREATE"))
"/{id}", InvoiceCtrl::get, Roles(Role.Explicit("ROLE_INVOICE_VIEW", "ROLE_INVOICE_CREATE"))
)
put("/{id}", InvoiceCtrl::update, Roles(Role.Explicit("ROLE_INVOICE_CREATE")))
post(
"/getAll",
InvoiceCtrl::getAll,
Roles(Role.Explicit("ROLE_INVOICE_CREATE", "ROLE_INVOICE_VIEW"))
"/getAll", InvoiceCtrl::getAll, Roles(Role.Explicit("ROLE_INVOICE_CREATE", "ROLE_INVOICE_VIEW"))
)
}
path("/payment") {
post("", PaymentCtrl::create, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
get(
"/{id}",
PaymentCtrl::get,
Roles(Role.Explicit("ROLE_PAYMENT_VIEW", "ROLE_PAYMENT_CREATE"))
"/{id}", PaymentCtrl::get, Roles(Role.Explicit("ROLE_PAYMENT_VIEW", "ROLE_PAYMENT_CREATE"))
)
put("/{id}", PaymentCtrl::update, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
post(
"/getAll",
PaymentCtrl::getAll,
Roles(Role.Explicit("ROLE_PAYMENT_CREATE", "ROLE_PAYMENT_VIEW"))
"/getAll", PaymentCtrl::getAll, Roles(Role.Explicit("ROLE_PAYMENT_CREATE", "ROLE_PAYMENT_VIEW"))
)
delete("/{id}", PaymentCtrl::delete, Roles(Role.Explicit("ROLE_PAYMENT_CREATE")))
}
@ -194,88 +173,62 @@ fun main(args: Array<String>) {
post("", FleetCtrl::create, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
get(
"/{id}",
FleetCtrl::get,
Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
"/{id}", FleetCtrl::get, Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
)
put("/{id}", FleetCtrl::update, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
post(
"/getAll",
FleetCtrl::getAll,
Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
"/getAll", FleetCtrl::getAll, Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
)
delete("/{id}", FleetCtrl::delete, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
}
path("/renewal") {
post("", RenewalCtrl::create, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
get(
"/{id}",
RenewalCtrl::get,
Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
"/{id}", RenewalCtrl::get, Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
)
put("/{id}", RenewalCtrl::update, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
post(
"/getAll",
RenewalCtrl::getAll,
Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
"/getAll", RenewalCtrl::getAll, Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
)
delete("/{id}", RenewalCtrl::delete, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
}
path("/reminder") {
post("", ReminderCtrl::create, Roles(Role.Explicit("ROLE_REMINDER_CREATE")))
get(
"/{id}",
ReminderCtrl::get,
Roles(Role.Explicit("ROLE_REMINDER_VIEW", "ROLE_REMINDER_CREATE"))
"/{id}", ReminderCtrl::get, Roles(Role.Explicit("ROLE_REMINDER_VIEW", "ROLE_REMINDER_CREATE"))
)
put("/{id}", ReminderCtrl::update, Roles(Role.Explicit("ROLE_REMINDER_CREATE")))
post(
"/getAll",
ReminderLogCtrl::getAll,
Roles(Role.Explicit("ROLE_REMINDER_CREATE", "ROLE_REMINDER_VIEW"))
"/getAll", ReminderLogCtrl::getAll, Roles(Role.Explicit("ROLE_REMINDER_CREATE", "ROLE_REMINDER_VIEW"))
)
post(
"/done",
ReminderLogCtrl::done,
Roles(Role.Explicit("ROLE_REMAINDER_CREATE"))
"/done", ReminderLogCtrl::done, Roles(Role.Explicit("ROLE_REMAINDER_CREATE"))
)
get(
"/getAll/{id}",
ReminderCtrl::getAllByFleetId,
Roles(Role.Explicit("ROLE_REMINDER_CREATE", "ROLE_REMINDER_VIEW"))
"/getAll/{id}", ReminderCtrl::getAllByFleetId, Roles(Role.Explicit("ROLE_REMINDER_CREATE", "ROLE_REMINDER_VIEW"))
)
delete(
"/{id}",
ReminderCtrl::delete,
Roles(Role.Explicit("ROLE_REMINDER_CREATE"))
"/{id}", ReminderCtrl::delete, Roles(Role.Explicit("ROLE_REMINDER_CREATE"))
)
}
path("/vehicle") {
post("", VehicleCtrl::create, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
get(
"/{id}",
VehicleCtrl::get,
Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
"/{id}", VehicleCtrl::get, Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
)
put("/{id}", VehicleCtrl::update, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
post(
"/getAll",
VehicleCtrl::getAll,
Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
"/getAll", VehicleCtrl::getAll, Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
)
}
path("/fleetType") {
post("", FleetTypeCtrl::create, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
get(
"/{id}",
FleetTypeCtrl::get,
Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
"/{id}", FleetTypeCtrl::get, Roles(Role.Explicit("ROLE_FLEET_VIEW", "ROLE_FLEET_CREATE"))
)
put("/{id}", FleetTypeCtrl::update, Roles(Role.Explicit("ROLE_FLEET_CREATE")))
post(
"/getAll",
FleetTypeCtrl::getAll,
Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
"/getAll", FleetTypeCtrl::getAll, Roles(Role.Explicit("ROLE_FLEET_CREATE", "ROLE_FLEET_VIEW"))
)
}
path("/po") {
@ -283,14 +236,10 @@ fun main(args: Array<String>) {
post("", PurchaseOrderCtrl::create, Roles(Role.Explicit("ROLE_PO_CREATE")))
post("/batch", PurchaseOrderCtrl::createBatch, Roles(Role.Explicit("ROLE_PO_CREATE")))
post(
"/getAll",
PurchaseOrderCtrl::getAll,
Roles(Role.Explicit("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_VENDOR_CREATE"))
"/getAll", PurchaseOrderCtrl::getAll, Roles(Role.Explicit("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_VENDOR_CREATE"))
)
get(
"/{id}",
PurchaseOrderCtrl::get,
Roles(Role.Explicit("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_QUOTE_CREATE"))
"/{id}", PurchaseOrderCtrl::get, Roles(Role.Explicit("ROLE_PO_CREATE", "ROLE_PO_VIEW", "ROLE_QUOTE_CREATE"))
)
put("/{id}", PurchaseOrderCtrl::update, Roles(Role.Explicit("ROLE_PO_CREATE")))
put("/approve/{id}", PurchaseOrderCtrl::approve, Roles(Role.Explicit()))
@ -302,9 +251,7 @@ fun main(args: Array<String>) {
post("", QuotationCtrl::create, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
post("/batch", QuotationCtrl::createBatch, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
post(
"/getAll",
QuotationCtrl::getAll,
Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_QUOTE_VIEW"))
"/getAll", QuotationCtrl::getAll, Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_QUOTE_VIEW"))
)
get("/{id}", QuotationCtrl::get, Roles(Role.Explicit("ROLE_QUOTE_VIEW", "ROLE_QUOTE_CREATE")))
put("/{id}", QuotationCtrl::update, Roles(Role.Explicit("ROLE_QUOTE_CREATE")))
@ -322,33 +269,23 @@ fun main(args: Array<String>) {
post("", DocumentCtrl::create, Roles(Role.Explicit("ROLE_DOC_CREATE")))
//why type and refid are clubbed ??
get(
"/{type}/{refId}",
DocumentCtrl::getWithRefId,
Roles(Role.Explicit("ROLE_DOC_VIEW", "ROLE_PRODUCT_CREATE"))
"/{type}/{refId}", DocumentCtrl::getWithRefId, Roles(Role.Explicit("ROLE_DOC_VIEW", "ROLE_PRODUCT_CREATE"))
)
get("/{id}", DocumentCtrl::get, Roles(Role.Explicit("ROLE_DOC_VIEW", "ROLE_PRODUCT_CREATE")))
get(
"/print/{id}",
DocumentCtrl::print,
Roles(Role.Explicit("ROLE_DOC_CREATE", "ROLE_DOC_VIEW"))
"/print/{id}", DocumentCtrl::print, Roles(Role.Explicit("ROLE_DOC_CREATE", "ROLE_DOC_VIEW"))
)
delete("/{id}", DocumentCtrl::delete, Roles(Role.Explicit("ROLE_DOC_CREATE")))
}
path("/reqForQuote") {
post(
"",
RequestForQuote::create,
Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_PO_CREATE", "ROLE_RFQ_CREATE"))
"", RequestForQuote::create, Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_PO_CREATE", "ROLE_RFQ_CREATE"))
)
get(
"/{id}",
RequestForQuote::get,
Roles(Role.Explicit("ROLE_RFQ_CREATE", "ROLE_RFQ_VIEW", "ROLE_QUOTE_VIEW", "ROLE_PO_VIEW"))
"/{id}", RequestForQuote::get, Roles(Role.Explicit("ROLE_RFQ_CREATE", "ROLE_RFQ_VIEW", "ROLE_QUOTE_VIEW", "ROLE_PO_VIEW"))
)
put(
"/{id}",
RequestForQuote::update,
Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_PO_CREATE", "ROLE_RFQ_CREATE"))
"/{id}", RequestForQuote::update, Roles(Role.Explicit("ROLE_QUOTE_CREATE", "ROLE_PO_CREATE", "ROLE_RFQ_CREATE"))
)
}
}
@ -368,18 +305,11 @@ fun main(args: Array<String>) {
patch("/{entity}/{id}", Entities::patch, Roles(adminRole, updateRole))
delete("/{entity}/{id}", Entities::delete, Roles(adminRole, Role.Standard(Action.DELETE)))
}
}
.exception(DuplicateKeyException::class.java, Exceptions.dupKeyExceptionHandler)
.exception(DataIntegrityException::class.java, Exceptions.dataIntegrityException)
.exception(DataNotFoundException::class.java, Exceptions.dataNotFoundException)
.exception(IllegalArgumentException::class.java, Exceptions.illegalArgumentException)
.exception(JsonMappingException::class.java, Exceptions.jsonMappingException)
.exception(InvalidJwtException::class.java, Exceptions.invalidJwtException)
}.exception(DuplicateKeyException::class.java, Exceptions.dupKeyExceptionHandler).exception(DataIntegrityException::class.java, Exceptions.dataIntegrityException)
.exception(DataNotFoundException::class.java, Exceptions.dataNotFoundException).exception(IllegalArgumentException::class.java, Exceptions.illegalArgumentException)
.exception(JsonMappingException::class.java, Exceptions.jsonMappingException).exception(InvalidJwtException::class.java, Exceptions.invalidJwtException)
.start(appConfig.portNumber())
}
private fun Context.getAuthHeader() = header("Authorization")
?.replace("Bearer ", "")
?.replace("Bearer: ", "")
?.trim()
private fun Context.getAuthHeader() = header("Authorization")?.replace("Bearer ", "")?.replace("Bearer: ", "")?.trim()

View File

@ -58,6 +58,10 @@ interface AppConfig {
@Key("app.iam.client_secret")
fun iamClientSecret(): Optional<String>
@Key("app.integration.rmc")
@Default("https://www.readymixerp.com")
fun integrationRmc(): String
@Key("app.cache.redis_uri")
fun redisUri(): Optional<String>

View File

@ -2,6 +2,7 @@ package com.restapi.config
import com.fasterxml.jackson.module.kotlin.readValue
import com.restapi.config.AppConfig.Companion.appConfig
import com.restapi.domain.Plant
import com.restapi.domain.Session
import com.restapi.domain.Session.objectMapper
import io.javalin.http.BadRequestResponse
@ -9,6 +10,9 @@ import io.javalin.http.ContentType
import io.javalin.http.Context
import io.javalin.http.UnauthorizedResponse
import io.javalin.security.RouteRole
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import org.jose4j.jwk.HttpsJwks
import org.jose4j.jwt.consumer.JwtConsumerBuilder
import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver
@ -43,13 +47,10 @@ object Auth {
fun getAuthEndpoint(): AuthEndpoint {
return authCache.computeIfAbsent("AUTH") {
val wellKnown =
"${appConfig.iamUrl()}/realms/${appConfig.iamRealm()}/.well-known/openid-configuration"
val wellKnown = "${appConfig.iamUrl()}/realms/${appConfig.iamRealm()}/.well-known/openid-configuration"
val client = HttpClient.newHttpClient()
val req = HttpRequest.newBuilder()
.uri(URI.create(wellKnown))
.GET().build()
val req = HttpRequest.newBuilder().uri(URI.create(wellKnown)).GET().build()
objectMapper.readValue<AuthEndpoint>(
client.send(req, HttpResponse.BodyHandlers.ofString()).body()
@ -58,19 +59,11 @@ object Auth {
}
private val jwtConsumer = JwtConsumerBuilder()
.setRequireExpirationTime()
.setAllowedClockSkewInSeconds(30)
.setRequireSubject()
.setExpectedAudience("account")
.setExpectedIssuer(getAuthEndpoint().issuer)
.setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri)))
.build()
private val jwtConsumer = JwtConsumerBuilder().setRequireExpirationTime().setAllowedClockSkewInSeconds(30).setRequireSubject().setExpectedAudience("account")
.setExpectedIssuer(getAuthEndpoint().issuer).setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri))).build()
private val jwtConsumerSkipValidate = JwtConsumerBuilder()
.setSkipAllValidators()
.setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri)))
.build()
private val jwtConsumerSkipValidate =
JwtConsumerBuilder().setSkipAllValidators().setVerificationKeyResolver(HttpsJwksVerificationKeyResolver(HttpsJwks(getAuthEndpoint().jwksUri))).build()
fun validateAuthToken(authToken: String, skipValidate: Boolean = false): AuthUser {
@ -78,14 +71,29 @@ object Auth {
val jwtClaims = if (skipValidate) jwtConsumerSkipValidate.process(authToken) else jwtConsumer.process(authToken)
val userId = jwtClaims.jwtClaims.claimsMap["preferred_username"] as String
val tenant = jwtClaims.jwtClaims.claimsMap["tenant"] as String
val plantIds = jwtClaims.jwtClaims.claimsMap["plantIds"] as List<String>
val roles = ((jwtClaims.jwtClaims.claimsMap["realm_access"] as Map<String, Any>)["roles"]) as List<String>
val date = Date(jwtClaims.jwtClaims.expirationTime.valueInMillis)
HttpClients.createDefault().use { h ->
//sync plant's from rmc to here, just name and id
for (plantId in plantIds) {
val existing = Session.database.find(Plant::class.java).where().eq("plantId", plantId).findOne()
if (existing == null) {
h.execute(HttpGet("${appConfig.integrationRmc()}/plant?id=${plantId}")).use { r ->
if (r.statusLine.statusCode == 200) {
Session.database.save(Plant().apply {
this.plantId = plantId
this.plantName = EntityUtils.toString(r.entity)
})
}
}
}
}
}
return AuthUser(
userName = userId,
tenant = tenant,
roles = roles,
token = authToken,
expiry = LocalDateTime.from(date.toInstant().atZone(ZoneId.systemDefault()))
userName = userId, tenant = tenant, roles = roles, token = authToken, expiry = LocalDateTime.from(date.toInstant().atZone(ZoneId.systemDefault())), plantIds = plantIds
)
}
@ -100,8 +108,7 @@ object Auth {
fun init(ctx: Context) {
val endpoint = getAuthEndpoint().authorizationEndpoint
val redirectUrl =
"$endpoint?response_type=code&client_id=${appConfig.iamClient()}&redirect_uri=${appConfig.iamClientRedirectUri()}&scope=profile&state=1234zyx"
val redirectUrl = "$endpoint?response_type=code&client_id=${appConfig.iamClient()}&redirect_uri=${appConfig.iamClientRedirectUri()}&scope=profile&state=1234zyx"
ctx.redirect(redirectUrl)
}
@ -112,9 +119,7 @@ object Auth {
val ep = getAuthEndpoint().tokenEndpoint
val httpClient = HttpClient.newHttpClient()
val req = HttpRequest.newBuilder()
.uri(URI.create(ep))
.POST(
val req = HttpRequest.newBuilder().uri(URI.create(ep)).POST(
HttpRequest.BodyPublishers.ofString(
getFormDataAsString(
mapOf(
@ -125,9 +130,7 @@ object Auth {
)
)
)
)
.header("Content-Type", "application/x-www-form-urlencoded")
.build()
).header("Content-Type", "application/x-www-form-urlencoded").build()
val message = httpClient.send(req, HttpResponse.BodyHandlers.ofString()).body()
val atResponse = objectMapper.readValue<AuthTokenResponse>(message)
@ -135,8 +138,7 @@ object Auth {
//keep track of this for renewal when asked by client
Session.redis.lpush(
"$AUTH_TOKEN${parsed.userName}",
objectMapper.writeValueAsString(
"$AUTH_TOKEN${parsed.userName}", objectMapper.writeValueAsString(
atResponse.copy(
createdAt = LocalDateTime.now()
)
@ -147,10 +149,7 @@ object Auth {
fun refreshToken(ctx: Context) {
//refresh authToken
val authToken = ctx.header("Authorization")
?.replace("Bearer ", "")
?.replace("Bearer: ", "")
?.trim() ?: throw UnauthorizedResponse()
val authToken = ctx.header("Authorization")?.replace("Bearer ", "")?.replace("Bearer: ", "")?.trim() ?: throw UnauthorizedResponse()
val authUser = validateAuthToken(authToken, skipValidate = true)
val client = ctx.queryParam("client") ?: throw BadRequestResponse("client not sent")
@ -159,10 +158,7 @@ object Auth {
val key = "$AUTH_TOKEN${authUser.userName}"
val found = Session.redis.llen(key)
logger.warn("for user ${authUser.userName}, found from redis, $key => $found entries")
val foundOldAt = (0..found)
.mapNotNull { Session.redis.lindex(key, it) }
.map { objectMapper.readValue<AuthTokenResponse>(it) }
.firstOrNull { it.accessToken == authToken }
val foundOldAt = (0..found).mapNotNull { Session.redis.lindex(key, it) }.map { objectMapper.readValue<AuthTokenResponse>(it) }.firstOrNull { it.accessToken == authToken }
?: throw BadRequestResponse("authToken not found in cache")
val createdAt = foundOldAt.createdAt ?: throw BadRequestResponse("created at is missing")
@ -177,9 +173,7 @@ object Auth {
logger.warn("We can refresh the token for ${authUser.userName}, expires = $expiresAt, refresh Till = $rtExpiresAt")
val ep = getAuthEndpoint().tokenEndpoint
val httpClient = HttpClient.newHttpClient()
val req = HttpRequest.newBuilder()
.uri(URI.create(ep))
.POST(
val req = HttpRequest.newBuilder().uri(URI.create(ep)).POST(
HttpRequest.BodyPublishers.ofString(
getFormDataAsString(
mapOf(
@ -190,16 +184,13 @@ object Auth {
)
)
)
)
.header("Content-Type", "application/x-www-form-urlencoded")
.build()
).header("Content-Type", "application/x-www-form-urlencoded").build()
val message = httpClient.send(req, HttpResponse.BodyHandlers.ofString()).body()
val atResponse = objectMapper.readValue<AuthTokenResponse>(message)
val parsed = validateAuthToken(atResponse.accessToken)
Session.redis.lpush(
"AUTH_TOKEN_${parsed.userName}",
objectMapper.writeValueAsString(
"AUTH_TOKEN_${parsed.userName}", objectMapper.writeValueAsString(
atResponse.copy(createdAt = LocalDateTime.now())
)
)
@ -221,11 +212,7 @@ object Auth {
}
data class AuthUser(
val userName: String,
val tenant: String,
val roles: List<String>,
val token: String,
val expiry: LocalDateTime
val userName: String, val tenant: String, val roles: List<String>, val token: String, val expiry: LocalDateTime, val plantIds: List<String>
)
enum class Action {

View File

@ -39,7 +39,7 @@ object Session {
private val logger = LoggerFactory.getLogger("session")
private val currentUser = object : ThreadLocal<AuthUser>() {
override fun initialValue(): AuthUser {
return AuthUser("", "", emptyList(), "", LocalDateTime.now())
return AuthUser("", "", emptyList(), "", LocalDateTime.now(), emptyList())
}
}
@ -182,6 +182,13 @@ object Session {
fun currentTenant() = currentUser.get().tenant
fun currentRoles() = currentUser.get().roles
fun currentToken() = currentUser.get().token
fun currentUserPlants() = currentUser.get().plantIds.map {
Session.database.find(Plant::class.java)
.where()
.eq("plantId", it)
.findOne()
}.filterNotNull()
fun jwk() = keypair.toParams(JsonWebKey.OutputControlLevel.PUBLIC_ONLY)
fun Database.findDataModelByEntityAndUniqId(entity: String, uniqId: String): DataModel {

View File

@ -14,11 +14,7 @@ import javax.persistence.*
data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now())
data class POProducts(
val productId: String = "",
val productName: String = "",
val unitPrice: Double = 0.0,
val quantity: Double = 0.0,
val description: String = ""
val productId: String = "", val productName: String = "", val unitPrice: Double = 0.0, val quantity: Double = 0.0, val description: String = ""
)
@ -112,15 +108,13 @@ open class AuditLog : BaseTenantModel() {
@DbJsonB
@Index(
definition = "create index audit_log_values_idx on audit_log using GIN (data)",
platforms = [Platform.POSTGRES]
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]
definition = "create index audit_log_changes_idx on audit_log using GIN (changes)", platforms = [Platform.POSTGRES]
)
var changes: Map<String, Any> = hashMapOf()
}
@ -636,3 +630,10 @@ open class ReminderLog : BaseTenantModel() {
@DbArray
var documents: List<String>? = null
}
@Entity
@Index(name="plantid_idx", columnNames = ["plant_id"], unique = true)
open class Plant : BaseModel() {
var plantId: String = ""
var plantName: String = ""
}