Skip to content

Commit c3296a2

Browse files
committed
Make the admin API update the local policy data
1 parent 7569223 commit c3296a2

File tree

7 files changed

+66
-3
lines changed

7 files changed

+66
-3
lines changed

crates/cli/src/app_state.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,12 @@ impl FromRef<AppState> for Limiter {
204204
}
205205
}
206206

207+
impl FromRef<AppState> for Arc<PolicyFactory> {
208+
fn from_ref(input: &AppState) -> Self {
209+
input.policy_factory.clone()
210+
}
211+
}
212+
207213
impl FromRef<AppState> for BoxHomeserverConnection {
208214
fn from_ref(input: &AppState) -> Self {
209215
Box::new(input.homeserver_connection.clone())

crates/handlers/src/admin/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// SPDX-License-Identifier: AGPL-3.0-only
55
// Please see LICENSE in the repository root for full details.
66

7+
use std::sync::Arc;
8+
79
use aide::{
810
axum::ApiRouter,
911
openapi::{OAuth2Flow, OAuth2Flows, OpenApi, SecurityScheme, Server, Tag},
@@ -20,6 +22,7 @@ use indexmap::IndexMap;
2022
use mas_axum_utils::FancyError;
2123
use mas_http::CorsLayerExt;
2224
use mas_matrix::BoxHomeserverConnection;
25+
use mas_policy::PolicyFactory;
2326
use mas_router::{
2427
ApiDoc, ApiDocCallback, OAuth2AuthorizationEndpoint, OAuth2TokenEndpoint, Route, SimpleRoute,
2528
UrlBuilder,
@@ -118,6 +121,7 @@ where
118121
CallContext: FromRequestParts<S>,
119122
Templates: FromRef<S>,
120123
UrlBuilder: FromRef<S>,
124+
Arc<PolicyFactory>: FromRef<S>,
121125
{
122126
// We *always* want to explicitly set the possible responses, beacuse the
123127
// infered ones are not necessarily correct

crates/handlers/src/admin/v1/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
// SPDX-License-Identifier: AGPL-3.0-only
55
// Please see LICENSE in the repository root for full details.
66

7+
use std::sync::Arc;
8+
79
use aide::axum::{
810
ApiRouter,
911
routing::{get_with, post_with},
1012
};
1113
use axum::extract::{FromRef, FromRequestParts};
1214
use mas_matrix::BoxHomeserverConnection;
15+
use mas_policy::PolicyFactory;
1316
use mas_storage::BoxRng;
1417

1518
use super::call_context::CallContext;
@@ -28,6 +31,7 @@ where
2831
S: Clone + Send + Sync + 'static,
2932
BoxHomeserverConnection: FromRef<S>,
3033
PasswordManager: FromRef<S>,
34+
Arc<PolicyFactory>: FromRef<S>,
3135
BoxRng: FromRequestParts<S>,
3236
CallContext: FromRequestParts<S>,
3337
{

crates/handlers/src/admin/v1/policy_data/set.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
//
33
// SPDX-License-Identifier: AGPL-3.0-only
44

5+
use std::sync::Arc;
6+
57
use aide::{NoApi, OperationIo, transform::TransformOperation};
6-
use axum::{Json, response::IntoResponse};
8+
use axum::{Json, extract::State, response::IntoResponse};
79
use hyper::StatusCode;
10+
use mas_policy::PolicyFactory;
811
use mas_storage::BoxRng;
912
use schemars::JsonSchema;
1013
use serde::Deserialize;
@@ -21,6 +24,9 @@ use crate::{
2124
#[derive(Debug, thiserror::Error, OperationIo)]
2225
#[aide(output_with = "Json<ErrorResponse>")]
2326
pub enum RouteError {
27+
#[error("Failed to instanciate policy with the provided data")]
28+
InvalidPolicyData(#[from] mas_policy::LoadError),
29+
2430
#[error(transparent)]
2531
Internal(Box<dyn std::error::Error + Send + Sync + 'static>),
2632
}
@@ -30,7 +36,10 @@ impl_from_error_for_route!(mas_storage::RepositoryError);
3036
impl IntoResponse for RouteError {
3137
fn into_response(self) -> axum::response::Response {
3238
let error = ErrorResponse::from_error(&self);
33-
let status = StatusCode::INTERNAL_SERVER_ERROR;
39+
let status = match self {
40+
RouteError::InvalidPolicyData(_) => StatusCode::BAD_REQUEST,
41+
RouteError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
42+
};
3443
(status, Json(error)).into_response()
3544
}
3645
}
@@ -62,6 +71,12 @@ pub fn doc(operation: TransformOperation) -> TransformOperation {
6271
t.description("Policy data was successfully set")
6372
.example(response)
6473
})
74+
.response_with::<400, Json<ErrorResponse>, _>(|t| {
75+
let error = ErrorResponse::from_error(&RouteError::InvalidPolicyData(
76+
mas_policy::LoadError::invalid_data_example(),
77+
));
78+
t.description("Invalid policy data").example(error)
79+
})
6580
}
6681

6782
#[tracing::instrument(name = "handler.admin.v1.policy_data.set", skip_all, err)]
@@ -70,13 +85,17 @@ pub async fn handler(
7085
mut repo, clock, ..
7186
}: CallContext,
7287
NoApi(mut rng): NoApi<BoxRng>,
88+
State(policy_factory): State<Arc<PolicyFactory>>,
7389
Json(request): Json<SetPolicyDataRequest>,
7490
) -> Result<(StatusCode, Json<SingleResponse<PolicyData>>), RouteError> {
7591
let policy_data = repo
7692
.policy_data()
7793
.set(&mut rng, &clock, request.data)
7894
.await?;
7995

96+
// Swap the policy data. This will fail if the policy data is invalid
97+
policy_factory.set_dynamic_data(policy_data.clone()).await?;
98+
8099
repo.save().await?;
81100

82101
Ok((

crates/handlers/src/bin/api-schema.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
)]
1414
#![warn(clippy::pedantic)]
1515

16-
use std::io::Write;
16+
use std::{io::Write, sync::Arc};
1717

1818
use aide::openapi::{Server, ServerVariable};
1919
use indexmap::IndexMap;
@@ -58,6 +58,7 @@ impl_from_ref!(mas_templates::Templates);
5858
impl_from_ref!(mas_matrix::BoxHomeserverConnection);
5959
impl_from_ref!(mas_keystore::Keystore);
6060
impl_from_ref!(mas_handlers::passwords::PasswordManager);
61+
impl_from_ref!(Arc<mas_policy::PolicyFactory>);
6162

6263
fn main() -> Result<(), Box<dyn std::error::Error>> {
6364
let (mut api, _) = mas_handlers::admin_api_router::<DummyState>();

crates/handlers/src/test_utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,12 @@ impl FromRef<TestState> for SiteConfig {
513513
}
514514
}
515515

516+
impl FromRef<TestState> for Arc<PolicyFactory> {
517+
fn from_ref(input: &TestState) -> Self {
518+
input.policy_factory.clone()
519+
}
520+
}
521+
516522
impl FromRef<TestState> for BoxHomeserverConnection {
517523
fn from_ref(input: &TestState) -> Self {
518524
Box::new(input.homeserver_connection.clone())

docs/api/spec.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,29 @@
640640
}
641641
}
642642
}
643+
},
644+
"400": {
645+
"description": "Invalid policy data",
646+
"content": {
647+
"application/json": {
648+
"schema": {
649+
"$ref": "#/components/schemas/ErrorResponse"
650+
},
651+
"example": {
652+
"errors": [
653+
{
654+
"title": "Failed to instanciate policy with the provided data"
655+
},
656+
{
657+
"title": "invalid policy data"
658+
},
659+
{
660+
"title": "Failed to merge policy data objects"
661+
}
662+
]
663+
}
664+
}
665+
}
643666
}
644667
}
645668
}

0 commit comments

Comments
 (0)