Skip to content

Commit

Permalink
migrate revoke to planner v2
Browse files Browse the repository at this point in the history
  • Loading branch information
TCeason committed Jun 20, 2022
1 parent be7f251 commit 19ce575
Show file tree
Hide file tree
Showing 21 changed files with 562 additions and 309 deletions.
120 changes: 85 additions & 35 deletions common/ast/src/ast/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,7 @@ pub enum Statement<'a> {
// User
ShowUsers,
CreateUser(CreateUserStmt),
AlterUser {
// None means current user
user: Option<UserIdentity>,
// None means no change to make
auth_option: Option<AuthOption>,
role_options: Vec<RoleOption>,
},
AlterUser(AlterUserStmt),
DropUser {
if_exists: bool,
user: UserIdentity,
Expand All @@ -121,10 +115,11 @@ pub enum Statement<'a> {
if_exists: bool,
role_name: String,
},
Grant(GrantStatement),
Grant(AccountMgrStatement),
ShowGrants {
principal: Option<PrincipalIdentity>,
},
Revoke(AccountMgrStatement),

// UDF
CreateUDF {
Expand Down Expand Up @@ -458,6 +453,15 @@ pub struct CreateUserStmt {
pub role_options: Vec<RoleOption>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct AlterUserStmt {
// None means current user
pub user: Option<UserIdentity>,
// None means no change to make
pub auth_option: Option<AuthOption>,
pub role_options: Vec<RoleOption>,
}

#[derive(Debug, Clone, PartialEq, Default)]
pub struct AuthOption {
pub auth_type: Option<AuthType>,
Expand All @@ -473,27 +477,27 @@ pub enum RoleOption {
}

#[derive(Debug, Clone, PartialEq)]
pub struct GrantStatement {
pub source: GrantSource,
pub struct AccountMgrStatement {
pub source: AccountMgrSource,
pub principal: PrincipalIdentity,
}

#[derive(Debug, Clone, PartialEq)]
pub enum GrantSource {
pub enum AccountMgrSource {
Role {
role: String,
},
Privs {
privileges: Vec<UserPrivilegeType>,
level: GrantLevel,
level: AccountMgrLevel,
},
ALL {
level: GrantLevel,
level: AccountMgrLevel,
},
}

#[derive(Debug, Clone, PartialEq)]
pub enum GrantLevel {
pub enum AccountMgrLevel {
Global,
Database(Option<String>),
Table(Option<String>, String),
Expand Down Expand Up @@ -1014,11 +1018,11 @@ impl<'a> Display for Statement<'a> {
}
}
}
Statement::AlterUser {
Statement::AlterUser(AlterUserStmt {
user,
auth_option,
role_options,
} => {
}) => {
write!(f, "ALTER USER")?;
if let Some(user) = user {
write!(f, " {user}")?;
Expand Down Expand Up @@ -1068,48 +1072,43 @@ impl<'a> Display for Statement<'a> {
}
write!(f, " '{role}'")?;
}
Statement::Grant(GrantStatement { source, principal }) => {
Statement::Grant(AccountMgrStatement { source, principal }) => {
write!(f, "GRANT")?;
match source {
GrantSource::Role { role } => write!(f, " ROLE {role}")?,
GrantSource::Privs { privileges, level } => {
write!(
f,
" {}",
privileges
.iter()
.map(|p| p.to_string())
.collect::<Vec<_>>()
.join(", ")
)?;
AccountMgrSource::Role { role } => write!(f, " ROLE {role}")?,
AccountMgrSource::Privs { privileges, level } => {
write!(f, " ")?;
write_comma_separated_list(f, privileges.iter().map(|p| p.to_string()))?;
write!(f, " ON")?;
match level {
GrantLevel::Global => write!(f, " *.*")?,
GrantLevel::Database(database_name) => {
AccountMgrLevel::Global => write!(f, " *.*")?,
AccountMgrLevel::Database(database_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.*")?;
} else {
write!(f, " *")?;
}
}
GrantLevel::Table(database_name, table_name) => {
AccountMgrLevel::Table(database_name, table_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.{table_name}")?;
}
}
}
}
GrantSource::ALL { level, .. } => {
AccountMgrSource::ALL { level, .. } => {
write!(f, " ALL PRIVILEGES")?;
write!(f, " ON")?;
match level {
GrantLevel::Global => write!(f, " *.*")?,
GrantLevel::Database(database_name) => {
AccountMgrLevel::Global => write!(f, " *.*")?,
AccountMgrLevel::Database(database_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.*")?;
} else {
write!(f, " *")?;
}
}
GrantLevel::Table(database_name, table_name) => {
AccountMgrLevel::Table(database_name, table_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.{table_name}")?;
}
Expand All @@ -1134,6 +1133,57 @@ impl<'a> Display for Statement<'a> {
}
}
}
Statement::Revoke(AccountMgrStatement { source, principal }) => {
write!(f, "REVOKE")?;
match source {
AccountMgrSource::Role { role } => write!(f, " ROLE {role}")?,
AccountMgrSource::Privs { privileges, level } => {
write!(f, " ")?;
write_comma_separated_list(f, privileges.iter().map(|p| p.to_string()))?;
write!(f, " ON")?;
match level {
AccountMgrLevel::Global => write!(f, " *.*")?,
AccountMgrLevel::Database(database_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.*")?;
} else {
write!(f, " *")?;
}
}
AccountMgrLevel::Table(database_name, table_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.{table_name}")?;
}
}
}
}
AccountMgrSource::ALL { level, .. } => {
write!(f, " ALL PRIVILEGES")?;
write!(f, " ON")?;
match level {
AccountMgrLevel::Global => write!(f, " *.*")?,
AccountMgrLevel::Database(database_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.*")?;
} else {
write!(f, " *")?;
}
}
AccountMgrLevel::Table(database_name, table_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.{table_name}")?;
}
}
}
}
}

write!(f, " FROM")?;
match principal {
PrincipalIdentity::User(user) => write!(f, " USER {user}")?,
PrincipalIdentity::Role(role) => write!(f, " ROLE {role}")?,
}
}
Statement::CreateUDF {
if_not_exists,
udf_name,
Expand Down
55 changes: 35 additions & 20 deletions common/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,15 +395,17 @@ pub fn statement(i: Input) -> IResult<Statement> {
~ ( IDENTIFIED ~ ( WITH ~ ^#auth_type )? ~ ( BY ~ ^#literal_string )? )?
~ ( WITH ~ ^#role_option+ )?
},
|(_, _, user, opt_auth_option, opt_role_options)| Statement::AlterUser {
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)
.unwrap_or_default(),
|(_, _, user, opt_auth_option, opt_role_options)| {
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)
.unwrap_or_default(),
})
},
);
let drop_user = map(
Expand Down Expand Up @@ -434,12 +436,12 @@ pub fn statement(i: Input) -> IResult<Statement> {
role_name,
},
);
let grant_priv = map(
let grant = map(
rule! {
GRANT ~ #grant_source ~ TO ~ #grant_option
},
|(_, source, _, grant_option)| {
Statement::Grant(GrantStatement {
Statement::Grant(AccountMgrStatement {
source,
principal: grant_option,
})
Expand All @@ -453,6 +455,17 @@ pub fn statement(i: Input) -> IResult<Statement> {
principal: opt_principal.map(|(_, principal)| principal),
},
);
let revoke = map(
rule! {
REVOKE ~ #grant_source ~ FROM ~ #grant_option
},
|(_, source, _, grant_option)| {
Statement::Revoke(AccountMgrStatement {
source,
principal: grant_option,
})
},
);
let create_udf = map(
rule! {
CREATE ~ FUNCTION ~ ( IF ~ NOT ~ EXISTS )?
Expand Down Expand Up @@ -663,8 +676,10 @@ pub fn statement(i: Input) -> IResult<Statement> {
| #drop_stage: "`DROP STAGE <stage_name>`"
),
rule!(
#grant_priv : "`GRANT { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } TO { [ROLE <role_name>] | [USER] <user> }`"
#grant : "`GRANT { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } TO { [ROLE <role_name>] | [USER] <user> }`"
| #show_grants : "`SHOW GRANTS [FOR { ROLE <role_name> | [USER] <user> }]`"
| #revoke : "`REVOKE { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } FROM { [ROLE <role_name>] | [USER] <user> }`"

),
));

Expand Down Expand Up @@ -768,25 +783,25 @@ pub fn column_def(i: Input) -> IResult<ColumnDefinition> {
)(i)
}

pub fn grant_source(i: Input) -> IResult<GrantSource> {
pub fn grant_source(i: Input) -> IResult<AccountMgrSource> {
let role = map(
rule! {
ROLE ~ #literal_string
},
|(_, role_name)| GrantSource::Role { role: role_name },
|(_, role_name)| AccountMgrSource::Role { role: role_name },
);
let privs = map(
rule! {
#comma_separated_list1(priv_type) ~ ON ~ #grant_level
},
|(privs, _, level)| GrantSource::Privs {
|(privs, _, level)| AccountMgrSource::Privs {
privileges: privs,
level,
},
);
let all = map(
rule! { ALL ~ PRIVILEGES? ~ ON ~ #grant_level },
|(_, _, _, level)| GrantSource::ALL { level },
|(_, _, _, level)| AccountMgrSource::ALL { level },
);

rule!(
Expand Down Expand Up @@ -815,24 +830,24 @@ pub fn priv_type(i: Input) -> IResult<UserPrivilegeType> {
))(i)
}

pub fn grant_level(i: Input) -> IResult<GrantLevel> {
pub fn grant_level(i: Input) -> IResult<AccountMgrLevel> {
// *.*
let global = map(rule! { "*" ~ "." ~ "*" }, |_| GrantLevel::Global);
let global = map(rule! { "*" ~ "." ~ "*" }, |_| AccountMgrLevel::Global);
// db.*
// "*": as current db or "table" with current db
let db = map(
rule! {
( #ident ~ "." )? ~ "*"
},
|(database, _)| GrantLevel::Database(database.map(|(database, _)| database.name)),
|(database, _)| AccountMgrLevel::Database(database.map(|(database, _)| database.name)),
);
// db.table
let table = map(
rule! {
( #ident ~ "." )? ~ #ident
},
|(database, table)| {
GrantLevel::Table(database.map(|(database, _)| database.name), table.name)
AccountMgrLevel::Table(database.map(|(database, _)| database.name), table.name)
},
);

Expand Down
2 changes: 2 additions & 0 deletions common/ast/src/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,8 @@ pub enum TokenKind {
PRIVILEGES,
#[token("REMOVE", ignore(ascii_case))]
REMOVE,
#[token("REVOKE", ignore(ascii_case))]
REVOKE,
#[token("GRANTS", ignore(ascii_case))]
GRANTS,
#[token("RIGHT", ignore(ascii_case))]
Expand Down
3 changes: 3 additions & 0 deletions common/ast/tests/it/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ fn test_statement() {
r#"SHOW GRANTS FOR 'test-grant'@'localhost';"#,
r#"SHOW GRANTS FOR USER 'test-grant'@'localhost';"#,
r#"SHOW GRANTS FOR ROLE 'role1';"#,
r#"REVOKE SELECT, CREATE ON * FROM 'test-grant'@'localhost';"#,
];

for case in cases {
Expand Down Expand Up @@ -187,6 +188,8 @@ fn test_statement_error() {
r#"GRANT SELECT, ALL PRIVILEGES, CREATE ON * TO 'test-grant'@'localhost';"#,
r#"GRANT SELECT, CREATE ON *.c TO 'test-grant'@'localhost';"#,
r#"SHOW GRANT FOR ROLE role1;"#,
r#"REVOKE SELECT, CREATE, ALL PRIVILEGES ON * FROM 'test-grant'@'localhost';"#,
r#"REVOKE SELECT, CREATE ON * TO 'test-grant'@'localhost';"#,
];

for case in cases {
Expand Down
25 changes: 25 additions & 0 deletions common/ast/tests/it/testdata/statement-error.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,28 @@ error:
| ^^^^^ expected `SETTINGS`, `STAGES`, `PROCESSLIST`, `METRICS`, `FUNCTIONS`, `DATABASES`, or 8 more ...


---------- Input ----------
REVOKE SELECT, CREATE, ALL PRIVILEGES ON * FROM 'test-grant'@'localhost';
---------- Output ---------
error:
--> SQL:1:24
|
1 | REVOKE SELECT, CREATE, ALL PRIVILEGES ON * FROM 'test-grant'@'localhost';
| ------ ------ ^^^ expected `USAGE`, `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `CREATE`, or 5 more ...
| | |
| | while parsing <privileges> ON <privileges_level>
| while parsing `REVOKE { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } FROM { [ROLE <role_name>] | [USER] <user> }`


---------- Input ----------
REVOKE SELECT, CREATE ON * TO 'test-grant'@'localhost';
---------- Output ---------
error:
--> SQL:1:28
|
1 | REVOKE SELECT, CREATE ON * TO 'test-grant'@'localhost';
| ------ ^^ expected `FROM` or `.`
| |
| while parsing `REVOKE { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } FROM { [ROLE <role_name>] | [USER] <user> }`


Loading

0 comments on commit 19ce575

Please sign in to comment.