Skip to content

Commit

Permalink
Merge pull request #22 from darkredz/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
darkredz committed Dec 12, 2020
2 parents 0fdd43d + 773cdba commit 569fd81
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 48 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>io.zeko</groupId>
<artifactId>zeko-restapi</artifactId>
<version>1.2.3-SNAPSHOT</version>
<version>1.2.5-SNAPSHOT</version>
<packaging>jar</packaging>

<name>${project.groupId}:${project.artifactId}</name>
Expand Down Expand Up @@ -126,7 +126,7 @@
<dependency>
<groupId>io.zeko</groupId>
<artifactId>zeko-validator</artifactId>
<version>1.1.2</version>
<version>1.1.4</version>
</dependency>

<dependency>
Expand Down
22 changes: 18 additions & 4 deletions src/main/kotlin/io/zeko/restapi/core/controllers/ApiController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,27 @@ import java.lang.Double
import java.lang.Float
import java.lang.Long
import io.vertx.kotlin.core.json.*
import io.zeko.db.sql.utilities.toCamelCase
import io.zeko.restapi.core.utilities.endJson
import io.zeko.restapi.core.utilities.errorJson
import io.zeko.restapi.core.utilities.validate
import io.zeko.restapi.core.validations.ValidateResult
import io.zeko.restapi.core.validations.ValidationError

