Skip to content

Commit

Permalink
Fix Kotlin AuthAPI
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-quiltt committed Feb 19, 2024
1 parent 893b82f commit e2647a6
Showing 1 changed file with 91 additions and 55 deletions.
146 changes: 91 additions & 55 deletions connector/src/main/java/app/quiltt/connector/QuilttAuthApi.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
package app.quiltt.connector

import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL


data class EmailInput(val email: String)
data class PhoneInput(val phone: String)

sealed class UsernamePayload {
data class Email(val email: String) : UsernamePayload()
data class Phone(val phone: String) : UsernamePayload()
Expand All @@ -20,11 +13,29 @@ sealed class UsernamePayload {
data class PasscodePayload(val usernamePayload: UsernamePayload, val passcode: String)

data class SessionData(val token: String)
data class UnauthorizedData(val message: String, val instruction: String)
data class UnprocessableData(val attribute: Map<String, String>)

sealed class AuthResponse {
data class SessionResponse(val status: Int, val data: SessionData) : AuthResponse()
data class UnprocessableResponse(val status: Int, val data: UnprocessableData) : AuthResponse()
sealed class PingResponse {
data class SessionResponse(val status: Int, val data: SessionData) : PingResponse()
data class UnprocessableResponse(val status: Int, val data: UnprocessableData) : PingResponse()
}

sealed class IdentifyResponse {
data class SessionResponse(val status: Int, val data: SessionData) : IdentifyResponse()
data class AcceptedResponse(val status: Int) : IdentifyResponse()
data class UnprocessableResponse(val status: Int, val data: UnprocessableData) : IdentifyResponse()
}

sealed class AuthenticateResponse {
data class SessionResponse(val status: Int, val data: SessionData) : AuthenticateResponse()
data class UnauthorizedResponse(val status: Int, val data: UnauthorizedData) : AuthenticateResponse()
data class UnprocessableResponse(val status: Int, val data: UnprocessableData) : AuthenticateResponse()
}

sealed class RevokeResponse {
data class NoContentResponse(val status: Int) : RevokeResponse()
data class UnauthorizedResponse(val status: Int, val data: UnauthorizedData) : RevokeResponse()
}

class QuilttAuthApi(private val clientId: String?) {
Expand All @@ -35,7 +46,7 @@ class QuilttAuthApi(private val clientId: String?) {
* - 200: OK -> Session is Valid
* - 401: Unauthorized -> Session is Invalid
*/
fun ping(token: String): AuthResponse {
fun ping(token: String): PingResponse {
val url = URL(endpointAuth)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
Expand All @@ -45,53 +56,53 @@ class QuilttAuthApi(private val clientId: String?) {
val statusCode = connection.responseCode

if (statusCode == 200) {
return AuthResponse.SessionResponse(statusCode, SessionData(token))
return PingResponse.SessionResponse(statusCode, SessionData(token))
}
val inputStream = connection.errorStream
val errorData = errorMap(inputStream)
return AuthResponse.UnprocessableResponse(statusCode, errorData)
return PingResponse.UnprocessableResponse(statusCode, errorData)
}

private fun errorMap(inputStream: InputStream): UnprocessableData {
println("errorMap inputStream: $inputStream")
val jsonObject = JSONObject(inputStream.bufferedReader().use { it.readText() })
println("errorMap jsonObject: $jsonObject")
val errorMap = mutableMapOf<String, String>()
val keys = jsonObject.keys()
while (keys.hasNext()) {
val key = keys.next()
val value = jsonObject.getString(key)
errorMap[key] = value
}
return UnprocessableData(errorMap)
}

fun identify(payload: UsernamePayload): SessionData {
/**
* Response Statuses:
* - 201: Created -> Profile Created, New Session Returned
* - 202: Accepted -> Profile Found, MFA Code Sent for `authenticate`
* - 422: Unprocessable Entity -> Invalid Payload
*/
fun identify(payload: UsernamePayload): IdentifyResponse {
val url = URL(endpointAuth)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/json; utf-8")
connection.doInput = true
connection.doOutput = true

val jsonPayload = JSONObject()
jsonPayload.put("clientId", clientId)
jsonPayload.put("payload", payload)

val writer = OutputStreamWriter(connection.outputStream)
writer.write(jsonPayload.toString())
writer.flush()
writer.close()

val reader = BufferedReader(InputStreamReader(connection.inputStream))
val response = reader.readLine()
reader.close()
when (payload) {
is UsernamePayload.Email -> jsonPayload.put("email", payload.email)
is UsernamePayload.Phone -> jsonPayload.put("phone", payload.phone)
}

val jsonObject = JSONObject(response)
return SessionData(jsonObject.getString("token"))
if (connection.responseCode == 201) {
val inputStream = connection.inputStream
val jsonObject = JSONObject(inputStream.bufferedReader().use { it.readText() })
return IdentifyResponse.SessionResponse(connection.responseCode, SessionData(jsonObject.getString("token")))
}
if (connection.responseCode == 202) {
return IdentifyResponse.AcceptedResponse(connection.responseCode)
}
val inputStream = connection.errorStream
val errorData = errorMap(inputStream)
return IdentifyResponse.UnprocessableResponse(connection.responseCode, errorData)
}

fun authenticate(payload: PasscodePayload): SessionData {
/**
* Response Statuses:
* - 201: Created -> MFA Validated, New Session Returned
* - 401: Unauthorized -> MFA Invalid
* - 422: Unprocessable Entity -> Invalid Payload
*/
fun authenticate(payload: PasscodePayload): AuthenticateResponse {
val url = URL(endpointAuth)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "PUT"
Expand All @@ -102,25 +113,50 @@ class QuilttAuthApi(private val clientId: String?) {
jsonPayload.put("clientId", clientId)
jsonPayload.put("payload", payload)

val writer = OutputStreamWriter(connection.outputStream)
writer.write(jsonPayload.toString())
writer.flush()
writer.close()

val reader = BufferedReader(InputStreamReader(connection.inputStream))
val response = reader.readLine()
reader.close()

val jsonObject = JSONObject(response)
return SessionData(jsonObject.getString("token"))
if (connection.responseCode == 201) {
val inputStream = connection.inputStream
val jsonObject = JSONObject(inputStream.bufferedReader().use { it.readText() })
return AuthenticateResponse.SessionResponse(connection.responseCode, SessionData(jsonObject.getString("token")))
}
if (connection.responseCode == 401) {
val inputStream = connection.errorStream
val errorData = errorMap(inputStream) as UnauthorizedData
return AuthenticateResponse.UnauthorizedResponse(connection.responseCode, errorData)
}
val inputStream = connection.errorStream
val errorData = errorMap(inputStream)
return AuthenticateResponse.UnprocessableResponse(connection.responseCode, errorData)
}

fun revoke(token: String) {
/**
* Response Statuses:
* - 204: No Content -> Session Revoked
* - 401: Unauthorized -> Session Not Found
*/
fun revoke(token: String): RevokeResponse {
val url = URL(endpointAuth)
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "DELETE"
connection.setRequestProperty("Authorization", "Bearer $token")
connection.responseCode
println("Revoke response code: ${connection.responseCode}")

if (connection.responseCode == 204) {
return RevokeResponse.NoContentResponse(connection.responseCode)
}
val inputStream = connection.errorStream
val errorData = errorMap(inputStream) as UnauthorizedData
return RevokeResponse.UnauthorizedResponse(connection.responseCode, errorData)
}

private fun errorMap(inputStream: InputStream): UnprocessableData {
val jsonObject = JSONObject(inputStream.bufferedReader().use { it.readText() })
val errorMap = mutableMapOf<String, String>()
val keys = jsonObject.keys()
while (keys.hasNext()) {
val key = keys.next()
val value = jsonObject.getString(key)
errorMap[key] = value
}
return UnprocessableData(errorMap)
}
}

0 comments on commit e2647a6

Please sign in to comment.