Skip to content

Commit 0798731

Browse files
committed
task: add logout support. Remove ktor wrapper.
1 parent ffc2346 commit 0798731

File tree

12 files changed

+182
-215
lines changed

12 files changed

+182
-215
lines changed
Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,49 @@
11
package com.ctrlhub.core
22

3-
import com.ctrlhub.core.api.KtorApiClient
43
import com.ctrlhub.core.auth.AuthRouter
54
import com.ctrlhub.core.iam.IamRouter
5+
import io.ktor.client.HttpClient
6+
import io.ktor.client.engine.cio.CIO
7+
import io.ktor.client.plugins.UserAgent
8+
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
9+
import io.ktor.client.plugins.defaultRequest
10+
import io.ktor.http.HttpHeaders
11+
import io.ktor.serialization.kotlinx.json.json
12+
import io.ktor.util.appendIfNameAbsent
13+
import kotlinx.serialization.json.Json
614

7-
class Api private constructor(apiClient: KtorApiClient) {
8-
val auth: AuthRouter = AuthRouter(apiClient)
9-
val iam: IamRouter = IamRouter(apiClient)
15+
class Api private constructor(httpClient: HttpClient) {
16+
val auth: AuthRouter = AuthRouter(httpClient)
17+
val iam: IamRouter = IamRouter(httpClient)
1018

1119
companion object {
1220
fun create(): Api {
13-
return Api(KtorApiClient.create(Config.apiBaseUrl))
21+
val httpClient = HttpClient(CIO)
22+
return Api(configureHttpClient(httpClient, Config.apiBaseUrl))
23+
}
24+
25+
fun create(httpClient: HttpClient): Api {
26+
return Api(configureHttpClient(httpClient, Config.apiBaseUrl))
27+
}
28+
29+
private fun configureHttpClient(baseClient: HttpClient, baseUrl: String? = null): HttpClient {
30+
return baseClient.config {
31+
baseUrl?.let {
32+
defaultRequest {
33+
url(baseUrl)
34+
}
35+
}
36+
defaultRequest {
37+
headers.appendIfNameAbsent(HttpHeaders.ContentType, "application/json")
38+
}
39+
expectSuccess = true
40+
install(ContentNegotiation) {
41+
json(Json { ignoreUnknownKeys = true })
42+
}
43+
install(UserAgent) {
44+
agent = Config.userAgent
45+
}
46+
}
1447
}
1548
}
1649
}

src/main/kotlin/com/ctrlhub/core/Config.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ enum class Environment {
77

88
object Config {
99
var environment: Environment = Environment.PRODUCTION
10+
var userAgent: String = "CtrlHub SDK"
1011

1112
val authBaseUrl: String
1213
get() = when (environment) {

src/main/kotlin/com/ctrlhub/core/api/KtorApiClient.kt

Lines changed: 0 additions & 88 deletions
This file was deleted.

src/main/kotlin/com/ctrlhub/core/auth/AuthRouter.kt

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,26 @@ package com.ctrlhub.core.auth
33
import com.ctrlhub.core.Config
44
import com.ctrlhub.core.api.ApiClientException
55
import com.ctrlhub.core.api.ApiException
6-
import com.ctrlhub.core.api.KtorApiClient
76
import com.ctrlhub.core.auth.payload.LoginPayload
7+
import com.ctrlhub.core.auth.payload.LogoutPayload
88
import com.ctrlhub.core.auth.response.AuthFlowResponse
99
import com.ctrlhub.core.auth.response.CompleteResponse
1010
import com.ctrlhub.core.router.Router
11+
import io.ktor.client.HttpClient
1112
import io.ktor.client.call.*
1213
import io.ktor.client.plugins.*
14+
import io.ktor.client.request.delete
15+
import io.ktor.client.request.get
16+
import io.ktor.client.request.post
17+
import io.ktor.client.request.setBody
1318
import io.ktor.http.*
19+
import kotlinx.serialization.encodeToString
20+
import kotlinx.serialization.json.Json
1421

15-
class AuthRouter(apiClient: KtorApiClient) : Router(apiClient = apiClient) {
22+
class AuthRouter(httpClient: HttpClient) : Router(httpClient = httpClient) {
1623
suspend fun initiate(): AuthFlowResponse {
1724
return try {
18-
return apiClient.get(url = "${Config.authBaseUrl}/self-service/login/api").body()
25+
httpClient.get("${Config.authBaseUrl}/self-service/login/api").body()
1926
} catch (e: ClientRequestException) {
2027
throw ApiClientException("Failed to initiate auth", e.response, e)
2128
} catch (e: Exception) {
@@ -25,7 +32,7 @@ class AuthRouter(apiClient: KtorApiClient) : Router(apiClient = apiClient) {
2532

2633
suspend fun refresh(): AuthFlowResponse {
2734
return try {
28-
return apiClient.get(url = "${Config.authBaseUrl}/self-service/login/api?refresh=true").body()
35+
httpClient.get("${Config.authBaseUrl}/self-service/login/api?refresh=true").body()
2936
} catch (e: ClientRequestException) {
3037
throw ApiClientException("Failed to initiate auth", e.response, e)
3138
} catch (e: Exception) {
@@ -35,7 +42,9 @@ class AuthRouter(apiClient: KtorApiClient) : Router(apiClient = apiClient) {
3542

3643
suspend fun complete(flowId: String, payload: LoginPayload): CompleteResponse {
3744
return try {
38-
apiClient.post(url = "${Config.authBaseUrl}/self-service/login?flow=$flowId", body = payload).body()
45+
httpClient.post("${Config.authBaseUrl}/self-service/login?flow=$flowId") {
46+
setBody(Json.encodeToString(payload))
47+
}.body()
3948
} catch (e: ClientRequestException) {
4049
if (e.response.status == HttpStatusCode.BadRequest) {
4150
val bodyAsString: String = e.response.body()
@@ -49,4 +58,20 @@ class AuthRouter(apiClient: KtorApiClient) : Router(apiClient = apiClient) {
4958
throw ApiException("Failed to complete auth", e)
5059
}
5160
}
61+
62+
suspend fun logout(sessionToken: String): Boolean {
63+
return try {
64+
val statusCode = httpClient.delete("${Config.authBaseUrl}/self-service/logout/api") {
65+
setBody(Json.encodeToString(LogoutPayload(
66+
sessionToken = sessionToken
67+
)))
68+
}.status
69+
70+
statusCode == HttpStatusCode.NoContent
71+
} catch (e: ClientRequestException) {
72+
false
73+
} catch (e: Exception) {
74+
throw ApiException("Failed to complete auth", e)
75+
}
76+
}
5277
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package com.ctrlhub.core.auth.payload
22

3+
import kotlinx.serialization.SerialName
34
import kotlinx.serialization.Serializable
45

56
@Serializable
67
data class LoginPayload(
78
val identifier: String,
89
val password: String,
910
val method: String
11+
)
12+
13+
@Serializable
14+
data class LogoutPayload(
15+
@SerialName("session_token") val sessionToken: String
1016
)

src/main/kotlin/com/ctrlhub/core/iam/IamRouter.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
package com.ctrlhub.core.iam
22

3+
import com.ctrlhub.core.Config
34
import com.ctrlhub.core.api.ApiClientException
45
import com.ctrlhub.core.api.ApiException
5-
import com.ctrlhub.core.api.KtorApiClient
66
import com.ctrlhub.core.iam.response.User
77
import com.ctrlhub.core.router.Router
88
import com.github.jasminb.jsonapi.ResourceConverter
9+
import io.ktor.client.HttpClient
910
import io.ktor.client.call.*
1011
import io.ktor.client.plugins.*
12+
import io.ktor.client.request.get
13+
import io.ktor.client.request.header
14+
import io.ktor.http.headers
1115

12-
class IamRouter(apiClient: KtorApiClient) : Router(apiClient) {
16+
class IamRouter(httpClient: HttpClient) : Router(httpClient) {
1317

1418
suspend fun whoami(sessionToken: String): User {
1519
return try {
16-
val rawResponse = apiClient.get("/v3/iam/whoami", mapOf("X-Session-Token" to sessionToken))
20+
val rawResponse = httpClient.get("${Config.apiBaseUrl}/v3/iam/whoami") {
21+
headers {
22+
header("X-Session-Token", sessionToken)
23+
}
24+
}
25+
1726
val resourceConverter = ResourceConverter(User::class.java)
1827
val jsonApiResponse = resourceConverter.readDocument<User>(rawResponse.body<ByteArray>(), User::class.java)
1928

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package com.ctrlhub.core.router
22

3-
import com.ctrlhub.core.api.KtorApiClient
3+
import io.ktor.client.HttpClient
44

5-
abstract class Router(val apiClient: KtorApiClient)
5+
abstract class Router(val httpClient: HttpClient)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.ctrlhub.core
2+
3+
import io.ktor.client.HttpClient
4+
import io.ktor.client.plugins.UserAgent
5+
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
6+
import io.ktor.client.plugins.defaultRequest
7+
import io.ktor.http.HttpHeaders
8+
import io.ktor.serialization.kotlinx.json.json
9+
import io.ktor.util.appendIfNameAbsent
10+
import kotlinx.serialization.json.Json
11+
12+
fun HttpClient.configureForTest(): HttpClient {
13+
return this.config {
14+
defaultRequest {
15+
headers.appendIfNameAbsent(HttpHeaders.ContentType, "application/json")
16+
}
17+
expectSuccess = true
18+
install(ContentNegotiation) {
19+
json(Json { ignoreUnknownKeys = true })
20+
}
21+
install(UserAgent) {
22+
agent = Config.userAgent
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)