-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(cat-gateway): Add document endpoints (#1470)
* feat(cat-gateway): Add document get endpoint * feat(cat-gateway): Add generic cbor payload type * fix(docs): spelling * fix(cat-gateway): code format * feat(cat-gateway): Add document put endpoint * fix(cat-gateway): fix documentation for the error responses. * feat(general): Bump cat-ci to v3.2.31 to get documentation updates * feat(docs): Add alternative OpenAPI viewers because Elements has issues * feat(cat-gateway): Add document index endpoint (request side only) * feat(cat-gateway): Add response type for document index endpoint * fix(cat-gateway): code format * fix api lint errors * fix(cat-gateway): Response Documentation consistency for document endpoints * feat: increase time schemathesis waits for schema --------- Co-authored-by: kukkok3 <[email protected]>
- Loading branch information
Showing
48 changed files
with
1,891 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
catalyst-gateway/bin/src/service/api/documents/get_document.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
//! Implementation of the GET `/document` endpoint | ||
use poem::Body; | ||
use poem_openapi::ApiResponse; | ||
|
||
use crate::service::common::{responses::WithErrorResponses, types::payload::cbor::Cbor}; | ||
|
||
/// Endpoint responses. | ||
#[derive(ApiResponse)] | ||
#[allow(dead_code)] | ||
pub(crate) enum Responses { | ||
/// ## OK | ||
/// | ||
/// The Document that was requested. | ||
#[oai(status = 200)] | ||
Ok(Cbor<Body>), | ||
/// ## Not Found | ||
/// | ||
/// The document could not be found. | ||
#[oai(status = 404)] | ||
NotFound, | ||
} | ||
|
||
/// All responses. | ||
pub(crate) type AllResponses = WithErrorResponses<Responses>; | ||
|
||
/// # GET `/document` | ||
#[allow(clippy::unused_async, clippy::no_effect_underscore_binding)] | ||
pub(crate) async fn endpoint(document_id: uuid::Uuid, version: Option<uuid::Uuid>) -> AllResponses { | ||
let _doc = document_id; | ||
let _ver = version; | ||
|
||
Responses::NotFound.into() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
//! Signed Documents API endpoints | ||
use anyhow::anyhow; | ||
use poem::{error::ReadBodyError, Body}; | ||
use poem_openapi::{ | ||
param::{Path, Query}, | ||
payload::Json, | ||
OpenApi, | ||
}; | ||
use post_document_index_query::query_filter::DocumentIndexQueryFilterBody; | ||
use put_document::{bad_put_request::PutDocumentBadRequest, MAXIMUM_DOCUMENT_SIZE}; | ||
|
||
use crate::service::{ | ||
common::{ | ||
self, | ||
auth::{none_or_rbac::NoneOrRBAC, rbac::scheme::CatalystRBACSecurityScheme}, | ||
tags::ApiTags, | ||
types::{generic::uuidv7::UUIDv7, payload::cbor::Cbor}, | ||
}, | ||
utilities::middleware::schema_validation::schema_version_validation, | ||
}; | ||
|
||
mod get_document; | ||
mod post_document_index_query; | ||
mod put_document; | ||
|
||
/// Cardano Follower API Endpoints | ||
pub(crate) struct DocumentApi; | ||
|
||
#[OpenApi(tag = "ApiTags::Documents")] | ||
impl DocumentApi { | ||
/// Get A Signed Document. | ||
/// | ||
/// This endpoint returns either a specific or latest version of a registered signed | ||
/// document. | ||
#[oai( | ||
path = "/draft/document/:document_id", | ||
method = "get", | ||
operation_id = "getDocument", | ||
transform = "schema_version_validation" | ||
)] | ||
async fn get_document( | ||
&self, /// UUIDv7 Document ID to retrieve | ||
document_id: Path<UUIDv7>, | ||
/// UUIDv7 Version of the Document to retrieve, if omitted, returns the latest | ||
/// version. | ||
version: Query<Option<UUIDv7>>, | ||
/// No Authorization required, but Token permitted. | ||
_auth: NoneOrRBAC, | ||
) -> get_document::AllResponses { | ||
let Ok(doc_id) = document_id.0.try_into() else { | ||
let err = anyhow!("Invalid UUIDv7"); // Should not happen as UUIDv7 is validating. | ||
return get_document::AllResponses::internal_error(&err); | ||
}; | ||
let Ok(ver_id) = version.0.map(std::convert::TryInto::try_into).transpose() else { | ||
let err = anyhow!("Invalid UUIDv7"); // Should not happen as UUIDv7 is validating. | ||
return get_document::AllResponses::internal_error(&err); | ||
}; | ||
get_document::endpoint(doc_id, ver_id).await | ||
} | ||
|
||
/// Put A Signed Document. | ||
/// | ||
/// This endpoint returns OK if the document is valid, able to be put by the | ||
/// submitter, and if it already exists, is identical to the existing document. | ||
#[oai( | ||
path = "/draft/document", | ||
method = "put", | ||
operation_id = "putDocument", | ||
transform = "schema_version_validation" | ||
)] | ||
async fn put_document( | ||
&self, /// The document to PUT | ||
document: Cbor<Body>, | ||
/// Authorization required. | ||
_auth: CatalystRBACSecurityScheme, | ||
) -> put_document::AllResponses { | ||
match document.0.into_bytes_limit(MAXIMUM_DOCUMENT_SIZE).await { | ||
Ok(document) => put_document::endpoint(document).await, | ||
Err(ReadBodyError::PayloadTooLarge) => put_document::Responses::PayloadTooLarge.into(), | ||
Err(_err) => { | ||
put_document::Responses::BadRequest(Json(PutDocumentBadRequest::new( | ||
"Failed to read document from the request", | ||
))) | ||
.into() | ||
}, | ||
} | ||
} | ||
|
||
/// Post A Signed Document Index Query. | ||
/// | ||
/// This endpoint produces a summary of signed documents that meet the criteria | ||
/// defined in the request body. | ||
/// | ||
/// It does not return the actual documents, just an index of the document identifiers | ||
/// which allows the documents to be retrieved by the `GET document` endpoint. | ||
#[oai( | ||
path = "/draft/document/index", | ||
method = "post", | ||
operation_id = "postDocument", | ||
transform = "schema_version_validation" | ||
)] | ||
async fn post_document( | ||
&self, /// The Query Filter Specification | ||
query: Json<DocumentIndexQueryFilterBody>, | ||
page: Query<Option<common::types::generic::query::pagination::Page>>, | ||
limit: Query<Option<common::types::generic::query::pagination::Limit>>, | ||
/// Authorization required. | ||
_auth: CatalystRBACSecurityScheme, | ||
) -> post_document_index_query::AllResponses { | ||
post_document_index_query::endpoint(query.0 .0, page.0, limit.0).await | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
catalyst-gateway/bin/src/service/api/documents/post_document_index_query/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//! Document Index Query | ||
use poem_openapi::{payload::Json, ApiResponse, Object}; | ||
use query_filter::DocumentIndexQueryFilter; | ||
use response::DocumentIndexListDocumented; | ||
|
||
use super::common; | ||
use crate::service::common::responses::WithErrorResponses; | ||
|
||
pub(crate) mod query_filter; | ||
pub(crate) mod response; | ||
|
||
/// Endpoint responses. | ||
#[derive(ApiResponse)] | ||
#[allow(dead_code)] | ||
pub(crate) enum Responses { | ||
/// ## OK | ||
/// | ||
/// The Index of documents which match the query filter. | ||
#[oai(status = 200)] | ||
Ok(Json<DocumentIndexListDocumented>), | ||
/// ## Not Found | ||
/// | ||
/// No documents were found which match the query filter. | ||
#[oai(status = 404)] | ||
NotFound, | ||
} | ||
|
||
/// All responses. | ||
pub(crate) type AllResponses = WithErrorResponses<Responses>; | ||
|
||
/// Update user schema | ||
#[derive(Debug, Object, Clone, Eq, PartialEq)] | ||
pub(crate) struct QueryDocumentIndex { | ||
/// Name | ||
name: Option<String>, | ||
} | ||
|
||
/// # POST `/document/index` | ||
#[allow(clippy::unused_async, clippy::no_effect_underscore_binding)] | ||
pub(crate) async fn endpoint( | ||
filter: DocumentIndexQueryFilter, | ||
page: Option<common::types::generic::query::pagination::Page>, | ||
limit: Option<common::types::generic::query::pagination::Limit>, | ||
) -> AllResponses { | ||
let _filter = filter; | ||
let _page = page; | ||
let _limit = limit; | ||
|
||
// We return this when the filter results in no documents found. | ||
Responses::NotFound.into() | ||
} |
Oops, something went wrong.