Skip to content

Commit

Permalink
Merge pull request #803 from umccr/feat/filemanager-swagger
Browse files Browse the repository at this point in the history
feat(filemanager): deployable swagger ui
  • Loading branch information
mmalenic authored Jan 8, 2025
2 parents 1b7ee2a + c799243 commit 02bce97
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
28 changes: 20 additions & 8 deletions lib/workload/stateless/stacks/filemanager/deploy/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import { StringParameter } from 'aws-cdk-lib/aws-ssm';
import { ProviderFunction } from '../../../../components/provider-function';
import { ApiGatewayConstruct, ApiGatewayConstructProps } from '../../../../components/api-gateway';
import { IQueue, Queue } from 'aws-cdk-lib/aws-sqs';
import { HttpMethod, HttpRoute, HttpRouteKey } from 'aws-cdk-lib/aws-apigatewayv2';
import {
HttpMethod,
HttpNoneAuthorizer,
HttpRoute,
HttpRouteKey,
} from 'aws-cdk-lib/aws-apigatewayv2';
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import { InventoryFunction } from './constructs/functions/inventory';
import { NamedLambdaRole } from '../../../../components/named-lambda-role';
Expand Down Expand Up @@ -150,24 +155,31 @@ export class Filemanager extends Stack {
const apiGateway = new ApiGatewayConstruct(this, 'ApiGateway', props.apiGatewayCognitoProps);
const httpApi = apiGateway.httpApi;

const apiIntegration = new HttpLambdaIntegration('ApiIntegration', apiLambda.function);
const integration = new HttpLambdaIntegration('ApiIntegration', apiLambda.function);

new HttpRoute(this, 'GetSchemaHttpRoute', {
httpApi,
integration,
authorizer: new HttpNoneAuthorizer(),
routeKey: HttpRouteKey.with(`/schema/{proxy+}`, HttpMethod.GET),
});

new HttpRoute(this, 'GetHttpRoute', {
httpApi: httpApi,
integration: apiIntegration,
httpApi,
integration,
routeKey: HttpRouteKey.with('/{proxy+}', HttpMethod.GET),
});

new HttpRoute(this, 'PatchHttpRoute', {
httpApi: httpApi,
integration: apiIntegration,
httpApi,
integration,
authorizer: apiGateway.authStackHttpLambdaAuthorizer,
routeKey: HttpRouteKey.with('/{proxy+}', HttpMethod.PATCH),
});

new HttpRoute(this, 'PostHttpRoute', {
httpApi: httpApi,
integration: apiIntegration,
httpApi,
integration,
authorizer: apiGateway.authStackHttpLambdaAuthorizer,
routeKey: HttpRouteKey.with('/{proxy+}', HttpMethod.POST),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use filemanager::error::Result;
use filemanager::handlers::init_tracing_with_format;
use filemanager::handlers::Format::Pretty;
use filemanager::queries::EntriesBuilder;
use filemanager::routes::openapi::SWAGGER_UI_PATH;
use filemanager::routes::{router, AppState};

/// Run the filemanager API server locally to explore the API.
Expand Down Expand Up @@ -115,8 +116,7 @@ async fn main() -> Result<()> {
.with_key_divisor(key_divisor)
.with_shuffle(shuffle)
.build(state.database_client())
.await
.unwrap();
.await?;
}

if args.migrate {
Expand All @@ -132,7 +132,7 @@ async fn main() -> Result<()> {
let docs = Uri::builder()
.scheme("http")
.authority(local_addr.to_string())
.path_and_query("/swagger-ui")
.path_and_query(SWAGGER_UI_PATH)
.build()
.map_err(|err| IoError(io::Error::other(err)))?;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ pub enum ErrorStatusCode {
example = json!({"message": "JSON Error: parsing json"}),
)]
BadRequest(ErrorResponse),
#[response(
status = UNAUTHORIZED,
description = "the request lacked valid authentication credentials",
example = json!({"message": "Unauthorized"}),
)]
Unauthorized(ErrorResponse),
#[response(
status = FORBIDDEN,
description = "the request lacked valid permissions for the resource",
example = json!({"message": "Forbidden"}),
)]
Forbidden(ErrorResponse),
}

impl From<QueryRejection> for ErrorStatusCode {
Expand Down Expand Up @@ -117,6 +129,8 @@ impl Display for ErrorStatusCode {
ErrorStatusCode::BadRequest(err) => Display::fmt(err, f),
ErrorStatusCode::NotFound(err) => Display::fmt(err, f),
ErrorStatusCode::InternalServerError(err) => Display::fmt(err, f),
ErrorStatusCode::Forbidden(err) => Display::fmt(err, f),
ErrorStatusCode::Unauthorized(err) => Display::fmt(err, f),
ErrorStatusCode::Rejection(_, message) => Display::fmt(message, f),
}
}
Expand All @@ -130,6 +144,8 @@ impl IntoResponse for ErrorStatusCode {
(StatusCode::INTERNAL_SERVER_ERROR, extract::Json(err))
}
ErrorStatusCode::NotFound(err) => (StatusCode::NOT_FOUND, extract::Json(err)),
ErrorStatusCode::Forbidden(err) => (StatusCode::NOT_FOUND, extract::Json(err)),
ErrorStatusCode::Unauthorized(err) => (StatusCode::NOT_FOUND, extract::Json(err)),
ErrorStatusCode::Rejection(status, err) => (
StatusCode::from_u16(status).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
extract::Json(err),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ use crate::routes::pagination::*;
use crate::routes::presign::ContentDisposition;
use crate::routes::update::*;

/// The path to the swagger ui.
pub const SWAGGER_UI_PATH: &str = "/schema/swagger-ui";

/// A newtype equivalent to a `DateTime` with a time zone.
#[derive(ToSchema)]
#[schema(value_type = DateTime, format = DateTime)]
Expand Down Expand Up @@ -102,7 +105,7 @@ impl Modify for SecurityAddon {

/// Create the swagger ui endpoint.
pub fn swagger_ui() -> SwaggerUi {
SwaggerUi::new("/swagger-ui").url("/schema/openapi.json", ApiDoc::openapi())
SwaggerUi::new(SWAGGER_UI_PATH).url("/schema/openapi.json", ApiDoc::openapi())
}

#[cfg(test)]
Expand All @@ -113,6 +116,7 @@ mod tests {
use sqlx::PgPool;
use tower::util::ServiceExt;

use super::*;
use crate::database::aws::migration::tests::MIGRATOR;
use crate::routes::router;
use crate::routes::AppState;
Expand All @@ -123,7 +127,7 @@ mod tests {
let response = app
.oneshot(
Request::builder()
.uri("/swagger-ui")
.uri(SWAGGER_UI_PATH)
.body(Body::empty())
.unwrap(),
)
Expand Down

0 comments on commit 02bce97

Please sign in to comment.