covert_types/
response.rs

1use std::time::Duration;
2
3use http::StatusCode;
4use serde::{de::DeserializeOwned, Serialize};
5use serde_json::Value;
6use tracing_error::SpanTrace;
7
8use crate::error::ApiError;
9
10/// Response from the backend
11#[derive(Debug, Serialize)]
12#[serde(untagged)]
13pub enum Response {
14    /// Raw response. The data will be returned as is to the client.
15    Raw(Value),
16    /// Authentication response. The client will receive a token for the
17    /// given alias.
18    Auth(AuthResponse),
19    /// Register a lease for the payload. Useful for returning dynamic
20    /// secrets that can be revoked and renewed.
21    Lease(LeaseResponse),
22}
23
24// TODO: add renew fields as well
25#[derive(Debug, Serialize)]
26pub struct LeaseResponse {
27    pub revoke: LeaseRenewRevokeEndpoint,
28    pub renew: LeaseRenewRevokeEndpoint,
29    pub data: Value,
30    #[serde(with = "humantime_serde")]
31    pub ttl: Option<Duration>,
32}
33
34#[derive(Debug, Serialize)]
35pub struct LeaseRenewRevokeEndpoint {
36    pub path: String,
37    pub data: Value,
38}
39
40#[derive(Debug, Serialize)]
41pub struct AuthResponse {
42    pub alias: String,
43    #[serde(with = "humantime_serde")]
44    pub ttl: Option<Duration>,
45}
46
47impl Response {
48    #[must_use]
49    pub fn ok() -> Self {
50        Self::Raw(Value::default())
51    }
52
53    /// Construct a response with data that will be returned as is to the client.
54    ///
55    /// # Errors
56    ///
57    /// Returns an error if it fails to serialize the payload.
58    pub fn raw<T: Serialize>(data: T) -> Result<Self, serde_json::Error> {
59        serde_json::to_value(data).map(Self::Raw)
60    }
61
62    /// Try to deserialize the raw data payload from the response.
63    ///
64    /// # Errors
65    ///
66    /// Returns an error if it fails to deserialize the raw payload or if the
67    /// response is not a raw payload.
68    pub fn data<T: DeserializeOwned>(self) -> Result<T, ApiError> {
69        match self {
70            Response::Raw(data) => serde_json::from_value(data).map_err(|err| ApiError {
71                error: err.into(),
72                status_code: StatusCode::BAD_REQUEST,
73                span_trace: Some(SpanTrace::capture()),
74            }),
75            Response::Auth(_data) => Err(ApiError {
76                error: anyhow::Error::msg("expected raw data, found auth data"),
77                status_code: StatusCode::BAD_REQUEST,
78                span_trace: Some(SpanTrace::capture()),
79            }),
80            Response::Lease(_data) => Err(ApiError {
81                error: anyhow::Error::msg("expected raw data, found lease data"),
82                status_code: StatusCode::BAD_REQUEST,
83                span_trace: Some(SpanTrace::capture()),
84            }),
85        }
86    }
87}