helloasso/error.rs
1//! Errors this crate can return
2
3use std::fmt::Display;
4
5use thiserror::Error;
6
7use serde::Deserialize;
8
9/// Errors that may occur when using the [client](crate::HelloAsso)
10///
11/// It can ether be a [Reqwest Error](reqwest::Error) or an [Authentication Error](crate::AuthenticationError)
12#[derive(Error, Debug)]
13#[non_exhaustive]
14pub enum Error {
15 #[error("request failed")]
16 ReqwestErr(#[from] reqwest::Error),
17 #[error("authentification failed")]
18 AuthErr(AuthenticationError),
19 #[error("your don't have the right permission")]
20 PermErr(AuthorizationError),
21 #[error("can't decode request")]
22 DecodeErr(reqwest::Error),
23 #[error("can't parse url")]
24 ParseUrlErr(url::ParseError),
25}
26
27/// Authentication Error that may occur when trying to access the api
28///
29/// `helloasso` will raise an [AuthenticationError](crate::AuthenticationError) {
30/// error: "unauthorized_client",
31/// error_description: "Invalid client_id '{client_id}'"
32/// } even when it is your `client_secret` witch is wrong.
33/// This behaviour is from the web api.
34#[derive(Error, Debug, Deserialize)]
35pub struct AuthenticationError {
36 pub error: String,
37 pub error_description: String,
38}
39
40impl Display for AuthenticationError {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(f, "{}: {}", self.error, self.error_description)
43 }
44}
45
46/// Authorization Error that may occur when trying to access the api
47#[derive(Error, Debug, Deserialize)]
48pub struct AuthorizationError {
49 pub message: String,
50}
51
52impl Display for AuthorizationError {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "authorization error: {}", self.message)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use crate::Error;
61 use std::error::Error as StdError;
62
63 fn error_trait_implemented<T>()
64 where
65 T: StdError,
66 {
67 }
68
69 #[test]
70 pub fn error_trait() {
71 error_trait_implemented::<Error>();
72 }
73}
74
75/*
76Note to myself:
77
78// TODO: Add test for PermErr, StatusCode::FORBIDDEN
79By implementing an endpoint and using a mocker (ie https://github.com/lipanski/mockito)
80We need to implement an endpoint first because the token url can't return a 401 or a 403
81
82Example code for AuthenticationError and AuthorizationError:
83
84StatusCode::UNAUTHORIZED => {
85 let error = response.json::<AuthorizationError>().await.map_err(|err| {
86 error!("Can't decode authentication error");
87 Error::DecodeErr(err)
88 })?;
89
90 error!("An authentication error as occur, wrong jwt");
91
92 Err(Error::AuthErr(error))
93}
94
95StatusCode::FORBIDDEN => {
96 let error = response.json::<AuthorizationError>().await.map_err(|err| {
97 error!("Can't decode authentication error");
98 Error::DecodeErr(err)
99 })?;
100
101 error!("Your JWT token hasn't the privileges or Roles for this action");
102
103 Err(Error::PermErr(error))
104}
105
106
107 */