1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-09 04:22:45 +03:00

handlers: bootstrap the admin API router

This commit is contained in:
Quentin Gliech
2024-07-24 15:41:49 +02:00
parent a1b13288ab
commit f4f61f0d51
5 changed files with 156 additions and 0 deletions

52
Cargo.lock generated
View File

@@ -84,6 +84,41 @@ dependencies = [
"memchr",
]
[[package]]
name = "aide"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0e3b97a21e41ec5c19bfd9b4fc1f7086be104f8b988681230247ffc91cc8ed"
dependencies = [
"aide-macros",
"axum",
"axum-extra",
"bytes",
"cfg-if",
"http",
"indexmap 2.2.6",
"schemars",
"serde",
"serde_json",
"serde_qs",
"thiserror",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "aide-macros"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0487f8598afe49e6bc950a613a678bd962c4a6f431022ded62643c8b990301a"
dependencies = [
"darling 0.20.9",
"proc-macro2",
"quote",
"syn 2.0.68",
]
[[package]]
name = "allocator-api2"
version = "0.2.18"
@@ -3283,6 +3318,7 @@ dependencies = [
name = "mas-handlers"
version = "0.9.0"
dependencies = [
"aide",
"anyhow",
"argon2",
"async-graphql",
@@ -3298,6 +3334,7 @@ dependencies = [
"futures-util",
"headers",
"hyper",
"indexmap 2.2.6",
"insta",
"lettre",
"mas-axum-utils",
@@ -3325,6 +3362,7 @@ dependencies = [
"rand",
"rand_chacha",
"rustls 0.23.12",
"schemars",
"sentry",
"serde",
"serde_json",
@@ -5249,6 +5287,7 @@ dependencies = [
"chrono",
"dyn-clone",
"indexmap 1.9.3",
"indexmap 2.2.6",
"schemars_derive",
"serde",
"serde_json",
@@ -5553,6 +5592,19 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_qs"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6"
dependencies = [
"axum",
"futures",
"percent-encoding",
"serde",
"thiserror",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"

View File

@@ -55,6 +55,11 @@ mas-templates = { path = "./crates/templates/", version = "=0.9.0" }
mas-tower = { path = "./crates/tower/", version = "=0.9.0" }
oauth2-types = { path = "./crates/oauth2-types/", version = "=0.9.0" }
# OpenAPI schema generation and validation
[workspace.dependencies.aide]
version = "0.13.4"
features = ["axum", "axum-headers", "macros"]
# GraphQL server
[workspace.dependencies.async-graphql]
version = "7.0.7"

View File

@@ -36,7 +36,9 @@ axum-macros = "0.4.1"
axum-extra.workspace = true
rustls.workspace = true
aide.workspace = true
async-graphql.workspace = true
schemars.workspace = true
# Emails
lettre.workspace = true
@@ -65,6 +67,7 @@ zeroize = "1.8.1"
base64ct = "1.6.0"
camino.workspace = true
chrono.workspace = true
indexmap = "2.2.6"
psl = "2.1.55"
time = "0.3.36"
url.workspace = true

View File

@@ -0,0 +1,94 @@
// Copyright 2024 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use aide::{
axum::ApiRouter,
openapi::{OAuth2Flow, OAuth2Flows, OpenApi, SecurityScheme, Server, ServerVariable},
};
use axum::{Json, Router};
use hyper::header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE};
use indexmap::IndexMap;
use mas_http::CorsLayerExt;
use mas_router::{OAuth2AuthorizationEndpoint, OAuth2TokenEndpoint, SimpleRoute};
use tower_http::cors::{Any, CorsLayer};
pub fn router<S>() -> (OpenApi, Router<S>)
where
S: Clone + Send + Sync + 'static,
{
let mut api = OpenApi::default();
let router = ApiRouter::<S>::new()
// TODO: add routes
.finish_api_with(&mut api, |t| {
t.title("Matrix Authentication Service admin API")
.security_scheme(
"oauth2",
SecurityScheme::OAuth2 {
flows: OAuth2Flows {
client_credentials: Some(OAuth2Flow::ClientCredentials {
refresh_url: Some(OAuth2TokenEndpoint::PATH.to_owned()),
token_url: OAuth2TokenEndpoint::PATH.to_owned(),
scopes: IndexMap::from([(
"urn:mas:admin".to_owned(),
"Grant access to the admin API".to_owned(),
)]),
}),
authorization_code: Some(OAuth2Flow::AuthorizationCode {
authorization_url: OAuth2AuthorizationEndpoint::PATH.to_owned(),
refresh_url: Some(OAuth2TokenEndpoint::PATH.to_owned()),
token_url: OAuth2TokenEndpoint::PATH.to_owned(),
scopes: IndexMap::from([(
"urn:mas:admin".to_owned(),
"Grant access to the admin API".to_owned(),
)]),
}),
implicit: None,
password: None,
},
description: None,
extensions: IndexMap::default(),
},
)
.security_requirement_scopes("oauth2", ["urn:mas:admin"])
.server(Server {
url: "{base}".to_owned(),
variables: IndexMap::from([(
"base".to_owned(),
ServerVariable {
default: "/".to_owned(),
..ServerVariable::default()
},
)]),
..Server::default()
})
});
let router = router
// Serve the OpenAPI spec as JSON
.route(
"/api/spec.json",
axum::routing::get({
let res = Json(api.clone());
move || std::future::ready(res.clone())
}),
)
.layer(
CorsLayer::new()
.allow_origin(Any)
.allow_methods(Any)
.allow_otel_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE]),
);
(api, router)
}

View File

@@ -53,6 +53,7 @@ use sqlx::PgPool;
use tower::util::AndThenLayer;
use tower_http::cors::{Any, CorsLayer};
mod admin;
mod compat;
mod graphql;
mod health;
@@ -89,6 +90,7 @@ pub use mas_axum_utils::{
pub use self::{
activity_tracker::{ActivityTracker, Bound as BoundActivityTracker},
admin::router as admin_api_router,
graphql::{
schema as graphql_schema, schema_builder as graphql_schema_builder, Schema as GraphQLSchema,
},