Skip to content
This repository was archived by the owner on Sep 10, 2024. It is now read-only.

Commit f4f61f0

Browse files
committed
handlers: bootstrap the admin API router
1 parent a1b1328 commit f4f61f0

File tree

5 files changed

+156
-0
lines changed

5 files changed

+156
-0
lines changed

Cargo.lock

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ mas-templates = { path = "./crates/templates/", version = "=0.9.0" }
5555
mas-tower = { path = "./crates/tower/", version = "=0.9.0" }
5656
oauth2-types = { path = "./crates/oauth2-types/", version = "=0.9.0" }
5757

58+
# OpenAPI schema generation and validation
59+
[workspace.dependencies.aide]
60+
version = "0.13.4"
61+
features = ["axum", "axum-headers", "macros"]
62+
5863
# GraphQL server
5964
[workspace.dependencies.async-graphql]
6065
version = "7.0.7"

crates/handlers/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ axum-macros = "0.4.1"
3636
axum-extra.workspace = true
3737
rustls.workspace = true
3838

39+
aide.workspace = true
3940
async-graphql.workspace = true
41+
schemars.workspace = true
4042

4143
# Emails
4244
lettre.workspace = true
@@ -65,6 +67,7 @@ zeroize = "1.8.1"
6567
base64ct = "1.6.0"
6668
camino.workspace = true
6769
chrono.workspace = true
70+
indexmap = "2.2.6"
6871
psl = "2.1.55"
6972
time = "0.3.36"
7073
url.workspace = true

crates/handlers/src/admin/mod.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright 2024 The Matrix.org Foundation C.I.C.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use aide::{
16+
axum::ApiRouter,
17+
openapi::{OAuth2Flow, OAuth2Flows, OpenApi, SecurityScheme, Server, ServerVariable},
18+
};
19+
use axum::{Json, Router};
20+
use hyper::header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE};
21+
use indexmap::IndexMap;
22+
use mas_http::CorsLayerExt;
23+
use mas_router::{OAuth2AuthorizationEndpoint, OAuth2TokenEndpoint, SimpleRoute};
24+
use tower_http::cors::{Any, CorsLayer};
25+
26+
pub fn router<S>() -> (OpenApi, Router<S>)
27+
where
28+
S: Clone + Send + Sync + 'static,
29+
{
30+
let mut api = OpenApi::default();
31+
let router = ApiRouter::<S>::new()
32+
// TODO: add routes
33+
.finish_api_with(&mut api, |t| {
34+
t.title("Matrix Authentication Service admin API")
35+
.security_scheme(
36+
"oauth2",
37+
SecurityScheme::OAuth2 {
38+
flows: OAuth2Flows {
39+
client_credentials: Some(OAuth2Flow::ClientCredentials {
40+
refresh_url: Some(OAuth2TokenEndpoint::PATH.to_owned()),
41+
token_url: OAuth2TokenEndpoint::PATH.to_owned(),
42+
scopes: IndexMap::from([(
43+
"urn:mas:admin".to_owned(),
44+
"Grant access to the admin API".to_owned(),
45+
)]),
46+
}),
47+
authorization_code: Some(OAuth2Flow::AuthorizationCode {
48+
authorization_url: OAuth2AuthorizationEndpoint::PATH.to_owned(),
49+
refresh_url: Some(OAuth2TokenEndpoint::PATH.to_owned()),
50+
token_url: OAuth2TokenEndpoint::PATH.to_owned(),
51+
scopes: IndexMap::from([(
52+
"urn:mas:admin".to_owned(),
53+
"Grant access to the admin API".to_owned(),
54+
)]),
55+
}),
56+
implicit: None,
57+
password: None,
58+
},
59+
description: None,
60+
extensions: IndexMap::default(),
61+
},
62+
)
63+
.security_requirement_scopes("oauth2", ["urn:mas:admin"])
64+
.server(Server {
65+
url: "{base}".to_owned(),
66+
variables: IndexMap::from([(
67+
"base".to_owned(),
68+
ServerVariable {
69+
default: "/".to_owned(),
70+
..ServerVariable::default()
71+
},
72+
)]),
73+
..Server::default()
74+
})
75+
});
76+
77+
let router = router
78+
// Serve the OpenAPI spec as JSON
79+
.route(
80+
"/api/spec.json",
81+
axum::routing::get({
82+
let res = Json(api.clone());
83+
move || std::future::ready(res.clone())
84+
}),
85+
)
86+
.layer(
87+
CorsLayer::new()
88+
.allow_origin(Any)
89+
.allow_methods(Any)
90+
.allow_otel_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE]),
91+
);
92+
93+
(api, router)
94+
}

crates/handlers/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use sqlx::PgPool;
5353
use tower::util::AndThenLayer;
5454
use tower_http::cors::{Any, CorsLayer};
5555

56+
mod admin;
5657
mod compat;
5758
mod graphql;
5859
mod health;
@@ -89,6 +90,7 @@ pub use mas_axum_utils::{
8990

9091
pub use self::{
9192
activity_tracker::{ActivityTracker, Bound as BoundActivityTracker},
93+
admin::router as admin_api_router,
9294
graphql::{
9395
schema as graphql_schema, schema_builder as graphql_schema_builder, Schema as GraphQLSchema,
9496
},

0 commit comments

Comments
 (0)