-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Authentication through Envoy bound to Keycloak (#15)
* Experiments with ydb native * Fix building * Envoy authentication with Keycloak
- Loading branch information
Showing
54 changed files
with
9,873 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,7 @@ | |
/kotlin-js-store/ | ||
**/logs/ | ||
!**/src/logs/ | ||
|
||
**/.vscode/ | ||
|
||
**/Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
crowdproj-ad-back/crowdproj-ad-app-ktor/src/commonMain/kotlin/helpers/JwtHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.crowdproj.ad.app.helpers | ||
|
||
import com.crowdproj.ad.common.models.CwpAdUserId | ||
import com.crowdproj.ad.common.permissions.CwpAdPrincipalModel | ||
import com.crowdproj.ad.common.permissions.CwpAdUserGroups | ||
import io.ktor.server.request.* | ||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.json.Json | ||
import kotlin.io.encoding.Base64 | ||
import kotlin.io.encoding.ExperimentalEncodingApi | ||
|
||
@OptIn(ExperimentalEncodingApi::class) | ||
fun ApplicationRequest.jwt2principal(): CwpAdPrincipalModel = this.header("x-jwt-payload") | ||
?.let { jwtHeader -> | ||
val jwtJson = Base64.decode(jwtHeader).decodeToString() | ||
println("JWT JSON PAYLOAD: $jwtJson") | ||
val jwtObj = jsMapper.decodeFromString(JwtPayload.serializer(), jwtJson) | ||
jwtObj.toPrincipal() | ||
} | ||
?: run { | ||
println("No jwt found in headers") | ||
CwpAdPrincipalModel.NONE | ||
} | ||
|
||
private val jsMapper = Json { | ||
ignoreUnknownKeys = true | ||
} | ||
|
||
@Serializable | ||
private data class JwtPayload( | ||
val aud: List<String>? = null, | ||
val sub: String? = null, | ||
@SerialName("family_name") | ||
val familyName: String? = null, | ||
@SerialName("given_name") | ||
val givenName: String? = null, | ||
@SerialName("middle_name") | ||
val middleName: String? = null, | ||
val groups: List<String>? = null, | ||
) | ||
|
||
private fun JwtPayload.toPrincipal(): CwpAdPrincipalModel = CwpAdPrincipalModel( | ||
id = sub?.let { CwpAdUserId(it) } ?: CwpAdUserId.NONE, | ||
fname = givenName ?: "", | ||
mname = middleName ?: "", | ||
lname = familyName ?: "", | ||
groups = groups?.mapNotNull { it.toPrincipalGroup() }?.toSet() ?: emptySet(), | ||
) | ||
|
||
private fun String?.toPrincipalGroup(): CwpAdUserGroups? = when (this?.uppercase()) { | ||
"USER" -> CwpAdUserGroups.USER | ||
"ADMIN_AD" -> CwpAdUserGroups.ADMIN_AD | ||
"MODERATOR_MP" -> CwpAdUserGroups.MODERATOR_MP | ||
"TEST" -> CwpAdUserGroups.TEST | ||
"BAN_AD" -> CwpAdUserGroups.BAN_AD | ||
// TODO сделать обработку ошибок | ||
else -> null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
crowdproj-ad-back/crowdproj-ad-app-ktor/src/commonTest/kotlin/AdRequestSerializationTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.crowdproj.ad.app | ||
|
||
import com.crowdproj.ad.api.v1.models.* | ||
import kotlinx.serialization.json.Json | ||
import kotlin.test.Test | ||
|
||
class AdRequestSerializationTest { | ||
@Test | ||
fun test() { | ||
val req = AdCreateRequest( | ||
ad = AdCreateObject( | ||
title = "my title", | ||
description = "my description", | ||
adType = DealSide.DEMAND, | ||
visibility = AdVisibility.PUBLIC, | ||
productId = "23423423", | ||
), | ||
debug = AdDebug( | ||
mode = AdRequestDebugMode.STUB, | ||
stub = AdRequestDebugStubs.SUCCESS, | ||
) | ||
) | ||
val json = Json.encodeToString(AdCreateRequest.serializer(), req) | ||
println("REQUEST: $json") | ||
} | ||
} |
158 changes: 158 additions & 0 deletions
158
crowdproj-ad-back/crowdproj-ad-app-ktor/src/commonTest/kotlin/stub/V1AdStubApiTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
package com.crowdproj.ad.app.stub | ||
|
||
import com.crowdproj.ad.api.v1.cwpAdApiV1Json | ||
import com.crowdproj.ad.api.v1.models.* | ||
import com.crowdproj.ad.app.module | ||
import io.ktor.client.* | ||
import io.ktor.client.call.* | ||
import io.ktor.client.plugins.contentnegotiation.* | ||
import io.ktor.client.request.* | ||
import io.ktor.http.* | ||
import io.ktor.serialization.kotlinx.json.* | ||
import io.ktor.server.testing.* | ||
import kotlin.test.Test | ||
import kotlin.test.assertEquals | ||
|
||
class V1AdStubApiTest { | ||
|
||
@Test | ||
fun create() = v2TestApplication { client -> | ||
val response = client.post("/v1/create") { | ||
val requestObj = AdCreateRequest( | ||
ad = AdCreateObject( | ||
title = "Болт", | ||
description = "КРУТЕЙШИЙ", | ||
adType = DealSide.DEMAND, | ||
visibility = AdVisibility.PUBLIC, | ||
), | ||
debug = AdDebug( | ||
mode = AdRequestDebugMode.STUB, | ||
stub = AdRequestDebugStubs.SUCCESS | ||
) | ||
) | ||
contentType(ContentType.Application.Json) | ||
header("X-Request-ID", "12345") | ||
setBody(requestObj) | ||
} | ||
val responseObj = response.body<IResponseAd>() as AdCreateResponse | ||
assertEquals(200, response.status.value) | ||
assertEquals("666", responseObj.ad?.id) | ||
} | ||
|
||
@Test | ||
fun read() = v2TestApplication { client -> | ||
val response = client.post("/v1/read") { | ||
val requestObj = AdReadRequest( | ||
ad = AdReadObject("666"), | ||
debug = AdDebug( | ||
mode = AdRequestDebugMode.STUB, | ||
stub = AdRequestDebugStubs.SUCCESS | ||
) | ||
) | ||
contentType(ContentType.Application.Json) | ||
header("X-Request-ID", "12345") | ||
setBody(requestObj) | ||
} | ||
val responseObj = response.body<IResponseAd>() as AdReadResponse | ||
assertEquals(200, response.status.value) | ||
assertEquals("666", responseObj.ad?.id) | ||
} | ||
|
||
@Test | ||
fun update() = v2TestApplication { client -> | ||
val response = client.post("/v1/update") { | ||
val requestObj = AdUpdateRequest( | ||
ad = AdUpdateObject( | ||
id = "666", | ||
title = "Болт", | ||
description = "КРУТЕЙШИЙ", | ||
adType = DealSide.DEMAND, | ||
visibility = AdVisibility.PUBLIC, | ||
), | ||
debug = AdDebug( | ||
mode = AdRequestDebugMode.STUB, | ||
stub = AdRequestDebugStubs.SUCCESS | ||
) | ||
) | ||
contentType(ContentType.Application.Json) | ||
header("X-Request-ID", "12345") | ||
setBody(requestObj) | ||
} | ||
val responseObj = response.body<IResponseAd>() as AdUpdateResponse | ||
assertEquals(200, response.status.value) | ||
assertEquals("666", responseObj.ad?.id) | ||
} | ||
|
||
@Test | ||
fun delete() = v2TestApplication { client -> | ||
val response = client.post("/v1/delete") { | ||
val requestObj = AdDeleteRequest( | ||
ad = AdDeleteObject( | ||
id = "666", | ||
lock = "123" | ||
), | ||
debug = AdDebug( | ||
mode = AdRequestDebugMode.STUB, | ||
stub = AdRequestDebugStubs.SUCCESS | ||
) | ||
) | ||
contentType(ContentType.Application.Json) | ||
header("X-Request-ID", "12345") | ||
setBody(requestObj) | ||
} | ||
val responseObj = response.body<IResponseAd>() as AdDeleteResponse | ||
assertEquals(200, response.status.value) | ||
assertEquals("666", responseObj.ad?.id) | ||
} | ||
|
||
@Test | ||
fun search() = v2TestApplication { client -> | ||
val response = client.post("/v1/search") { | ||
val requestObj = AdSearchRequest( | ||
adFilter = AdSearchFilter(), | ||
debug = AdDebug( | ||
mode = AdRequestDebugMode.STUB, | ||
stub = AdRequestDebugStubs.SUCCESS | ||
) | ||
) | ||
contentType(ContentType.Application.Json) | ||
header("X-Request-ID", "12345") | ||
setBody(requestObj) | ||
} | ||
val responseObj = response.body<IResponseAd>() as AdSearchResponse | ||
assertEquals(200, response.status.value) | ||
assertEquals("d-666-01", responseObj.ads?.first()?.id) | ||
} | ||
|
||
@Test | ||
fun offers() = v2TestApplication { client -> | ||
val response = client.post("/v1/offers") { | ||
val requestObj = AdOffersRequest( | ||
ad = AdReadObject( | ||
id = "666" | ||
), | ||
debug = AdDebug( | ||
mode = AdRequestDebugMode.STUB, | ||
stub = AdRequestDebugStubs.SUCCESS | ||
) | ||
) | ||
contentType(ContentType.Application.Json) | ||
header("X-Request-ID", "12345") | ||
setBody(requestObj) | ||
} | ||
val responseObj = response.body<IResponseAd>() as AdOffersResponse | ||
assertEquals(200, response.status.value) | ||
assertEquals("s-666-01", responseObj.ads?.first()?.id) | ||
} | ||
|
||
private fun v2TestApplication(function: suspend (HttpClient) -> Unit): Unit = testApplication { | ||
application { module() } | ||
val client = createClient { | ||
install(ContentNegotiation) { | ||
json(cwpAdApiV1Json) | ||
} | ||
} | ||
function(client) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
...proj-ad-back/crowdproj-ad-common/src/commonMain/kotlin/permissions/CwpAdPrincipalModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.crowdproj.ad.common.permissions | ||
|
||
import com.crowdproj.ad.common.models.CwpAdUserId | ||
|
||
data class CwpAdPrincipalModel( | ||
val id: CwpAdUserId = CwpAdUserId.NONE, | ||
val fname: String = "", | ||
val mname: String = "", | ||
val lname: String = "", | ||
val groups: Set<CwpAdUserGroups> = emptySet() | ||
) { | ||
companion object { | ||
val NONE = CwpAdPrincipalModel() | ||
} | ||
} |
Oops, something went wrong.