Skip to content

Commit

Permalink
Merge pull request #8 from Liftric/refactoring/suspend-result
Browse files Browse the repository at this point in the history
Refactoring: using suspend and Result<T> properly
  • Loading branch information
benjohnde authored Aug 24, 2020
2 parents 4a25b86 + c3c7736 commit 4039883
Show file tree
Hide file tree
Showing 12 changed files with 260 additions and 236 deletions.
2 changes: 1 addition & 1 deletion auth/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import java.util.Date
import com.jfrog.bintray.gradle.tasks.BintrayUploadTask
import java.util.*

plugins {
id("com.android.library")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.liftric.base

actual class Environment {
actual internal class Environment {
actual companion object {
actual fun variable(value: String): String? {
return System.getenv(value)
Expand Down
14 changes: 7 additions & 7 deletions auth/src/commonMain/kotlin/com/liftric/Auth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,29 @@ interface Auth {
* @param attributes
* @param response Callback with error if something went wrong or an object on success
*/
suspend fun signUp(username: String, password: String, attributes: List<UserAttribute>? = null, response: (error: Error?, value: SignUpResponse?) -> Unit)
suspend fun signUp(username: String, password: String, attributes: List<UserAttribute>? = null): Result<SignUpResponse>

/**
* Signs in the user with the given parameters
* @param username The username
* @param password The password
* @param response Callback with error if something went wrong or an object on success
*/
suspend fun signIn(username: String, password: String, response: (error: Error?, value: SignInResponse?) -> Unit)
suspend fun signIn(username: String, password: String): Result<SignInResponse>

/**
* Signs out the user globally
* @param accessToken The access token from the sign in request
* @param response Callback with error if something went wrong
*/
suspend fun signOut(accessToken: String, response: (error: Error?) -> Unit)
suspend fun signOut(accessToken: String): Result<Unit>

/**
* Fetches the user object
* @param accessToken The access token from the sign in request
* @param response Callback with error if something went wrong or an object on success
*/
suspend fun getUser(accessToken: String, response: (error: Error?, value: GetUserResponse?) -> Unit)
suspend fun getUser(accessToken: String): Result<GetUserResponse>

/**
* Updates the users attributes
Expand All @@ -41,7 +41,7 @@ interface Auth {
* @param attributes List of attributes that should be updated
* @param response Callback with error if something went wrong or an object on success
*/
suspend fun updateUserAttributes(accessToken: String, attributes: List<UserAttribute>, response: (error: Error?, value: UpdateUserAttributesResponse?) -> Unit)
suspend fun updateUserAttributes(accessToken: String, attributes: List<UserAttribute>): Result<UpdateUserAttributesResponse>

/**
* Changes the password of the current user
Expand All @@ -50,12 +50,12 @@ interface Auth {
* @param newPassword The new password
* @param response Callback with request response error
*/
suspend fun changePassword(accessToken: String, currentPassword: String, newPassword: String, response: (error: Error?) -> Unit)
suspend fun changePassword(accessToken: String, currentPassword: String, newPassword: String): Result<Unit>

/**
* Deletes the users account
* @param accessToken The access token from the sign in request
* @param response Callback with error if something went wrong
*/
suspend fun deleteUser(accessToken: String, response: (error: Error?) -> Unit)
suspend fun deleteUser(accessToken: String): Result<Unit>
}
163 changes: 91 additions & 72 deletions auth/src/commonMain/kotlin/com/liftric/AuthHandler.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.liftric

import com.liftric.base.*
import io.ktor.client.HttpClient
import io.ktor.client.features.defaultRequest
import io.ktor.client.request.header
import io.ktor.client.request.post
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.readBytes
import io.ktor.http.ContentType
import io.ktor.http.contentType
import io.ktor.utils.io.core.String
import kotlinx.coroutines.*
import io.ktor.client.*
import io.ktor.client.features.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.utils.io.core.*
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.serializer

/**
* Authentifaction handler for AWS Cognito
Expand All @@ -36,10 +36,9 @@ open class AuthHandler(private val configuration: Configuration) : Auth {
override suspend fun signUp(
username: String,
password: String,
attributes: List<UserAttribute>?,
response: (error: Error?, value: SignUpResponse?) -> Unit
) {
request(
attributes: List<UserAttribute>?
): Result<SignUpResponse> {
val response = request(
RequestType.signUp,
serialize(
SignUp.serializer(),
Expand All @@ -50,17 +49,23 @@ open class AuthHandler(private val configuration: Configuration) : Auth {
UserAttributes = attributes ?: listOf()
)
)
) { error, value ->
response(error, value?.let { parse(SignUpResponse.serializer(), it) })
)
return if (response.isSuccess) {
try {
Result.success(parse(SignUpResponse.serializer(), response.getOrNull()!!))
} catch (e: SerializationException) {
Result.failure(e)
}
} else {
Result.failure(response.exceptionOrNull()!!)
}
}

override suspend fun signIn(
username: String,
password: String,
response: (error: Error?, value: SignInResponse?) -> Unit
) {
request(
password: String
): Result<SignInResponse> {
val response = request(
RequestType.signIn,
serialize(
Authentication.serializer(),
Expand All @@ -70,79 +75,80 @@ open class AuthHandler(private val configuration: Configuration) : Auth {
AuthParameters(username, password)
)
)
) { error, value ->
response(error, value?.let { parse(SignInResponse.serializer(), it) })
)
return if (response.isSuccess) {
try {
Result.success(parse(SignInResponse.serializer(), response.getOrNull()!!))
} catch (e: SerializationException) {
Result.failure(e)
}
} else {
Result.failure(response.exceptionOrNull()!!)
}
}

override suspend fun deleteUser(
accessToken: String,
response: (error: Error?) -> Unit
) {
request(
RequestType.deleteUser,
override suspend fun signOut(accessToken: String): Result<Unit> {
val response = request(
RequestType.signOut,
serialize(
AccessToken.serializer(),
AccessToken(accessToken)
)
) { error, _ ->
response(error)
)
return if (response.isSuccess) {
Result.success(Unit)
} else {
Result.failure(response.exceptionOrNull()!!)
}
}

override suspend fun getUser(
accessToken: String,
response: (error: Error?, value: GetUserResponse?) -> Unit
) {
request(
override suspend fun getUser(accessToken: String): Result<GetUserResponse> {
val response = request(
RequestType.getUser,
serialize(
AccessToken.serializer(),
AccessToken(accessToken)
)
) { error, value ->
response(error, value?.let { parse(GetUserResponse.serializer(), it) })
}
}

override suspend fun signOut(
accessToken: String,
response: (error: Error?) -> Unit
) {
request(
RequestType.signOut,
serialize(
AccessToken.serializer(),
AccessToken(accessToken)
)
) { error, _ ->
response(error)
)
return if (response.isSuccess) {
try {
Result.success(parse(GetUserResponse.serializer(), response.getOrNull()!!))
} catch (e: SerializationException) {
Result.failure(e)
}
} else {
Result.failure(response.exceptionOrNull()!!)
}
}

override suspend fun updateUserAttributes(
accessToken: String,
attributes: List<UserAttribute>,
response: (error: Error?, value: UpdateUserAttributesResponse?) -> Unit
) {
request(
attributes: List<UserAttribute>
): Result<UpdateUserAttributesResponse> {
val response = request(
RequestType.updateUserAttributes,
serialize(
UpdateUserAttributes.serializer(),
UpdateUserAttributes(accessToken, attributes)
)
) { error, value ->
response(error, value?.let { parse(UpdateUserAttributesResponse.serializer(), it) })
)
return if (response.isSuccess) {
try {
Result.success(parse(UpdateUserAttributesResponse.serializer(), response.getOrNull()!!))
} catch (e: SerializationException) {
Result.failure(e)
}
} else {
Result.failure(response.exceptionOrNull()!!)
}
}

override suspend fun changePassword(
accessToken: String,
currentPassword: String,
newPassword: String,
response: (error: Error?) -> Unit
) {
request(
newPassword: String
): Result<Unit> {
val response = request(
RequestType.changePassword,
serialize(
ChangePassword.serializer(),
Expand All @@ -153,20 +159,34 @@ open class AuthHandler(private val configuration: Configuration) : Auth {
newPassword
)
)
) { error, _ ->
response(error)
)
return if (response.isSuccess) {
Result.success(Unit)
} else {
Result.failure(response.exceptionOrNull()!!)
}
}

override suspend fun deleteUser(accessToken: String): Result<Unit> {
val response = request(
RequestType.deleteUser,
serialize(
AccessToken.serializer(),
AccessToken(accessToken)
)
)
return if (response.isSuccess) {
Result.success(Unit)
} else {
Result.failure(response.exceptionOrNull()!!)
}
}

//----------
// REQUEST
//----------

private suspend fun request(
type: RequestType,
payload: String,
completion: (error: Error?, value: String?) -> Unit
) {
private suspend fun request(type: RequestType, payload: String): Result<String> {
val response = client.post<HttpResponse>(configuration.requestUrl) {
header(
Header.AmzTarget,
Expand All @@ -185,12 +205,11 @@ open class AuthHandler(private val configuration: Configuration) : Auth {
)
body = payload
}

return if (response.status.value == 200) {
completion(null, String(response.readBytes()))
Result.success(String(response.readBytes()))
} else {
val error = parse(RequestError.serializer(), String(response.readBytes()))
completion(Error(error.message), null)
Result.failure(Error(error.message))
}
}
}
2 changes: 1 addition & 1 deletion auth/src/commonMain/kotlin/com/liftric/base/Environment.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.liftric.base

expect class Environment() {
expect internal class Environment() {
companion object {
/**
* Accesses environment variable
Expand Down
12 changes: 6 additions & 6 deletions auth/src/commonMain/kotlin/com/liftric/base/Payload.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,32 @@ package com.liftric.base
import kotlinx.serialization.Serializable

@Serializable
data class Authentication(
internal data class Authentication(
val AuthFlow: String,
val ClientId: String,
val AuthParameters: AuthParameters
)

@Serializable
data class AuthParameters(
internal data class AuthParameters(
val USERNAME: String,
val PASSWORD: String
)

@Serializable
data class AccessToken(
internal data class AccessToken(
val AccessToken: String
)

@Serializable
data class ChangePassword(
internal data class ChangePassword(
val AccessToken: String,
val PreviousPassword: String,
val ProposedPassword: String
)

@Serializable
data class SignUp(
internal data class SignUp(
val ClientId: String,
val Password: String,
val Username: String,
Expand All @@ -42,7 +42,7 @@ data class UserAttribute(
)

@Serializable
data class UpdateUserAttributes(
internal data class UpdateUserAttributes(
val AccessToken: String,
val UserAttributes: List<UserAttribute>
)
3 changes: 2 additions & 1 deletion auth/src/commonMain/kotlin/com/liftric/base/Response.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ data class AuthenticationResult(
val RefreshToken: String = "",
val TokenType: String = ""
)

// Sign up

@Serializable
Expand Down Expand Up @@ -61,4 +62,4 @@ data class MFAOptions(
@Serializable
data class UpdateUserAttributesResponse(
val CodeDeliveryDetailsList: List<CodeDeliveryDetails> = listOf()
)
)
Loading

0 comments on commit 4039883

Please sign in to comment.