-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ANCHOR-295] Implement Kotlin reference server #1060
Changes from 19 commits
b8ba116
160e335
bcd19ae
210a319
9c85f05
2ddaaf4
8fac62f
1d44fee
274d948
30997dc
970340c
0a7e6ce
1c9e308
561d6c8
57389ef
2d6db06
cdb1ea9
02a4138
d165937
b2a628e
d4bbaff
e55133d
0141c1a
f48d2cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.stellar.anchor.api.callback; | ||
|
||
import com.google.gson.annotations.SerializedName; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
|
||
@Data | ||
@Builder | ||
@AllArgsConstructor | ||
public class GetUniqueAddressRequest { | ||
@SerializedName("transaction_id") | ||
String transactionId; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package org.stellar.reference.callbacks | ||
|
||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.Transient | ||
|
||
@Serializable | ||
class BadRequestException(val error: String, @Transient override val cause: Throwable? = null) : | ||
RuntimeException(error, cause) | ||
|
||
@Serializable | ||
class NotFoundException( | ||
val error: String, | ||
val id: String, | ||
@Transient override val cause: Throwable? = null | ||
) : RuntimeException(error, cause) | ||
|
||
@Serializable | ||
class UnprocessableEntityException( | ||
val error: String, | ||
val id: String, | ||
@Transient override val cause: Throwable? = null | ||
) : RuntimeException(error, cause) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package org.stellar.reference.callbacks.customer | ||
|
||
import io.ktor.http.* | ||
import io.ktor.server.application.* | ||
import io.ktor.server.auth.* | ||
import io.ktor.server.request.* | ||
import io.ktor.server.response.* | ||
import io.ktor.server.routing.* | ||
import org.stellar.anchor.api.callback.GetCustomerRequest | ||
import org.stellar.anchor.api.callback.PutCustomerRequest | ||
import org.stellar.anchor.util.GsonUtils | ||
import org.stellar.reference.callbacks.BadRequestException | ||
import org.stellar.reference.callbacks.NotFoundException | ||
import org.stellar.reference.log | ||
import org.stellar.reference.plugins.AUTH_CONFIG_ENDPOINT | ||
|
||
/** | ||
* Defines the routes related to the customer callback API. See | ||
* [Customer Callbacks](https://developers.stellar.org/api/anchor-platform/callbacks/customer/). | ||
* | ||
* @param customerService the [CustomerService] to use to process the requests. | ||
*/ | ||
fun Route.customer(customerService: CustomerService) { | ||
authenticate(AUTH_CONFIG_ENDPOINT) { | ||
route("/customer") { | ||
get { | ||
val request = | ||
GetCustomerRequest.builder() | ||
.id(call.parameters["id"]) | ||
.account(call.parameters["account"]) | ||
.memo(call.parameters["memo"]) | ||
.memoType(call.parameters["memo_type"]) | ||
.type(call.parameters["type"]) | ||
.lang(call.parameters["lang"]) | ||
.build() | ||
try { | ||
val response = GsonUtils.getInstance().toJson(customerService.getCustomer(request)) | ||
call.respond(response) | ||
} catch (e: BadRequestException) { | ||
call.respond(HttpStatusCode.BadRequest, e) | ||
} catch (e: NotFoundException) { | ||
call.respond(HttpStatusCode.NotFound, e) | ||
} catch (e: Exception) { | ||
log.error("Unexpected exception", e) | ||
call.respond(HttpStatusCode.InternalServerError) | ||
} | ||
} | ||
put { | ||
val request = | ||
GsonUtils.getInstance().fromJson(call.receive<String>(), PutCustomerRequest::class.java) | ||
try { | ||
val response = GsonUtils.getInstance().toJson(customerService.upsertCustomer(request)) | ||
call.respond(response) | ||
} catch (e: BadRequestException) { | ||
call.respond(HttpStatusCode.BadRequest, e) | ||
} catch (e: Exception) { | ||
call.respond(HttpStatusCode.InternalServerError) | ||
} | ||
} | ||
delete("{id}") { | ||
val id = call.parameters["id"]!! | ||
try { | ||
customerService.deleteCustomer(id) | ||
call.respond(HttpStatusCode.NoContent) | ||
} catch (e: NotFoundException) { | ||
call.respond(HttpStatusCode.NotFound, e) | ||
} catch (e: Exception) { | ||
call.respond(HttpStatusCode.InternalServerError) | ||
} | ||
} | ||
} | ||
route("/invalidate_clabe") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a config flag that marks it's only for test. You can do |
||
get("{id}") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❓ I'm assuming this is used to setup an integration test? Any chance we can make the endpoint available only when deployed in that context? We could do this later when we add a persistent deployment too, so I'll leave it to you. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I put a comment in the code to consider enabling this endpoint only when testing. |
||
val id = call.parameters["id"]!! | ||
try { | ||
customerService.invalidateClabe(id) | ||
call.respond(HttpStatusCode.OK) | ||
} catch (e: NotFoundException) { | ||
call.respond(HttpStatusCode.NotFound, e) | ||
} catch (e: Exception) { | ||
call.respond(HttpStatusCode.InternalServerError) | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we create a helper function for try/catch errors -> respond with status code?