Skip to content

Commit

Permalink
feat: migrate to utoipa stable, add manual schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-mader committed Dec 3, 2024
1 parent 91fd64e commit 93084d4
Show file tree
Hide file tree
Showing 16 changed files with 319 additions and 114 deletions.
12 changes: 6 additions & 6 deletions Cargo.lock

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

12 changes: 8 additions & 4 deletions agent_api_rest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ tower-http.workspace = true
tracing.workspace = true
url.workspace = true
uuid.workspace = true
utoipa = { version = "=5.0.0-beta.0", features = ["axum_extras", "yaml"] }
utoipa-scalar = { version = "=0.2.0-beta.0", features = ["axum"] }
utoipa = { version = "5.2", features = ["axum_extras", "yaml"] }
utoipa-scalar = { version = "0.2", features = ["axum"] }
# TODO: wait for new release that contains PR juhaku/utoipa#1002 (current version `=5.0.0-alpha.1`)
# utoipa = { git = "https://github.com/juhaku/utoipa.git", rev = "f2a7143", features = [
# "axum_extras",
Expand All @@ -44,11 +44,15 @@ utoipa-scalar = { version = "=0.2.0-beta.0", features = ["axum"] }
# ] }

[dev-dependencies]
agent_event_publisher_http = { path = "../agent_event_publisher_http", features = ["test_utils"] }
agent_event_publisher_http = { path = "../agent_event_publisher_http", features = [
"test_utils",
] }
agent_holder = { path = "../agent_holder", features = ["test_utils"] }
agent_identity = { path = "../agent_identity", features = ["test_utils"] }
agent_issuance = { path = "../agent_issuance", features = ["test_utils"] }
agent_secret_manager = { path = "../agent_secret_manager", features = ["test_utils"] }
agent_secret_manager = { path = "../agent_secret_manager", features = [
"test_utils",
] }
agent_shared = { path = "../agent_shared", features = ["test_utils"] }
agent_store = { path = "../agent_store" }
agent_verification = { path = "../agent_verification", features = [
Expand Down
4 changes: 4 additions & 0 deletions agent_api_rest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ The current version of the REST API is `v0`.
> [!NOTE]
> UniCore uses [Scalar](https://scalar.com) to make its OpenAPI specification interactive. It is served under `/<BASE_PATH>/<API_VERSION>/api-reference` (for example: `/v0/api-reference`). The `openapi.yaml` file can be downloaded there as well. The latest version of the `openapi.yaml` file is also deployed as part of the documentation at https://docs.impierce.com/unicore/api-reference.
#### Generate OpenAPI specification

The `openapi.yaml` file can be generated manually by executing the test `generate_openapi_file()` _(ignored in a regular test run)_.

#### Swagger UI

You can also run a local Swagger UI container to inspect the OpenAPI specification.
Expand Down
151 changes: 120 additions & 31 deletions agent_api_rest/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,8 @@ paths:
description: Standard OAuth 2.0 endpoint that returns an access_token after successful authorization.
operationId: token
requestBody:
description: ''
content:
application/x-www-form-urlencoded:
application/json:
schema:
$ref: '#/components/schemas/TokenRequest'
required: true
Expand Down Expand Up @@ -182,7 +181,7 @@ paths:
Standard OpenID4VCI endpoint that allows the Issuer to pass information about the credential offer to the Holder's wallet.
[Specification](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-credential-offer-endpoint)
operationId: offers
operationId: offers_params
requestBody:
content:
application/json:
Expand All @@ -200,9 +199,8 @@ paths:
description: Standard OAuth 2.0 endpoint.
operationId: redirect
requestBody:
description: ''
content:
application/x-www-form-urlencoded:
application/json:
schema:
$ref: '#/components/schemas/GenericAuthorizationResponse'
required: true
Expand Down Expand Up @@ -252,7 +250,7 @@ paths:
- Verification
summary: Get an Authorization Request
description: Retrieve an existing Authorization Request.
operationId: get_authorization_requests
operationId: all_authorization_requests
parameters:
- name: id
in: path
Expand Down Expand Up @@ -328,7 +326,7 @@ paths:
- Issuance
summary: Retrieve a credential
description: Retrieves an existing credential by its ID.
operationId: get_credentials
operationId: credential
parameters:
- name: id
in: path
Expand Down Expand Up @@ -432,7 +430,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/SendOfferEndpointRequest'
$ref: '#/components/schemas/SendOfferEndpointRequestSchema'
example:
offerId: '0001'
targetUrl: https://wallet.example.com/openid4vci/offers
Expand All @@ -445,20 +443,71 @@ paths:
components:
schemas:
AuthorizationRequestsEndpointRequest:
allOf:
- allOf:
- type: 'null'
- $ref: '#/components/schemas/PresentationDefinitionResource'
- type: object
required:
- nonce
properties:
nonce:
type: string
state:
type:
- string
- 'null'
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
AuthorizationServerMetadata:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
CredentialIssuerMetadata:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
CredentialRequest:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
CredentialResponse:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
CredentialView:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
CredentialsEndpointRequest:
type: object
required:
Expand All @@ -473,6 +522,28 @@ components:
type: boolean
offerId:
type: string
GenericAuthorizationRequest:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
GenericAuthorizationResponse:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
OffersEndpointRequest:
type: object
required:
Expand All @@ -481,19 +552,37 @@ components:
offerId:
type: string
Oid4vciOfferEndpointRequest:
allOf:
- $ref: '#/components/schemas/CredentialOffer'
- type: object
SendOfferEndpointRequest:
type: object
required:
- offerId
- targetUrl
- foo
- bar
properties:
offerId:
bar:
type: integer
format: int32
foo:
type: string
SendOfferEndpointRequestSchema:
type: object
required:
- offer_id
- target_url
properties:
offer_id:
type: string
target_url:
type: string
TokenRequest:
type: object
required:
- foo
- bar
properties:
bar:
type: integer
format: int32
foo:
type: string
targetUrl:
$ref: '#/components/schemas/Url'
tags:
- name: (public)
description: A collection of endpoints that should be publicly accessible without authentication. They are used to resolve metadata or allow communication with wallets.
Expand Down
18 changes: 16 additions & 2 deletions agent_api_rest/src/holder/openid4vci/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,21 @@ use serde_json::Value;
use tracing::info;
use utoipa::ToSchema;

#[derive(Deserialize, Serialize, ToSchema)]
#[derive(ToSchema)]
#[schema(as = CredentialOffer)]
pub struct CredentialOfferSchema {
pub foo: String,
pub bar: i32,
}

#[derive(ToSchema)]
#[schema(as = Oid4vciOfferEndpointRequest)]
pub struct Oid4vciOfferEndpointRequestSchema {
pub foo: String,
pub bar: i32,
}

#[derive(Deserialize, Serialize)]
pub struct Oid4vciOfferEndpointRequest {
#[serde(flatten)]
pub credential_offer: CredentialOffer,
Expand All @@ -26,7 +40,7 @@ pub struct Oid4vciOfferEndpointRequest {
#[utoipa::path(
get,
path = "/openid4vci/offers",
request_body = Oid4vciOfferEndpointRequest,
request_body = Oid4vciOfferEndpointRequestSchema,
tag = "Holder",
tags = ["(public)"],
responses(
Expand Down
21 changes: 18 additions & 3 deletions agent_api_rest/src/issuance/credential_issuer/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,29 @@ use axum::{
response::{IntoResponse, Response},
};
use axum_auth::AuthBearer;
use oid4vci::credential_request::CredentialRequest;
use oid4vci::{credential_request::CredentialRequest, credential_response::CredentialResponse};
use serde_json::json;
use tokio::time::sleep;
use tracing::{error, info};
use utoipa::ToSchema;

const DEFAULT_EXTERNAL_SERVER_RESPONSE_TIMEOUT_MS: u64 = 1000;
const POLLING_INTERVAL_MS: u64 = 100;

#[derive(ToSchema)]
#[schema(as = CredentialRequest)]
pub struct CredentialRequestSchema {
pub foo: String,
pub bar: i32,
}

#[derive(ToSchema)]
#[schema(as = CredentialResponse)]
pub struct CredentialResponseSchema {
pub foo: String,
pub bar: i32,
}

/// Credential Endpoint
///
/// Standard OpenID4VCI endpoint for redeeming a token for a credential.
Expand All @@ -32,11 +47,11 @@ const POLLING_INTERVAL_MS: u64 = 100;
path = "/openid4vci/credential",
// TODO: doesn't work since (external) `CredentialRequest` doesn't implement `ToSchema`?
// See: https://github.com/juhaku/utoipa?tab=readme-ov-file#how-to-implement-toschema-for-external-type
request_body = CredentialRequest,
request_body = CredentialRequestSchema,
tag = "Issuance",
tags = ["(public)"],
responses(
(status = 200, description = "Successfully returns the credential", body = [CredentialResponse])
(status = 200, description = "Successfully returns the credential", body = [CredentialResponseSchema])
)
)]
#[axum_macros::debug_handler]
Expand Down
9 changes: 9 additions & 0 deletions agent_api_rest/src/issuance/credential_issuer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,22 @@ use axum::{
use oid4vci::token_request::TokenRequest;
use serde_json::json;
use tracing::info;
use utoipa::ToSchema;

#[derive(ToSchema)]
#[schema(as = TokenRequest)]
pub struct TokenRequestSchema {
pub foo: String,
pub bar: i32,
}

/// Token Endpoint
///
/// Standard OAuth 2.0 endpoint that returns an access_token after successful authorization.
#[utoipa::path(
post,
path = "/auth/token",
request_body = TokenRequestSchema,
tags = ["(public)"],
responses(
(status = 200, description = "Returns an access token."),
Expand Down
Loading

0 comments on commit 93084d4

Please sign in to comment.