Skip to content

feat: Add default role, force ALTER/CREATE USER enable planner v2 #6847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 32 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
41d94da
add default role to UserInfo
flaneur2020 Jul 27, 2022
c23c036
feat: add default_role to UserInfo and pb
flaneur2020 Jul 27, 2022
47bfa74
refactor: remove the User struct
flaneur2020 Jul 27, 2022
8d897e8
fix: add missed default_role
flaneur2020 Jul 27, 2022
e2805a6
refactor: move default_role to user option
flaneur2020 Jul 27, 2022
a2d25a0
refactor: rename role option to user option
flaneur2020 Jul 27, 2022
0a3f44b
feat: add parser for user option
flaneur2020 Jul 27, 2022
a6cebc0
test: add test about setting user options
flaneur2020 Jul 28, 2022
681e297
test: add test in parser.rs
flaneur2020 Jul 28, 2022
6016b4c
fix: parser about create/alter user with test
flaneur2020 Jul 28, 2022
3ef58ce
fix: remove planner v2 only case in unit test
flaneur2020 Jul 28, 2022
3b31945
feat: display default_role in system.users
flaneur2020 Jul 28, 2022
0e91e5d
test: add logictest about ALTER USER ... WITH
flaneur2020 Jul 28, 2022
fbc8a92
test: add a failed case
flaneur2020 Jul 28, 2022
a6603ff
Merge remote-tracking branch 'upstream/main' into add-default-role
flaneur2020 Jul 28, 2022
a9061d7
fix: error message in sqlogictest
flaneur2020 Jul 28, 2022
780eff7
feat: force ALTER USER always planner v2
flaneur2020 Jul 28, 2022
0c5723f
feat: force CREATE USER take planner v2
flaneur2020 Jul 28, 2022
193b828
fix: lint on unused code
flaneur2020 Jul 28, 2022
d9c509e
test: add test case about create user
flaneur2020 Jul 28, 2022
c9a8ac9
fix: take Option<&String> instead of &Option<String>
flaneur2020 Jul 29, 2022
9638ba0
fix: unify naming about role_option into user_option
flaneur2020 Jul 29, 2022
8afed51
fix: increase the VER to 3
flaneur2020 Jul 29, 2022
11445cf
fix: clippy
flaneur2020 Jul 29, 2022
c9cf62a
merge upstream/main
flaneur2020 Jul 29, 2022
29ce38d
fix: compat test in proto-conv
flaneur2020 Jul 29, 2022
019d543
merge upstream/main
flaneur2020 Aug 3, 2022
fe0fd2d
rm query/src/sql/statements/statement_alter_user.rs and query/src/sql…
flaneur2020 Aug 3, 2022
31cd3a3
fix: related issues in interpreter_user_alter.rs
flaneur2020 Aug 3, 2022
22eb73c
fix: add test about user_info_v3
flaneur2020 Aug 4, 2022
bc2b978
Merge remote-tracking branch 'upstream/main' into add-default-role
flaneur2020 Aug 4, 2022
09fb3c0
Merge branch 'main' into add-default-role
mergify[bot] Aug 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 23 additions & 28 deletions common/ast/src/ast/statements/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct CreateUserStmt {
pub if_not_exists: bool,
pub user: UserIdentity,
pub auth_option: AuthOption,
pub role_options: Vec<RoleOption>,
pub user_options: Vec<UserOptionItem>,
}