open abstract class ApiController(val vertx: Vertx, val logger: Logger, val context: RoutingContext) : Controller {

open abstract class ApiController(
val vertx: Vertx,
val logger: Logger,
val context: RoutingContext
) : Controller {
var params: Map<String, String>? = null
var useCamelCaseResponse: Boolean = false

init {
val entries = context.request().params().entries()
params = entries.associate { Pair(it.key, it.value) }
if (context.get<Boolean>("useCamelCaseResponse")) {
useCamelCaseResponse = true
}
}

override fun inputRules(): Map<String, Map<String, String>> {
Expand Down Expand Up @@ -66,15 +74,21 @@ open abstract class ApiController(val vertx: Vertx, val logger: Logger, val cont
return validateResult
}

protected fun getJsonKey(key: String): String {
if (useCamelCaseResponse)
return key.toCamelCase()
return key
}

protected open fun outputNoRulesError(statusCode: Int, errorCode: Int): ValidateResult {
val values = HashMap<String, Any?>()
val errors = mapOf(
"server_error" to listOf("Undefined input rules for this endpoint")
getJsonKey("server_error") to listOf("Undefined input rules for this endpoint")
)
val validateResult = ValidateResult(false, -1, errors, values)
val res = json {
obj(
"error_code" to errorCode,
getJsonKey("error_code") to errorCode,
"errors" to validateResult.errors
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ mvn clean compile vertx:run -Dvertx.verticle="$packageName.BootstrapVerticle" \
<properties>
<vertx.verticle>$packageName.BootstrapVerticle</vertx.verticle>
<kotlin.version>1.3.61</kotlin.version>
<zeko-restapi.version>1.2.3</zeko-restapi.version>
<zeko-restapi.version>1.2.4</zeko-restapi.version>
<vertx.version>3.9.4</vertx.version>
<micrometer.version>1.1.0</micrometer.version>
<java.version>1.8</java.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ open class JWTAuthHandler(
protected val jwtAuth: JWTAuth,
protected val skipAuth: List<String>,
protected val continueAfterFail: Boolean = false,
protected val statusFail: Int = 401
protected val statusFail: Int = 401,
protected val useCamelCase: Boolean = false
) : Handler<RoutingContext> {

override fun handle(ctx: RoutingContext) {
Expand Down Expand Up @@ -43,7 +44,7 @@ open class JWTAuthHandler(

if (!skip) {
var authHeader = ctx.request().getHeader(HttpHeaders.AUTHORIZATION.toString())
val helper = JWTAuthHelper(jwtAuth, null)
val helper = JWTAuthHelper(jwtAuth, null, useCamelCase)

helper.validateToken(authHeader) { user, result ->
if (user == null) {
Expand Down
65 changes: 33 additions & 32 deletions src/main/kotlin/io/zeko/restapi/core/security/JWTAuthHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@ import io.vertx.ext.auth.jwt.JWTAuthOptions
import io.vertx.ext.jwt.JWTOptions
import io.vertx.kotlin.core.json.json
import io.vertx.kotlin.core.json.obj

open class JWTAuthHelper(val jwtAuth: JWTAuth, val jwtAuthRefresh: JWTAuth?) {
val expireMsg = json {
obj(
"auth" to false,
"error" to obj(
"token_status" to "expired"
import io.zeko.db.sql.utilities.toCamelCase

open class JWTAuthHelper(val jwtAuth: JWTAuth, val jwtAuthRefresh: JWTAuth?, val useCamelCase: Boolean = false) {
val expireMsg: JsonObject
val invalidMsg: JsonObject

init {
expireMsg = json {
obj(
"auth" to false,
"error" to obj(
getJsonKey("token_status") to "expired"
)
)
)
}
}

val invalidMsg = json {
obj(
"auth" to false,
"error" to obj(
"token_status" to "invalid"
invalidMsg = json {
obj(
"auth" to false,
"error" to obj(
getJsonKey("token_status") to "invalid"
)
)
)
}
}

fun refreshToken(
Expand Down Expand Up @@ -69,8 +75,8 @@ open class JWTAuthHelper(val jwtAuth: JWTAuth, val jwtAuthRefresh: JWTAuth?) {

if (accessToken.isNullOrEmpty()) {
authHandler(null, invalidMsg)
} else if (user.containsKey("for_token") && user["for_token"] == accessToken) {
user.remove("for_token")
} else if (user.containsKey(getJsonKey("for_token")) && user[getJsonKey("for_token")] == accessToken) {
user.remove(getJsonKey("for_token"))
authHandler(
authUser,
JsonObject(generateAuthTokens(JsonObject(user), tokenExpireSeconds, refreshExpireSeconds))
Expand Down Expand Up @@ -111,31 +117,26 @@ open class JWTAuthHelper(val jwtAuth: JWTAuth, val jwtAuthRefresh: JWTAuth?) {
fun generateAuthTokens(
jwtAuthData: JsonObject,
tokenExpireSeconds: Int = 259200,
refreshExpireSeconds: Int = 604800,
useCamelCase: Boolean = false
refreshExpireSeconds: Int = 604800
): Map<String, String> {
val token = jwtAuth.generateToken(jwtAuthData, JWTOptions().setExpiresInSeconds(tokenExpireSeconds)) + ""

val refreshData = if (useCamelCase) {
jwtAuthData.copy().put("forToken", token)
} else {
jwtAuthData.copy().put("for_token", token)
}
val refreshData = jwtAuthData.copy().put(getJsonKey("for_token"), token)
val refreshToken =
jwtAuthRefresh?.generateToken(refreshData, JWTOptions().setExpiresInSeconds(refreshExpireSeconds)) + ""

if (useCamelCase) {
return mapOf(
"accessToken" to token,
"refreshToken" to refreshToken
)
}
return mapOf(
"access_token" to token,
"refresh_token" to refreshToken
getJsonKey("access_token") to token,
getJsonKey("refresh_token") to refreshToken
)
}

protected fun getJsonKey(key: String): String {
if (useCamelCase)
return key.toCamelCase()
return key
}

companion object {
@JvmStatic
fun createJWTAuth(vertx: Vertx, jwtOptions: JWTAuthOptions) = JWTAuth.create(vertx, jwtOptions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ open class JWTAuthRefreshHandler(
accessToken = "invalid"
}

val refreskTokenKey = if (useCamelCase) "refreshToken" else "refresh_token"
var refreshToken = ctx.request().params().get(refreskTokenKey) + ""
val helper = JWTAuthHelper(jwtAuth, jwtAuthRefresh)
val refreshTokenKey = if (useCamelCase) "refreshToken" else "refresh_token"
var refreshToken = ctx.request().params().get(refreshTokenKey) + ""
val helper = JWTAuthHelper(jwtAuth, jwtAuthRefresh, useCamelCase)

helper.refreshToken(
refreshToken, accessToken, tokenExpireSeconds,
refreshExpireSeconds, refreshAfterExpired
) { user, result ->
if (user == null) {
ctx.response().setStatusCode(401)
ctx.response().statusCode = 401
ctx.endJson(result)
} else {
ctx.endJson(result)
Expand Down
5 changes: 4 additions & 1 deletion src/main/kotlin/io/zeko/restapi/core/utilities/controller.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ fun RoutingContext.errorJson(errors: Map<String, List<String>>, code: Int = 422)
}

fun RoutingContext.errorJson(errors: Map<String, List<String>>, statusCode: Int = 422, errorCode: Int = 422) {
val useCamelCase = this.get<Boolean>("useCamelCaseResponse")
val errCodeKey = if (useCamelCase) "error_code" else "errorCode"

this.response().setStatusCode(statusCode)
.putHeader("Content-Type", "application/json")
.end(json {
obj(
"error_code" to errorCode,
errCodeKey to errorCode,
"errors" to JsonObject(errors)
)
}.encode())
Expand Down
16 changes: 14 additions & 2 deletions src/main/kotlin/io/zeko/restapi/core/verticles/RestApiVerticle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,23 @@ open abstract class ZekoVerticle : CoroutineVerticle() {
}
}

fun bindRoutes(schema: RouteSchema, router: Router, logger: Logger) {
fun bindRoutes(schema: RouteSchema, router: Router, logger: Logger, useCamelCaseResponse: Boolean = false) {
if (useCamelCaseResponse) {
router.route().handler {
it.put("useCamelCaseResponse", true)
it.next()
}
}
schema.handleRoutes(router, logger, this::koto)
}

fun bindRoutes(schemaClass: String, router: Router, logger: Logger) {
fun bindRoutes(schemaClass: String, router: Router, logger: Logger, useCamelCaseResponse: Boolean = false) {
if (useCamelCaseResponse) {
router.route().handler {
it.put("useCamelCaseResponse", true)
it.next()
}
}
try {
val cls = Class.forName(schemaClass)
val constructor = cls.constructors.first()
Expand Down

0 comments on commit 569fd81

Please sign in to comment.