Skip to content

Commit

Permalink
Added the first endpoint implementations, added logging dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
CrsiX committed May 4, 2023
1 parent 6680144 commit 55f49bf
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 2 deletions.
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ project(":desktop") {

"implementation"("net.java.dev.jna:jna:5.11.0")
"implementation"("net.java.dev.jna:jna-platform:5.11.0")

// Logging for easier desktop development
"implementation"("ch.qos.logback:logback-classic:1.2.5")
}
}

Expand Down
166 changes: 166 additions & 0 deletions core/src/com/unciv/logic/multiplayer/api/EndpointImplementations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/**
* Collection of endpoint implementations
*
* Those classes are not meant to be used directly. Take a look at the Api class for common usage.
*/

package com.unciv.logic.multiplayer.api

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*

/**
* API wrapper for account handling (do not use directly; use the Api class instead)
*/
class AccountsApi constructor(private val client: HttpClient) {

/**
* Retrieve information about the currently logged in user
*/
suspend fun get(): AccountResponse {
val response = client.get("/api/v2/accounts/me")
if (response.status.equals(200)) {
return response.body()
} else {
val err: ApiErrorResponse = response.body()
throw err
}
}

/**
* Update the currently logged in user information
*
* At least one value must be set to a non-null value.
*/
suspend fun update(username: String?, displayName: String?): Boolean {
return update(UpdateAccountRequest(username, displayName))
}

/**
* Update the currently logged in user information
*
* At least one value must be set to a non-null value.
*/
suspend fun update(r: UpdateAccountRequest): Boolean {
val response = client.put("/api/v2/accounts/me") {
contentType(ContentType.Application.Json)
setBody(r)
}
if (response.status.equals(200)) {
return true
} else {
val err: ApiErrorResponse = response.body()
throw err
}
}

/**
* Deletes the currently logged-in account
*/
suspend fun delete(): Boolean {
val response = client.delete("/api/v2/accounts/me")
if (response.status.equals(200)) {
return true
} else {
val err: ApiErrorResponse = response.body()
throw err
}
}

/**
* Set a new password for the currently logged-in account, provided the old password was accepted as valid
*/
suspend fun setPassword(oldPassword: String, newPassword: String): Boolean {
return setPassword(SetPasswordRequest(oldPassword, newPassword))
}

/**
* Set a new password for the currently logged-in account, provided the old password was accepted as valid
*/
suspend fun setPassword(r: SetPasswordRequest): Boolean {
val response = client.post("/api/v2/accounts/setPassword") {
contentType(ContentType.Application.Json)
setBody(r)
}
if (response.status.equals(200)) {
return true
} else {
val err: ApiErrorResponse = response.body()
throw err
}
}

/**
* Register a new user account
*/
suspend fun register(username: String, displayName: String, password: String): Boolean {
return register(AccountRegistrationRequest(username, displayName, password))
}

/**
* Register a new user account
*/
suspend fun register(r: AccountRegistrationRequest): Boolean {
val response = client.post("/api/v2/accounts/register") {
contentType(ContentType.Application.Json)
setBody(r)
}
if (response.status.equals(200)) {
return true
} else {
val err: ApiErrorResponse = response.body()
throw err
}
}

}

/**
* API wrapper for authentication handling (do not use directly; use the Api class instead)
*/
class AuthApi constructor(private val client: HttpClient) {

/**
* Try logging in with username and password
*
* This method will also implicitly set a cookie in the in-memory cookie storage to authenticate further API calls
*/
suspend fun login(username: String, password: String): Boolean {
return login(LoginRequest(username, password))
}

/**
* Try logging in with username and password
*
* This method will also implicitly set a cookie in the in-memory cookie storage to authenticate further API calls
*/
suspend fun login(r: LoginRequest): Boolean {
val response = client.post("/api/v2/auth/login") {
contentType(ContentType.Application.Json)
setBody(r)
}
return if (response.status.equals(200)) {
true
} else {
response.body()
}
}

/**
* Logs out the currently logged in user
*
* This method will also clear the cookie on success only to avoid further authenticated API calls
*/
suspend fun logout(): Boolean {
val response = client.post("/api/v2/auth/logout")
return if (response.status.equals(200)) {
// TODO: Maybe clear cookie here
true
} else {
response.body()
}
}

}
4 changes: 2 additions & 2 deletions core/src/com/unciv/logic/multiplayer/api/ResponseStructs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ data class AccountResponse(
*/
@Serializable
data class ApiErrorResponse(
val message: String,
override val message: String,
@SerialName("status_code")
// TODO: @JsonValue or something similar, at least in Jackson
val statusCode: ApiStatusCode
)
): Throwable()

/**
* The status code represents a unique identifier for an error. Error codes in the range of 1000..2000 represent client errors that could be handled by the client. Error codes in the range of 2000..3000 represent server errors.
Expand Down

0 comments on commit 55f49bf

Please sign in to comment.