Skip to content

Commit 045ddc1

Browse files
committed
Check config schema
1 parent 330c427 commit 045ddc1

File tree

5 files changed

+67
-12
lines changed

5 files changed

+67
-12
lines changed

rust/agama-lib/src/questions/http_client.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub enum QuestionsHTTPClientError {
3838
HTTP(#[from] BaseHTTPClientError),
3939
#[error("Unknown question with ID {0}")]
4040
UnknownQuestion(u32),
41+
#[error(transparent)]
42+
Json(#[from] serde_json::Error),
4143
}
4244

4345
pub struct HTTPClient {
@@ -100,7 +102,7 @@ impl HTTPClient {
100102
};
101103

102104
let patch = Patch {
103-
update: Some(config),
105+
update: Some(serde_json::to_value(config)?),
104106
};
105107

106108
_ = self.client.patch_void("/v2/config", &patch).await?;
@@ -121,7 +123,7 @@ impl HTTPClient {
121123
};
122124

123125
let patch = Patch {
124-
update: Some(config),
126+
update: Some(serde_json::to_value(config)?),
125127
};
126128
self.client.patch_void("/v2/config", &patch).await?;
127129
Ok(())

rust/agama-server/src/server.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@
2020

2121
pub mod web;
2222
pub use web::server_service;
23+
24+
mod config_schema;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) [2025] SUSE LLC
2+
//
3+
// All Rights Reserved.
4+
//
5+
// This program is free software; you can redistribute it and/or modify it
6+
// under the terms of the GNU General Public License as published by the Free
7+
// Software Foundation; either version 2 of the License, or (at your option)
8+
// any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful, but WITHOUT
11+
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13+
// more details.
14+
//
15+
// You should have received a copy of the GNU General Public License along
16+
// with this program; if not, contact SUSE LLC.
17+
//
18+
// To contact SUSE LLC about this file by physical or electronic mail, you may
19+
// find current contact information at www.suse.com.
20+
21+
//! This module provides utilities to check the config schema.
22+
23+
use agama_lib::{
24+
error::ProfileError,
25+
profile::{ProfileValidator, ValidationOutcome},
26+
};
27+
28+
#[derive(thiserror::Error, Debug)]
29+
pub enum Error {
30+
#[error("The config does not match the schema: {0}")]
31+
Schema(String),
32+
#[error(transparent)]
33+
ProfileValidator(#[from] ProfileError),
34+
#[error(transparent)]
35+
Json(#[from] serde_json::Error),
36+
}
37+
38+
pub fn check(json: &serde_json::Value) -> Result<(), Error> {
39+
let raw_json = serde_json::to_string(json)?;
40+
let result = ProfileValidator::default_schema()?.validate_str(&raw_json)?;
41+
match result {
42+
ValidationOutcome::Valid => Ok(()),
43+
ValidationOutcome::NotValid(reasons) => Err(Error::Schema(reasons.join(", "))),
44+
}
45+
}

rust/agama-server/src/server/web.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
//! This module implements Agama's HTTP API.
2222
23+
use crate::server::config_schema;
2324
use agama_lib::error::ServiceError;
2425
use agama_manager::{self as manager, message};
2526
use agama_utils::{
@@ -39,14 +40,18 @@ use axum::{
3940
};
4041
use hyper::StatusCode;
4142
use serde::Serialize;
42-
use serde_json::{json, value::RawValue};
43+
use serde_json::{json, value::RawValue, Value};
4344

4445
#[derive(thiserror::Error, Debug)]
4546
pub enum Error {
4647
#[error(transparent)]
4748
Manager(#[from] manager::service::Error),
4849
#[error(transparent)]
4950
Questions(#[from] question::service::Error),
51+
#[error(transparent)]
52+
ConfigSchema(#[from] config_schema::Error),
53+
#[error(transparent)]
54+
Json(#[from] serde_json::Error),
5055
}
5156

5257
impl IntoResponse for Error {
@@ -179,13 +184,12 @@ async fn get_config(State(state): State<ServerState>) -> ServerResult<Json<Confi
179184
(status = 400, description = "Not possible to replace the configuration.")
180185
),
181186
params(
182-
("config" = Config, description = "Configuration to apply.")
187+
("config" = Value, description = "Configuration to apply.")
183188
)
184189
)]
185-
async fn put_config(
186-
State(state): State<ServerState>,
187-
Json(config): Json<Config>,
188-
) -> ServerResult<()> {
190+
async fn put_config(State(state): State<ServerState>, Json(json): Json<Value>) -> ServerResult<()> {
191+
config_schema::check(&json)?;
192+
let config = serde_json::from_value(json)?;
189193
state.manager.call(message::SetConfig::new(config)).await?;
190194
Ok(())
191195
}
@@ -202,14 +206,16 @@ async fn put_config(
202206
(status = 400, description = "Not possible to patch the configuration.")
203207
),
204208
params(
205-
("config" = Config, description = "Changes in the configuration.")
209+
("config" = config::Patch, description = "Changes in the configuration.")
206210
)
207211
)]
208212
async fn patch_config(
209213
State(state): State<ServerState>,
210214
Json(patch): Json<config::Patch>,
211215
) -> ServerResult<()> {
212-
if let Some(config) = patch.update {
216+
if let Some(json) = patch.update {
217+
config_schema::check(&json)?;
218+
let config = serde_json::from_value(json)?;
213219
state
214220
.manager
215221
.call(message::UpdateConfig::new(config))

rust/agama-utils/src/api/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
use crate::api::{l10n, question};
2222
use serde::{Deserialize, Serialize};
23-
use serde_json::value::RawValue;
23+
use serde_json::{value::RawValue, Value};
2424

2525
#[derive(Clone, Debug, Default, Deserialize, Serialize, utoipa::ToSchema)]
2626
#[serde(rename_all = "camelCase")]
@@ -43,5 +43,5 @@ pub struct Config {
4343
#[serde(rename_all = "camelCase")]
4444
pub struct Patch {
4545
/// Update for the current config.
46-
pub update: Option<Config>,
46+
pub update: Option<Value>,
4747
}

0 commit comments

Comments
 (0)