Skip to main content

databend_common_ast/ast/statements/
user.rs

1// Copyright 2021 Datafuse Labs
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 std::fmt::Display;
16use std::fmt::Formatter;
17
18use derive_visitor::Drive;
19use derive_visitor::DriveMut;
20
21use crate::ast::AuthType;
22use crate::ast::CreateOption;
23use crate::ast::PrincipalIdentity;
24use crate::ast::ProcedureIdentity;
25use crate::ast::ShowOptions;
26use crate::ast::UserIdentity;
27use crate::ast::UserPrivilegeType;
28use crate::ast::write_comma_separated_list;
29
30#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
31pub struct CreateUserStmt {
32    pub create_option: CreateOption,
33    pub user: UserIdentity,
34    pub auth_option: AuthOption,
35    pub user_options: Vec<UserOptionItem>,
36}
37
38impl Display for CreateUserStmt {
39    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
40        write!(f, "CREATE")?;
41        if let CreateOption::CreateOrReplace = self.create_option {
42            write!(f, " OR REPLACE")?;
43        }
44        write!(f, " USER")?;
45        if let CreateOption::CreateIfNotExists = self.create_option {
46            write!(f, " IF NOT EXISTS")?;
47        }
48        write!(f, " {} IDENTIFIED", self.user)?;
49        write!(f, " {}", self.auth_option)?;
50        if !self.user_options.is_empty() {
51            write!(f, " WITH ")?;
52            write_comma_separated_list(f, &self.user_options)?;
53        }
54
55        Ok(())
56    }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Default, Drive, DriveMut)]
60pub struct AuthOption {
61    pub auth_type: Option<AuthType>,
62    pub password: Option<String>,
63}
64
65impl Display for AuthOption {
66    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
67        if let Some(auth_type) = &self.auth_type {
68            write!(f, "WITH {auth_type} ")?;
69        }
70        if let Some(password) = &self.password {
71            write!(f, "BY '{password}'")?;
72        }
73
74        Ok(())
75    }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
79pub struct AlterUserStmt {
80    // None means current user
81    pub user: Option<UserIdentity>,
82    // None means no change to make
83    pub auth_option: Option<AuthOption>,
84    pub user_options: Vec<UserOptionItem>,
85}
86
87impl Display for AlterUserStmt {
88    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
89        write!(f, "ALTER USER")?;
90        if let Some(user) = &self.user {
91            write!(f, " {}", user)?;
92        } else {
93            write!(f, " USER()")?;
94        }
95        if let Some(auth_option) = &self.auth_option {
96            write!(f, " IDENTIFIED {}", auth_option)?;
97        }
98        if !self.user_options.is_empty() {
99            write!(f, " WITH ")?;
100            write_comma_separated_list(f, &self.user_options)?;
101        }
102
103        Ok(())
104    }
105}
106
107#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
108pub struct GrantStmt {
109    pub source: AccountMgrSource,
110    pub principal: PrincipalIdentity,
111}
112
113impl Display for GrantStmt {
114    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
115        write!(f, "GRANT")?;
116        write!(f, "{}", self.source)?;
117
118        write!(f, " TO")?;
119        write!(f, "{}", self.principal)
120    }
121}
122
123#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
124pub struct RevokeStmt {
125    pub source: AccountMgrSource,
126    pub principal: PrincipalIdentity,
127}
128
129impl Display for RevokeStmt {
130    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
131        write!(f, "REVOKE")?;
132        write!(f, "{}", self.source)?;
133
134        write!(f, " FROM")?;
135        write!(f, "{}", self.principal)
136    }
137}
138
139#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
140pub struct ShowGranteesOfRoleStmt {
141    pub name: String,
142    pub show_option: Option<ShowOptions>,
143}
144
145impl Display for ShowGranteesOfRoleStmt {
146    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
147        write!(f, "SHOW GRANTS OF ROLE {}", self.name)?;
148
149        if let Some(show_option) = &self.show_option {
150            write!(f, " {show_option}")?;
151        }
152        Ok(())
153    }
154}
155
156#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
157pub struct ShowObjectPrivilegesStmt {
158    pub object: GrantObjectName,
159    pub show_option: Option<ShowOptions>,
160}
161
162#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
163pub enum GrantObjectName {
164    Database(String),
165    Table(Option<String>, String),
166    UDF(String),
167    Stage(String),
168    Warehouse(String),
169    Connection(String),
170    Sequence(String),
171    Procedure(ProcedureIdentity),
172    MaskingPolicy(String),
173    RowAccessPolicy(String),
174}
175
176impl Display for GrantObjectName {
177    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
178        match self {
179            GrantObjectName::Database(database_name) => {
180                write!(f, "DATABASE {database_name}")
181            }
182            GrantObjectName::Table(database_name, table_name) => {
183                if let Some(database_name) = database_name {
184                    write!(f, "TABLE {database_name}.{table_name}")
185                } else {
186                    write!(f, "TABLE {table_name}")
187                }
188            }
189            GrantObjectName::UDF(udf) => write!(f, "UDF {udf}"),
190            GrantObjectName::Stage(stage) => write!(f, "STAGE {stage}"),
191            GrantObjectName::Warehouse(w) => write!(f, "WAREHOUSE {w}"),
192            GrantObjectName::Connection(c) => write!(f, "CONNECTION {c}"),
193            GrantObjectName::Sequence(s) => write!(f, "SEQUENCE {s}"),
194            GrantObjectName::Procedure(p) => write!(f, "PROCEDURE {p}"),
195            GrantObjectName::MaskingPolicy(policy) => write!(f, "MASKING POLICY {policy}"),
196            GrantObjectName::RowAccessPolicy(policy) => write!(f, "ROW ACCESS POLICY {policy}"),
197        }
198    }
199}
200
201impl Display for ShowObjectPrivilegesStmt {
202    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
203        write!(f, "SHOW GRANTS ON {}", self.object)?;
204
205        if let Some(show_option) = &self.show_option {
206            write!(f, " {show_option}")?;
207        }
208        Ok(())
209    }
210}
211
212#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
213pub enum AccountMgrSource {
214    Role {
215        role: String,
216    },
217    Privs {
218        privileges: Vec<UserPrivilegeType>,
219        level: AccountMgrLevel,
220    },
221    ALL {
222        level: AccountMgrLevel,
223    },
224}
225
226impl Display for AccountMgrSource {
227    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
228        match self {
229            AccountMgrSource::Role { role } => write!(f, " ROLE '{role}'")?,
230            AccountMgrSource::Privs { privileges, level } => {
231                if privileges.len() == 1
232                    && privileges[0] == UserPrivilegeType::ApplyMaskingPolicy
233                    && matches!(level, AccountMgrLevel::MaskingPolicy(_))
234                    && let AccountMgrLevel::MaskingPolicy(policy) = level
235                {
236                    write!(f, " APPLY ON MASKING POLICY {policy}")?;
237                    return Ok(());
238                }
239                if privileges.len() == 1
240                    && privileges[0] == UserPrivilegeType::ApplyRowAccessPolicy
241                    && matches!(level, AccountMgrLevel::RowAccessPolicy(_))
242                    && let AccountMgrLevel::RowAccessPolicy(policy) = level
243                {
244                    write!(f, " APPLY ON ROW ACCESS POLICY {policy}")?;
245                    return Ok(());
246                }
247                write!(f, " ")?;
248                write_comma_separated_list(f, privileges.iter().map(|p| p.to_string()))?;
249                write!(f, " ON")?;
250                write!(f, " {}", level)?;
251            }
252            AccountMgrSource::ALL { level, .. } => {
253                write!(f, " ALL PRIVILEGES")?;
254                write!(f, " ON")?;
255                write!(f, " {}", level)?;
256            }
257        }
258        Ok(())
259    }
260}
261
262#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
263pub enum AccountMgrLevel {
264    Global,
265    Database(Option<String>),
266    Table(Option<String>, String),
267    UDF(String),
268    Stage(String),
269    Warehouse(String),
270    Connection(String),
271    Sequence(String),
272    Procedure(ProcedureIdentity),
273    MaskingPolicy(String),
274    RowAccessPolicy(String),
275}
276
277impl Display for AccountMgrLevel {
278    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
279        match self {
280            AccountMgrLevel::Global => write!(f, " *.*"),
281            AccountMgrLevel::Database(database_name) => {
282                if let Some(database_name) = database_name {
283                    write!(f, " {database_name}.*")
284                } else {
285                    write!(f, " *")
286                }
287            }
288            AccountMgrLevel::Table(database_name, table_name) => {
289                if let Some(database_name) = database_name {
290                    write!(f, " {database_name}.{table_name}")
291                } else {
292                    write!(f, " {table_name}")
293                }
294            }
295            AccountMgrLevel::UDF(udf) => write!(f, " UDF {udf}"),
296            AccountMgrLevel::Stage(stage) => write!(f, " STAGE {stage}"),
297            AccountMgrLevel::Warehouse(w) => write!(f, " WAREHOUSE {w}"),
298            AccountMgrLevel::Connection(c) => write!(f, " CONNECTION {c}"),
299            AccountMgrLevel::Sequence(s) => write!(f, " SEQUENCE {s}"),
300            AccountMgrLevel::Procedure(p) => write!(f, " PROCEDURE {p}"),
301            AccountMgrLevel::MaskingPolicy(policy) => write!(f, " MASKING POLICY {policy}"),
302            AccountMgrLevel::RowAccessPolicy(policy) => {
303                write!(f, " ROW ACCESS POLICY {policy}")
304            }
305        }
306    }
307}
308
309#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
310pub enum SecondaryRolesOption {
311    None,
312    All,
313    SpecifyRole(Vec<String>),
314}
315
316#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
317pub enum UserOptionItem {
318    TenantSetting(bool),
319    DefaultRole(String),
320    DefaultWarehouse(String),
321    Disabled(bool),
322    SetNetworkPolicy(String),
323    UnsetNetworkPolicy,
324    SetPasswordPolicy(String),
325    UnsetPasswordPolicy,
326    MustChangePassword(bool),
327    SetWorkloadGroup(String),
328    UnsetWorkloadGroup,
329}
330
331impl Display for UserOptionItem {
332    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
333        match self {
334            UserOptionItem::TenantSetting(true) => write!(f, "TENANTSETTING"),
335            UserOptionItem::TenantSetting(false) => write!(f, "NOTENANTSETTING"),
336            UserOptionItem::DefaultRole(v) => write!(f, "DEFAULT_ROLE = '{}'", v),
337            UserOptionItem::DefaultWarehouse(v) => write!(f, "DEFAULT_WAREHOUSE = '{}'", v),
338            UserOptionItem::SetNetworkPolicy(v) => write!(f, "SET NETWORK POLICY = '{}'", v),
339            UserOptionItem::UnsetNetworkPolicy => write!(f, "UNSET NETWORK POLICY"),
340            UserOptionItem::SetPasswordPolicy(v) => write!(f, "SET PASSWORD POLICY = '{}'", v),
341            UserOptionItem::SetWorkloadGroup(v) => write!(f, "SET WORKLOAD GROUP = '{}'", v),
342            UserOptionItem::UnsetWorkloadGroup => write!(f, "UNSET WORKLOAD GROUP"),
343            UserOptionItem::UnsetPasswordPolicy => write!(f, "UNSET PASSWORD POLICY"),
344            UserOptionItem::Disabled(v) => write!(f, "DISABLED = {}", v),
345            UserOptionItem::MustChangePassword(v) => write!(f, "MUST_CHANGE_PASSWORD = {}", v),
346        }
347    }
348}