aauth_person_server/
error.rs1use bytes::Bytes;
2use http::{HeaderValue, Response, StatusCode};
3use serde_json::json;
4
5#[derive(Clone, Debug, thiserror::Error)]
7#[error("{error}: {detail}")]
8pub struct AAuthError {
9 pub status: StatusCode,
11 pub error: String,
13 pub detail: String,
15 pub headers: Vec<(&'static str, String)>,
17}
18
19impl AAuthError {
20 pub fn new(status: StatusCode, error: impl Into<String>, detail: impl Into<String>) -> Self {
22 Self {
23 status,
24 error: error.into(),
25 detail: detail.into(),
26 headers: Vec::new(),
27 }
28 }
29
30 pub(crate) fn invalid_request(detail: impl Into<String>) -> Self {
31 Self::new(StatusCode::BAD_REQUEST, "invalid_request", detail)
32 }
33
34 pub(crate) fn forbidden(detail: impl Into<String>) -> Self {
36 Self::new(StatusCode::FORBIDDEN, "invalid_request", detail)
37 }
38
39 pub(crate) fn mission_terminated(detail: impl Into<String>) -> Self {
41 Self::new(StatusCode::FORBIDDEN, "mission_terminated", detail)
42 }
43
44 pub(crate) fn mission_not_found() -> Self {
47 Self::new(
48 StatusCode::NOT_FOUND,
49 "mission_not_found",
50 "no such mission",
51 )
52 }
53
54 pub(crate) fn signature(code: &str, detail: impl Into<String>) -> Self {
56 let mut error = Self::new(StatusCode::UNAUTHORIZED, code, detail);
57 error
58 .headers
59 .push(("signature-error", format!("error={code}")));
60 error
61 }
62
63 pub fn into_response(self) -> Response<Bytes> {
65 let mut response = problem(self.status, &self.error, Some(&self.detail));
66 for (name, value) in self.headers {
67 if let Ok(value) = HeaderValue::from_str(&value) {
68 response.headers_mut().insert(name, value);
69 }
70 }
71 response
72 }
73}
74
75impl From<crate::store::StoreError> for AAuthError {
76 fn from(error: crate::store::StoreError) -> Self {
77 Self::new(
78 StatusCode::SERVICE_UNAVAILABLE,
79 "temporarily_unavailable",
80 error.to_string(),
81 )
82 }
83}
84
85pub fn problem(status: StatusCode, error: &str, detail: Option<&str>) -> Response<Bytes> {
87 let mut body = json!({ "error": error });
88 if let Some(detail) = detail.filter(|d| !d.is_empty()) {
89 body["detail"] = json!(detail);
90 }
91 let mut response = Response::new(Bytes::from(body.to_string()));
92 *response.status_mut() = status;
93 response.headers_mut().insert(
94 "content-type",
95 HeaderValue::from_static("application/problem+json"),
96 );
97 response
98}