auth/
error.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use common_error::ext::{BoxedError, ErrorExt};
16use common_error::status_code::StatusCode;
17use common_macro::stack_trace_debug;
18use snafu::{Location, Snafu};
19
20#[derive(Snafu)]
21#[snafu(visibility(pub))]
22#[stack_trace_debug]
23pub enum Error {
24    #[snafu(display("Invalid config value: {}, {}", value, msg))]
25    InvalidConfig { value: String, msg: String },
26
27    #[snafu(display("Illegal param: {}", msg))]
28    IllegalParam { msg: String },
29
30    #[snafu(display("Internal state error: {}", msg))]
31    InternalState { msg: String },
32
33    #[snafu(display("IO error"))]
34    Io {
35        #[snafu(source)]
36        error: std::io::Error,
37        #[snafu(implicit)]
38        location: Location,
39    },
40
41    #[snafu(display("Failed to convert to utf8"))]
42    FromUtf8 {
43        #[snafu(source)]
44        error: std::string::FromUtf8Error,
45        #[snafu(implicit)]
46        location: Location,
47    },
48
49    #[snafu(display("Authentication source failure"))]
50    AuthBackend {
51        #[snafu(implicit)]
52        location: Location,
53        #[snafu(source)]
54        source: BoxedError,
55    },
56
57    #[snafu(display("User not found, username: {}", username))]
58    UserNotFound { username: String },
59
60    #[snafu(display("Unsupported password type: {}", password_type))]
61    UnsupportedPasswordType { password_type: String },
62
63    #[snafu(display("Username and password does not match, username: {}", username))]
64    UserPasswordMismatch { username: String },
65
66    #[snafu(display(
67        "Access denied for user '{}' to database '{}-{}'",
68        username,
69        catalog,
70        schema
71    ))]
72    AccessDenied {
73        catalog: String,
74        schema: String,
75        username: String,
76    },
77
78    #[snafu(display("Failed to initialize a watcher for file {}", path))]
79    FileWatch {
80        path: String,
81        #[snafu(source)]
82        error: notify::Error,
83    },
84
85    #[snafu(display("User is not authorized to perform this action"))]
86    PermissionDenied {
87        #[snafu(implicit)]
88        location: Location,
89    },
90}
91
92impl ErrorExt for Error {
93    fn status_code(&self) -> StatusCode {
94        match self {
95            Error::InvalidConfig { .. } => StatusCode::InvalidArguments,
96            Error::IllegalParam { .. } | Error::FromUtf8 { .. } => StatusCode::InvalidArguments,
97            Error::FileWatch { .. } => StatusCode::InvalidArguments,
98            Error::InternalState { .. } => StatusCode::Unexpected,
99            Error::Io { .. } => StatusCode::StorageUnavailable,
100            Error::AuthBackend { source, .. } => source.status_code(),
101
102            Error::UserNotFound { .. } => StatusCode::UserNotFound,
103            Error::UnsupportedPasswordType { .. } => StatusCode::UnsupportedPasswordType,
104            Error::UserPasswordMismatch { .. } => StatusCode::UserPasswordMismatch,
105            Error::AccessDenied { .. } => StatusCode::AccessDenied,
106            Error::PermissionDenied { .. } => StatusCode::PermissionDenied,
107        }
108    }
109
110    fn as_any(&self) -> &dyn std::any::Any {
111        self
112    }
113}
114
115pub type Result<T> = std::result::Result<T, Error>;