Skip to main content

laterite_auth/
error.rs

1//! Auth error taxonomy.
2
3use laterite_core::CoreError;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum AuthError {
8    /// Username unknown, or password did not match. Deliberately does not
9    /// distinguish the two, so the response cannot be used to enumerate users.
10    #[error("invalid credentials")]
11    InvalidCredentials,
12
13    /// Too many recent failures for this identity; login is temporarily locked.
14    #[error("too many attempts")]
15    TooManyAttempts,
16
17    /// No such session, or it has expired.
18    #[error("session invalid")]
19    SessionInvalid,
20
21    /// Credentials were correct but the account is disabled.
22    #[error("account is inactive")]
23    InactiveAccount,
24
25    /// The authenticated backend user lacks the required permission.
26    #[error("permission denied: {0}")]
27    PermissionDenied(String),
28
29    /// Password hashing or verification failed at the cryptographic layer.
30    #[error("password hashing failure")]
31    PasswordHash(String),
32
33    #[error("database error")]
34    Store(#[from] sqlx::Error),
35
36    /// A stored value could not be parsed back into its Rust type (corrupt data
37    /// or a schema mismatch).
38    #[error("corrupt stored data: {0}")]
39    Data(String),
40}
41
42impl From<AuthError> for CoreError {
43    fn from(err: AuthError) -> Self {
44        match err {
45            AuthError::InvalidCredentials
46            | AuthError::TooManyAttempts
47            | AuthError::SessionInvalid => CoreError::Unauthorized,
48            AuthError::InactiveAccount => CoreError::Forbidden("account is inactive".to_string()),
49            AuthError::PermissionDenied(perm) => CoreError::Forbidden(perm),
50            AuthError::PasswordHash(msg) => CoreError::Internal(msg),
51            AuthError::Store(e) => CoreError::Database(e),
52            AuthError::Data(msg) => CoreError::Internal(msg),
53        }
54    }
55}