csaf-crud 0.3.4

CSAF 2.0 / 2.1 advisory CRUD server with HATEOAS JSON API and HTML UI (TLS 1.3, HTTP/1.1 + HTTP/2 + HTTP/3)
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2026 Pierre Gronau, ndaal in Cologne

//! Settings GET/PUT API handlers.

use http::{Response, StatusCode};
use serde_json::json;

use crate::app_state::AppState;
use crate::hateoas::self_link;
use crate::router::{Body, json_response, parse_json_body, problem_response};

/// `GET /api/v1/settings` -- Retrieve current application settings.
pub async fn get_settings(
    state: AppState,
    _parts: http::request::Parts,
    _params: Vec<(String, String)>,
) -> Response<Body> {
    let settings = state.settings();

    let body = json!({
        "data": serde_json::to_value(&settings).unwrap_or_default(),
        "_links": json!({
            "self": self_link("/api/v1/settings"),
        }),
    });

    json_response(StatusCode::OK, &body)
}

/// `PUT /api/v1/settings` -- Update application settings.
pub async fn update_settings(
    state: AppState,
    parts: http::request::Parts,
    _params: Vec<(String, String)>,
) -> Response<Body> {
    let new_settings: csaf_models::settings::Settings = match parse_json_body(&parts) {
        Ok(s) => s,
        Err(e) => {
            return problem_response(
                StatusCode::BAD_REQUEST,
                "https://ndaal.eu/csaf/errors/invalid-json",
                "Invalid JSON",
                &e,
            );
        },
    };

    if let Err(e) = state.update_settings(new_settings.clone()) {
        tracing::error!("Failed to update settings: {e}");
        return problem_response(
            StatusCode::INTERNAL_SERVER_ERROR,
            "https://ndaal.eu/csaf/errors/storage",
            "Storage Error",
            "Failed to persist settings",
        );
    }

    let body = json!({
        "data": serde_json::to_value(&new_settings).unwrap_or_default(),
        "message": "Settings updated successfully",
        "_links": json!({
            "self": self_link("/api/v1/settings"),
        }),
    });

    json_response(StatusCode::OK, &body)
}