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("Authentication source failure"))]
42    AuthBackend {
43        #[snafu(implicit)]
44        location: Location,
45        #[snafu(source)]
46        source: BoxedError,
47    },
48
49    #[snafu(display("User not found, username: {}", username))]
50    UserNotFound { username: String },
51
52    #[snafu(display("Unsupported password type: {}", password_type))]
53    UnsupportedPasswordType { password_type: String },
54
55    #[snafu(display("Username and password does not match, username: {}", username))]
56    UserPasswordMismatch { username: String },
57
58    #[snafu(display(
59        "Access denied for user '{}' to database '{}-{}'",
60        username,
61        catalog,
62        schema
63    ))]
64    AccessDenied {
65        catalog: String,
66        schema: String,
67        username: String,
68    },
69
70    #[snafu(display("Failed to initialize a watcher for file {}", path))]
71    FileWatch {
72        path: String,
73        #[snafu(source)]
74        error: notify::Error,
75    },
76
77    #[snafu(display("User is not authorized to perform this action"))]
78    PermissionDenied {
79        #[snafu(implicit)]
80        location: Location,
81    },
82}
83
84impl ErrorExt for Error {
85    fn status_code(&self) -> StatusCode {
86        match self {
87            Error::InvalidConfig { .. } => StatusCode::InvalidArguments,
88            Error::IllegalParam { .. } => StatusCode::InvalidArguments,
89            Error::FileWatch { .. } => StatusCode::InvalidArguments,
90            Error::InternalState { .. } => StatusCode::Unexpected,
91            Error::Io { .. } => StatusCode::StorageUnavailable,
92            Error::AuthBackend { source, .. } => source.status_code(),
93
94            Error::UserNotFound { .. } => StatusCode::UserNotFound,
95            Error::UnsupportedPasswordType { .. } => StatusCode::UnsupportedPasswordType,
96            Error::UserPasswordMismatch { .. } => StatusCode::UserPasswordMismatch,
97            Error::AccessDenied { .. } => StatusCode::AccessDenied,
98            Error::PermissionDenied { .. } => StatusCode::PermissionDenied,
99        }
100    }
101
102    fn as_any(&self) -> &dyn std::any::Any {
103        self
104    }
105}
106
107pub type Result<T> = std::result::Result<T, Error>;