Skip to content

Commit

Permalink
feat: OpenAPI docs (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
darioAnongba authored Jul 8, 2024
1 parent 286a77c commit 9e09d2c
Show file tree
Hide file tree
Showing 55 changed files with 2,024 additions and 836 deletions.
40 changes: 40 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ humantime = "2.1.0"
rust_socketio = { version = "0.6.0", features = ["async"] }
bcrypt = "0.15.1"
migration = { path = "migration" }
utoipa = { version = "4.2.3", features = ["axum_extras", "chrono", "uuid"] }
utoipa-scalar = { version = "0.1.0", features = ["axum"] }

[build-dependencies]
tonic-build = "0.11.0"
Expand Down
2 changes: 1 addition & 1 deletion config/development.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
domain: "swissknife"
domain: "numeraire.tech"
ln_provider: breez
auth_provider: bypass

Expand Down
3 changes: 1 addition & 2 deletions migration/src/m20240420_194334_ln_address_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ impl MigrationTrait for Migration {
username varchar(255) unique NOT NULL,
active boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT current_timestamp,
updated_at timestamptz,
deleted_at timestamptz
updated_at timestamptz
);
CREATE TRIGGER update_timestamp BEFORE
UPDATE ON ln_address FOR EACH ROW EXECUTE PROCEDURE update_timestamp();",
Expand Down
4 changes: 2 additions & 2 deletions migration/src/m20240420_195225_invoice_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl MigrationTrait for Migration {
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id varchar(255) NOT NULL,
payment_hash varchar(255),
ln_address uuid,
ln_address_id uuid,
bolt11 varchar,
ledger varchar(255) NOT NULL,
currency varchar(255) NOT NULL,
Expand All @@ -35,7 +35,7 @@ impl MigrationTrait for Migration {
created_at timestamptz NOT NULL DEFAULT current_timestamp,
updated_at timestamptz,
expires_at timestamptz,
CONSTRAINT fk_ln_address FOREIGN KEY (ln_address)
CONSTRAINT fk_ln_address FOREIGN KEY (ln_address_id)
REFERENCES ln_address (id)
ON DELETE SET NULL
);
Expand Down
3 changes: 3 additions & 0 deletions src/application/docs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod openapi;

pub use openapi::*;
105 changes: 105 additions & 0 deletions src/application/docs/openapi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use crate::{
application::{
dtos::ErrorResponse,
entities::{Currency, Ledger, OrderDirection},
},
domains::{
invoices::api::InvoiceHandler,
lightning::api::{BreezNodeHandler, LnAddressHandler, LnURLpHandler},
payments::api::PaymentHandler,
system::api::SystemHandler,
users::api::AuthHandler,
wallet::api::WalletHandler,
},
};
use utoipa::{
openapi::{
security::{Http, HttpAuthScheme, SecurityScheme},
Components, OpenApi,
},
Modify, OpenApi as OpenApiDoc,
};

#[derive(OpenApiDoc)]
#[openapi(
info(
title = "Numeraire SwissKnife REST API",
description = "This API is available to anyone with a Numeraire account. The `Wallet` endpoints are the main access point for most users.",
),
components(schemas(OrderDirection, Ledger, Currency), responses(ErrorResponse)),
modifiers(&SecurityAddon),
)]
struct ApiDoc;

pub fn merged_openapi() -> OpenApi {
let mut openapi = ApiDoc::openapi();
openapi.merge(AuthHandler::openapi());
openapi.merge(WalletHandler::openapi());
openapi.merge(InvoiceHandler::openapi());
openapi.merge(PaymentHandler::openapi());
openapi.merge(LnAddressHandler::openapi());
openapi.merge(LnURLpHandler::openapi());
openapi.merge(BreezNodeHandler::openapi());
openapi.merge(SystemHandler::openapi());
openapi
}

pub const BAD_REQUEST_EXAMPLE: &str = r#"
{
"status": "400 Bad Request",
"reason": "Missing required parameter in request"
}
"#;

pub const UNAUTHORIZED_EXAMPLE: &str = r#"
{
"status": "401 Unauthorized",
"reason": "Invalid credentials"
}
"#;

pub const FORBIDDEN_EXAMPLE: &str = r#"
{
"status": "403 Forbidden",
"reason": "Missing permissions"
}
"#;

pub const NOT_FOUND_EXAMPLE: &str = r#"
{
"status": "404 Not Found",
"reason": "Resouce not found"
}
"#;

pub const UNSUPPORTED_EXAMPLE: &str = r#"
{
"status": "405 Method Not Allowed",
"reason": "Sign in not allowed (not needed) for oauth2 provider"
}
"#;

pub const UNPROCESSABLE_EXAMPLE: &str = r#"
{
"status": "422 Unprocessable Entity",
"reason": "Validation failed: ..."
}
"#;

pub const INTERNAL_EXAMPLE: &str = r#"
{
"status": "500 Internal Server Error",
"reason": "Internal server error, Please contact your administrator or try later"
}
"#;

