1use actix_web::{http::StatusCode, HttpResponse, ResponseError};
2use log::{error, warn};
3use serde_json::json;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum PAASServerError {
8 #[error("User not authenticated")]
9 NotAuthenticated,
10
11 #[error("Could not start, end or retrieve session")]
12 SessionError(#[source] Box<dyn std::error::Error + Send + Sync>),
13
14 #[error("Invalid session format: {0}")]
15 InvalidSessionFormat(String),
16
17 #[error("Unknown or expired session: {0}")]
18 InvalidSession(String),
19
20 #[error("Unauthorized session access")]
21 UnauthorizedSession,
22
23 #[error("Access denied: not allowed to transcrypt from {from} to {to}")]
24 AccessDenied { from: String, to: String },
25}
26
27impl ResponseError for PAASServerError {
28 fn status_code(&self) -> StatusCode {
29 match &self {
30 Self::NotAuthenticated => StatusCode::UNAUTHORIZED,
31 Self::SessionError(_) => StatusCode::INTERNAL_SERVER_ERROR,
32 Self::InvalidSessionFormat(_) => StatusCode::BAD_REQUEST,
33 Self::InvalidSession(_) => StatusCode::NOT_FOUND,
34 Self::UnauthorizedSession => StatusCode::FORBIDDEN,
35 Self::AccessDenied { .. } => StatusCode::FORBIDDEN,
36 }
37 }
38
39 fn error_response(&self) -> HttpResponse {
40 let status = self.status_code();
41 let error_message = self.to_string();
42
43 match self {
44 Self::NotAuthenticated => {
45 warn!(
46 "Authentication failure: status_code={}, error={}",
47 status.as_u16(),
48 error_message
49 );
50 }
51 Self::SessionError(source) => {
52 error!(
53 "Session operation error: status_code={}, error={}, source={:?}",
54 status.as_u16(),
55 error_message,
56 source
57 );
58 }
59 Self::InvalidSessionFormat(format) => {
60 warn!(
61 "Invalid session format: status_code={}, error={}, format={}",
62 status.as_u16(),
63 error_message,
64 format
65 );
66 }
67 Self::InvalidSession(session) => {
68 warn!(
69 "Invalid session: status_code={}, error={}, session={}",
70 status.as_u16(),
71 error_message,
72 session
73 );
74 }
75 Self::UnauthorizedSession => {
76 warn!(
77 "Unauthorized session access: status_code={}, error={}",
78 status.as_u16(),
79 error_message
80 );
81 }
82 Self::AccessDenied { from, to } => {
83 warn!(
84 "Access denied for transcryption: status_code={}, error={}, from={}, to={}",
85 status.as_u16(),
86 error_message,
87 from,
88 to
89 );
90 }
91 }
92
93 let response_body = if status == StatusCode::INTERNAL_SERVER_ERROR {
95 json!({
96 "error": "An internal server error occurred"
97 })
98 } else {
99 json!({
100 "error": error_message
101 })
102 };
103
104 HttpResponse::build(status)
105 .content_type("application/json")
106 .json(response_body)
107 }
108}
109
110impl From<Box<dyn std::error::Error + Send + Sync>> for PAASServerError {
111 fn from(source: Box<dyn std::error::Error + Send + Sync>) -> Self {
112 error!(
113 "Converting generic error to PAASServerError: error={:?}",
114 source
115 );
116 PAASServerError::SessionError(source)
117 }
118}