2024-02-08 17:50:08 +05:30

67 lines
2.7 KiB
Kotlin

package com.restapi
import com.restapi.config.AppConfig.Companion.appConfig
import com.restapi.config.Role
import com.restapi.config.Roles
import com.restapi.domain.EntityModel
import io.javalin.http.Context
import io.javalin.http.Handler
import io.javalin.http.HttpStatus
import io.javalin.security.AccessManager
import io.javalin.security.RouteRole
import org.slf4j.LoggerFactory
import com.restapi.domain.Session.currentRoles
import com.restapi.domain.Session.database
class AppAccessManager : AccessManager {
private val logger = LoggerFactory.getLogger("Access")
private fun loadEntityActionRole(entity: String?, action: String?): List<String> {
if (entity == null || action == null) return emptyList()
return database.find(EntityModel::class.java)
.where()
.eq("name", entity)
.findOne()
?.actions
?.filter { it.equals(action, ignoreCase = true) }
?.map { "role_${entity}_$it" } ?: emptyList()
}
override fun manage(handler: Handler, ctx: Context, routeRoles: Set<RouteRole>) {
val pathParamMap = ctx.pathParamMap()
val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$")
if (pathParamMap.values.count { !regex.matches(it) } > 0) {
ctx.status(HttpStatus.FORBIDDEN).result("invalid request")
} else {
val entity = pathParamMap["entity"]
val action = pathParamMap["action"]
val allowedRoles = routeRoles.map { it as Roles }.flatMap { it.roles.toList() }.flatMap { role ->
when (role) {
Role.DbOps -> listOf("ROLE_DB_OPS")
Role.Entity -> loadEntityActionRole(entity, action)
is Role.Standard -> role.action.toList().map { "ROLE_${entity}_${it}" }
is Role.Explicit -> role.roles.toList() + listOf("ROLE_ADMIN")
}.map(String::uppercase)
}
val isAllowed = currentRoles().count { allowedRoles.contains(it) } > 0
logger.debug(
"entity - {}, action {}, user roles = {}, allowed = {}, isAllowed? {}, enforce? {}",
entity,
action,
currentRoles(),
allowedRoles,
isAllowed,
appConfig.enforceRoleRestriction()
)
if (isAllowed || !appConfig.enforceRoleRestriction() || allowedRoles.isEmpty()) {
//if role is allowed, or enforcement is turned off or no roles are explicitly allowed
handler.handle(ctx)
} else {
ctx.status(HttpStatus.FORBIDDEN).result("user not allowed to do this")
}
}
}
}