struct SecurityAddon;
impl Modify for SecurityAddon {
fn modify(&self, openapi: &mut OpenApi) {
let components: &mut Components = openapi.components.as_mut().unwrap(); // we can unwrap safely since there already is components registered.
components.add_security_scheme(
"jwt",
SecurityScheme::Http(Http::new(HttpAuthScheme::Bearer)),
);
}
}
18 changes: 18 additions & 0 deletions src/application/dtos/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

/// Sign In Request
#[derive(Debug, Deserialize, ToSchema)]
pub struct SignInRequest {
/// User password
#[schema(example = "password_from_config_file")]
pub password: String,
}

/// Sign In Response
#[derive(Debug, Serialize, ToSchema)]
pub struct SignInResponse {
/// JWT token
#[schema(example = "eyJ0eXAiOiJKV1QiLCJhbGciOiJ...")]
pub token: String,
}
14 changes: 14 additions & 0 deletions src/application/dtos/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use serde::Serialize;
use utoipa::{ToResponse, ToSchema};

/// Application Error Response
#[derive(Serialize, ToResponse, ToSchema)]
pub struct ErrorResponse {
/// Error status
#[schema(example = "401 Unauthorized")]
pub status: String,

/// Error reason
#[schema(example = "error message")]
pub reason: String,
}
15 changes: 15 additions & 0 deletions src/application/dtos/invoices.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use serde::Deserialize;
use utoipa::ToSchema;

/// New Invoice Request
#[derive(Debug, Deserialize, ToSchema)]
pub struct NewInvoiceRequest {
/// User ID. Will be populated with your own ID by default
pub user_id: Option<String>,
/// Amount in millisatoshis
pub amount_msat: u64,
/// Description of the invoice. Visible by the payer
pub description: Option<String>,
/// Expiration time in seconds
pub expiry: Option<u32>,
}
75 changes: 45 additions & 30 deletions src/application/dtos/lightning.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,69 @@
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

#[derive(Debug, Deserialize)]
pub struct NewInvoiceRequest {
pub user_id: Option<String>,
pub amount_msat: u64,
pub description: Option<String>,
pub expiry: Option<u32>,
}

#[derive(Debug, Deserialize)]
pub struct SendPaymentRequest {
pub user_id: Option<String>,
pub input: String,
pub amount_msat: Option<u64>,
pub comment: Option<String>,
}
#[derive(Debug, Deserialize, ToSchema)]
pub struct RedeemOnchainRequest {
/// Recipient BTC address
pub to_address: String,

// Part of the lightning types because this is the payload to send from the node with a swap service
#[derive(Debug, Deserialize)]
pub struct SendOnchainPaymentRequest {
pub amount_msat: u64,
pub recipient_address: String,
/// Fee rate in sats/vb
#[schema(example = "8")]
pub feerate: u32,
}

#[derive(Debug, Deserialize)]
pub struct RedeemOnchainRequest {
pub to_address: String,
pub feerate: u32,
#[derive(Debug, Serialize, ToSchema)]
pub struct RedeemOnchainResponse {
/// Transaction ID
#[schema(example = "ceb662f7e470e6...")]
pub txid: String,
}

#[derive(Debug, Deserialize)]
pub struct RegisterLightningAddressRequest {
#[derive(Debug, Deserialize, ToSchema)]
pub struct RegisterLnAddressRequest {
/// User ID. Will be populated with your own ID by default
pub user_id: Option<String>,
/// Username such as `username@domain`
pub username: String,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct ConnectLSPRequest {
/// LSP ID
#[schema(example = "3e8822d5-00de-4fa3-a30e-c2d31f5454e8")]
pub lsp_id: String,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct SignMessageRequest {
/// Message
#[schema(example = "my message...")]
pub message: String,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, Serialize, ToSchema)]
pub struct SignMessageResponse {
/// zbase encoded signature
#[schema(example = "d7norubk1xweo96ompcgqg4g4gyy...")]
pub signature: String,
}

#[derive(Debug, Deserialize, ToSchema)]
pub struct CheckMessageRequest {
/// Original message
#[schema(example = "my message...")]
pub message: String,

/// zbase encoded signature
#[schema(example = "d7norubk1xweo96ompcgqg4g4gyy...")]
pub signature: String,

/// Node public key
#[schema(example = "021e15c10d72f86a79323d1e3a42...")]
pub pubkey: String,
}

#[derive(Debug, Serialize, ToSchema)]
pub struct CheckMessageResponse {
/// Signature validity
pub is_valid: bool,
}
5 changes: 4 additions & 1 deletion src/application/dtos/lnurl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use serde::Deserialize;
use utoipa::IntoParams;

#[derive(Deserialize)]
#[derive(Debug, Deserialize, IntoParams)]
pub struct LNUrlpInvoiceQueryParams {
/// Amount in millisatoshis
pub amount: u64,
/// Optional comment for the recipient
pub comment: Option<String>,
}
10 changes: 8 additions & 2 deletions src/application/dtos/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
mod auth;
mod config;
mod error;
mod invoices;
mod lightning;
mod lnurl;
mod user;
mod payments;

pub use auth::*;
pub use config::*;
pub use error::*;
pub use invoices::*;
pub use lightning::*;
pub use lnurl::*;
pub use user::*;
pub use payments::*;
Loading

0 comments on commit 9e09d2c

Please sign in to comment.