1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use actix_web::http::StatusCode;
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Indicates that the user is authenticated but cannot continue until they
/// verify their email address. This can happen if a user registers a new
/// account with a password, then uses their password to log in before
/// completing the email verification challenge.
#[error("Email address is not verified")]
EmailNotVerified,
/// Indicates that the user tried to complete an email challenge, but the
/// code in their challenge link is not correct. The challenge might
/// already have been completed, or expired, or it never existed.
#[error("Incorrect challenge code")]
IncorrectChallengeCode,
/// Indicates that the user is not authenticated in a context where they
/// need to be.
#[error("User is not authenticated")]
NotAuthenticated,
/// Indicates that the user is authenticated but cannot continue until they
/// choose a new password. This can happen if a new user is created with a
/// temporary password, or the user completed a password reset challenge.
#[error("User is required to change their password")]
RequirePasswordChange,
/// Indicates that the user is authenticated but cannot continue, because
/// their account has been suspended.
#[error("User is suspended")]
UserIsSuspended,
/// Internal error which occurs when an authenticated user attempts to
/// reauthenticate, but when `AppDb::get_user_data_by_id` was called to
/// fetch the user's password, no record was returned.
///
/// This either indicates a logic error in your `AppDb` implementation, or
/// a race condition in which the user is deleted after the session cookie
/// is verified but before the reauthentication is checked.
#[error("User data query failed for id = {user_id}")]
UserDataQueryFailed {user_id: i64},
/// Internal error which occurs when serializing or deserializing challenge
/// data.
#[error("Corrupted challenge data")]
Serde(#[source] serde_json::Error),
/// Internal error which occurs when hashing a new password.
#[error("Failed to generate new password hash")]
NewPasswordHash(#[source] password_hash::Error),
/// Internal error which occurs when verifying a password. This could
/// indicate, for example, that a hash stored in the database is in the
/// wrong format, or uses an unsupported algorithm.
#[error("Failed to parse stored password hash")]
StoredPasswordHash(#[source] password_hash::phc::Error),
}
impl Error {
pub fn status_code(&self) -> StatusCode {
match self {
Self::UserIsSuspended
| Self::IncorrectChallengeCode
| Self::EmailNotVerified
| Self::RequirePasswordChange
| Self::NotAuthenticated => StatusCode::UNAUTHORIZED,
Self::UserDataQueryFailed {..}
| Self::NewPasswordHash(_)
| Self::StoredPasswordHash(_)
| Self::Serde(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
pub(crate) fn as_app_err<T, E: From<Self>>(self) -> Result<T, E> {
Err(E::from(self))
}
}