impl Display for CreateUserStmt {
Expand All @@ -40,10 +40,10 @@ impl Display for CreateUserStmt {
}
write!(f, " {} IDENTIFIED", self.user)?;
write!(f, " {}", self.auth_option)?;
if !self.role_options.is_empty() {
if !self.user_options.is_empty() {
write!(f, " WITH")?;
for role_option in &self.role_options {
write!(f, " {role_option}")?;
for user_option in &self.user_options {
write!(f, " {user_option}")?;
}
}

Expand Down Expand Up @@ -76,7 +76,7 @@ pub struct AlterUserStmt {
pub user: Option<UserIdentity>,
// None means no change to make
pub auth_option: Option<AuthOption>,
pub role_options: Vec<RoleOption>,
pub user_options: Vec<UserOptionItem>,
}

impl Display for AlterUserStmt {
Expand All @@ -90,9 +90,9 @@ impl Display for AlterUserStmt {
if let Some(auth_option) = &self.auth_option {
write!(f, " IDENTIFIED {}", auth_option)?;
}
if !self.role_options.is_empty() {
if !self.user_options.is_empty() {
write!(f, " WITH")?;
for with_option in &self.role_options {
for with_option in &self.user_options {
write!(f, " {with_option}")?;
}
}
Expand Down Expand Up @@ -155,28 +155,22 @@ pub enum AccountMgrLevel {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RoleOption {
TenantSetting,
NoTenantSetting,
ConfigReload,
NoConfigReload,
pub enum UserOptionItem {
TenantSetting(bool),
ConfigReload(bool),
DefaultRole(String),
}

impl RoleOption {
impl UserOptionItem {
pub fn apply(&self, option: &mut UserOption) {
match self {
Self::TenantSetting => {
option.set_option_flag(UserOptionFlag::TenantSetting);
Self::TenantSetting(enabled) => {
option.switch_option_flag(UserOptionFlag::TenantSetting, *enabled);
}
Self::NoTenantSetting => {
option.unset_option_flag(UserOptionFlag::TenantSetting);
}
Self::ConfigReload => {
option.set_option_flag(UserOptionFlag::ConfigReload);
}
Self::NoConfigReload => {
option.unset_option_flag(UserOptionFlag::ConfigReload);
Self::ConfigReload(enabled) => {
option.switch_option_flag(UserOptionFlag::ConfigReload, *enabled);
}
Self::DefaultRole(v) => option.set_default_role(Some(v.clone())),
}
}
}
Expand Down Expand Up @@ -233,13 +227,14 @@ impl Display for AccountMgrSource {
}
}

impl Display for RoleOption {
impl Display for UserOptionItem {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
RoleOption::TenantSetting => write!(f, "TENANTSETTING"),
RoleOption::NoTenantSetting => write!(f, "NOTENANTSETTING"),
RoleOption::ConfigReload => write!(f, "CONFIGRELOAD"),
RoleOption::NoConfigReload => write!(f, "NOCONFIGRELOAD"),
UserOptionItem::TenantSetting(true) => write!(f, "TENANTSETTING"),
UserOptionItem::TenantSetting(false) => write!(f, "NOTENANTSETTING"),
UserOptionItem::ConfigReload(true) => write!(f, "CONFIGRELOAD"),
UserOptionItem::ConfigReload(false) => write!(f, "NOCONFIGRELOAD"),
UserOptionItem::DefaultRole(v) => write!(f, "DEFAULT_ROLE = '{}'", v),
}
}
}
43 changes: 28 additions & 15 deletions common/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,18 +458,18 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
CREATE ~ USER ~ ( IF ~ NOT ~ EXISTS )?
~ #user_identity
~ IDENTIFIED ~ ( WITH ~ ^#auth_type )? ~ ( BY ~ ^#literal_string )?
~ ( WITH ~ ^#role_option+ )?
~ ( WITH ~ ^#comma_separated_list1(user_option))?
},
|(_, _, opt_if_not_exists, user, _, opt_auth_type, opt_password, opt_role_options)| {
|(_, _, opt_if_not_exists, user, _, opt_auth_type, opt_password, opt_user_option)| {
Statement::CreateUser(CreateUserStmt {
if_not_exists: opt_if_not_exists.is_some(),
user,
auth_option: AuthOption {
auth_type: opt_auth_type.map(|(_, auth_type)| auth_type),
password: opt_password.map(|(_, password)| password),
},
role_options: opt_role_options
.map(|(_, role_options)| role_options)
user_options: opt_user_option
.map(|(_, user_options)| user_options)
.unwrap_or_default(),
})
},
Expand All @@ -478,17 +478,17 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
rule! {
ALTER ~ USER ~ ( #map(rule! { USER ~ "(" ~ ")" }, |_| None) | #map(user_identity, Some) )
~ ( IDENTIFIED ~ ( WITH ~ ^#auth_type )? ~ ( BY ~ ^#literal_string )? )?
~ ( WITH ~ ^#role_option+ )?
~ ( WITH ~ ^#comma_separated_list1(user_option) )?
},
|(_, _, user, opt_auth_option, opt_role_options)| {
|(_, _, user, opt_auth_option, opt_user_option)| {
Statement::AlterUser(AlterUserStmt {
user,
auth_option: opt_auth_option.map(|(_, opt_auth_type, opt_password)| AuthOption {
auth_type: opt_auth_type.map(|(_, auth_type)| auth_type),
password: opt_password.map(|(_, password)| password),
}),
role_options: opt_role_options
.map(|(_, role_options)| role_options)
user_options: opt_user_option
.map(|(_, user_options)| user_options)
.unwrap_or_default(),
})
},
Expand Down Expand Up @@ -802,8 +802,8 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
),
rule!(
#show_users : "`SHOW USERS`"
| #create_user : "`CREATE USER [IF NOT EXISTS] '<username>'@'hostname' IDENTIFIED [WITH <auth_type>] [BY <password>] [WITH <role_option> ...]`"
| #alter_user : "`ALTER USER ('<username>'@'hostname' | USER()) [IDENTIFIED [WITH <auth_type>] [BY <password>]] [WITH <role_option> ...]`"
| #create_user : "`CREATE USER [IF NOT EXISTS] '<username>'@'hostname' IDENTIFIED [WITH <auth_type>] [BY <password>] [WITH <user_option>, ...]`"
| #alter_user : "`ALTER USER ('<username>'@'hostname' | USER()) [IDENTIFIED [WITH <auth_type>] [BY <password>]] [WITH <user_option>, ...]`"
| #drop_user : "`DROP USER [IF EXISTS] '<username>'@'hostname'`"
| #show_roles : "`SHOW ROLES`"
| #create_role : "`CREATE ROLE [IF NOT EXISTS] '<role_name>']`"
Expand Down Expand Up @@ -1298,12 +1298,25 @@ pub fn database_engine(i: Input) -> IResult<DatabaseEngine> {
)(i)
}

pub fn role_option(i: Input) -> IResult<RoleOption> {
pub fn user_option(i: Input) -> IResult<UserOptionItem> {
let default_role_option = map(
rule! {
"DEFAULT_ROLE" ~ "=" ~ #literal_string
},
|(_, _, role)| UserOptionItem::DefaultRole(role),
);
alt((
value(RoleOption::TenantSetting, rule! { TENANTSETTING }),
value(RoleOption::NoTenantSetting, rule! { NOTENANTSETTING }),
value(RoleOption::ConfigReload, rule! { CONFIGRELOAD }),
value(RoleOption::NoConfigReload, rule! { NOCONFIGRELOAD }),
value(UserOptionItem::TenantSetting(true), rule! { TENANTSETTING }),
value(
UserOptionItem::TenantSetting(false),
rule! { NOTENANTSETTING },
),
value(UserOptionItem::ConfigReload(true), rule! { CONFIGRELOAD }),
value(
UserOptionItem::ConfigReload(false),
rule! { NOCONFIGRELOAD },
),
default_role_option,
))(i)
}

Expand Down
4 changes: 4 additions & 0 deletions common/ast/tests/it/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ fn test_statement() {
r#"CREATE TABLE t(c1 int null, c2 bigint null, c3 varchar null);"#,
r#"CREATE TABLE t(c1 int not null, c2 bigint not null, c3 varchar not null);"#,
r#"CREATE TABLE t(c1 int default 1);"#,
r#"ALTER USER u1 IDENTIFIED BY '123456';"#,
r#"ALTER USER u1 WITH DEFAULT_ROLE = 'role1';"#,
r#"ALTER USER u1 WITH DEFAULT_ROLE = 'role1', TENANTSETTING;"#,
r#"CREATE USER u1 IDENTIFIED BY '123456' WITH DEFAULT_ROLE='role123', TENANTSETTING"#,
r#"DROP database if exists db1;"#,
r#"select distinct a, count(*) from t where a = 1 and b - 1 < a group by a having a = 1;"#,
r#"select * from t4;"#,
Expand Down
109 changes: 107 additions & 2 deletions common/ast/tests/it/testdata/statement.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1431,6 +1431,111 @@ CreateTable(
)


---------- Input ----------
ALTER USER u1 IDENTIFIED BY '123456';
---------- Output ---------
ALTER USER 'u1'@'%' IDENTIFIED BY '123456'
---------- AST ------------
AlterUser(
AlterUserStmt {
user: Some(
UserIdentity {
username: "u1",
hostname: "%",
},
),
auth_option: Some(
AuthOption {
auth_type: None,
password: Some(
"123456",
),
},
),
user_options: [],
},
)


---------- Input ----------
ALTER USER u1 WITH DEFAULT_ROLE = 'role1';
---------- Output ---------
ALTER USER 'u1'@'%' WITH DEFAULT_ROLE = 'role1'
---------- AST ------------
AlterUser(
AlterUserStmt {
user: Some(
UserIdentity {
username: "u1",
hostname: "%",
},
),
auth_option: None,
user_options: [
DefaultRole(
"role1",
),
],
},
)


---------- Input ----------
ALTER USER u1 WITH DEFAULT_ROLE = 'role1', TENANTSETTING;
---------- Output ---------
ALTER USER 'u1'@'%' WITH DEFAULT_ROLE = 'role1' TENANTSETTING
---------- AST ------------
AlterUser(
AlterUserStmt {
user: Some(
UserIdentity {
username: "u1",
hostname: "%",
},
),
auth_option: None,
user_options: [
DefaultRole(
"role1",
),
TenantSetting(
true,
),
],
},
)


---------- Input ----------
CREATE USER u1 IDENTIFIED BY '123456' WITH DEFAULT_ROLE='role123', TENANTSETTING
---------- Output ---------
CREATE USER 'u1'@'%' IDENTIFIED BY '123456' WITH DEFAULT_ROLE = 'role123' TENANTSETTING
---------- AST ------------
CreateUser(
CreateUserStmt {
if_not_exists: false,
user: UserIdentity {
username: "u1",
hostname: "%",
},
auth_option: AuthOption {
auth_type: None,
password: Some(
"123456",
),
},
user_options: [
DefaultRole(
"role123",
),
TenantSetting(
true,
),
],
},
)


---------- Input ----------
DROP database if exists db1;
---------- Output ---------
Expand Down Expand Up @@ -4554,7 +4659,7 @@ CreateUser(
"password",
),
},
role_options: [],
user_options: [],
},
)

Expand Down Expand Up @@ -4594,7 +4699,7 @@ AlterUser(
),
},
),
role_options: [],
user_options: [],
},
)

Expand Down
42 changes: 41 additions & 1 deletion common/meta/types/src/user_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,49 @@ impl TryFrom<Vec<u8>> for UserInfo {
#[serde(default)]
pub struct UserOption {
flags: BitFlags<UserOptionFlag>,

default_role: Option<String>,
}

impl UserOption {
pub fn new(flags: BitFlags<UserOptionFlag>) -> Self {
Self { flags }
Self {
flags,
default_role: None,
}
}

pub fn empty() -> Self {
Default::default()
}

pub fn with_flags(mut self, flags: BitFlags<UserOptionFlag>) -> Self {
self.flags = flags;
self
}

pub fn with_default_role(mut self, default_role: Option<String>) -> Self {
self.default_role = default_role;
self
}

pub fn with_set_flag(mut self, flag: UserOptionFlag) -> Self {
self.flags.insert(flag);
self
}

pub fn flags(&self) -> &BitFlags<UserOptionFlag> {
&self.flags
}

pub fn default_role(&self) -> Option<&String> {
self.default_role.as_ref()
}

pub fn set_default_role(&mut self, default_role: Option<String>) {
self.default_role = default_role;
}

pub fn set_all_flag(&mut self) {
self.flags = BitFlags::all();
}
Expand All @@ -113,6 +145,14 @@ impl UserOption {
self.flags.insert(flag);
}

pub fn switch_option_flag(&mut self, flag: UserOptionFlag, on: bool) {
if on {
self.flags.insert(flag);
} else {
self.flags.remove(flag);
}
}

pub fn unset_option_flag(&mut self, flag: UserOptionFlag) {
self.flags.remove(flag);
}
Expand Down
Loading