WIP: onboard API

This commit is contained in:
Daniel Lundin 2024-12-26 21:04:38 +01:00
parent 49372f0e58
commit f351c8615d
Signed by: dln
SSH key fingerprint: SHA256:dQy1Xj3UiqJYpKR5ggQ2bxgz4jCH8IF+k3AB8o0kmdI
6 changed files with 178 additions and 0 deletions

View file

@ -15,10 +15,12 @@ schemars.workspace = true
serde.workspace = true
slog-async.workspace = true
slog.workspace = true
thiserror.workspace = true
tokio.workspace = true
trace-request = { path = "../trace-request" }
tracing-slog.workspace = true
tracing.workspace = true
validator.workspace = true
[package.metadata.cargo-machete]
ignored = ["http"]

View file

@ -4,6 +4,7 @@ use dropshot::ApiDescription;
use std::sync::Arc;
use crate::context::ControllerContext;
use crate::onboard;
use crate::version;
type ControllerApiDescription = ApiDescription<Arc<ControllerContext>>;
@ -11,5 +12,6 @@ type ControllerApiDescription = ApiDescription<Arc<ControllerContext>>;
pub fn api() -> Result<ControllerApiDescription> {
let mut api = ControllerApiDescription::new();
api.register(version::version)?;
api.register(onboard::onboard)?;
Ok(api)
}

View file

@ -1,4 +1,5 @@
pub mod api;
pub mod context;
mod onboard;
mod version;

76
controller/src/onboard.rs Normal file
View file

@ -0,0 +1,76 @@
use dropshot::{endpoint, HttpError, HttpResponseOk, RequestContext, TypedBody};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use trace_request::trace_request;
use validator::Validate;
use std::result::Result;
use std::sync::Arc;
use crate::context::ControllerContext;
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Validate)]
pub struct OnboardRequest {
#[validate(nested)]
ownership_voucher: OwnershipVoucher,
}
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Validate)]
pub struct OwnershipVoucher {
#[validate(length(min = 3, max = 5))]
name: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
pub struct OnboardResponse {
result: String,
}
impl OnboardRequest {
pub fn from(body: TypedBody<OnboardRequest>) -> Result<Self, OnboardError> {
let req = body.into_inner();
req.validate()?;
Ok(req)
}
}
#[derive(Clone, Debug, Error)]
pub enum OnboardError {
#[error("Invalid ownership voucher: {0}")]
ValidationError(#[from] validator::ValidationErrors),
}
impl From<OnboardError> for HttpError {
fn from(e: OnboardError) -> Self {
match e {
OnboardError::ValidationError(msg) => HttpError::for_bad_request(
Some("ValidationError".to_string()),
msg.to_string(),
),
}
}
}
/// Onboard new device
#[endpoint {
method = POST,
path = "/onboard",
}]
#[trace_request]
pub(crate) async fn onboard(
rqctx: RequestContext<Arc<ControllerContext>>,
body: TypedBody<OnboardRequest>,
) -> Result<HttpResponseOk<OnboardResponse>, HttpError> {
tracing::info_span!("Hello, onboard!");
let req = OnboardRequest::from(body)?;
tracing::debug!("Got onboarding request: {:?}", req);
let res = OnboardResponse {
result: "Välkommen ombord!".to_string(),
};
Ok(HttpResponseOk(res))
}