Skip to content
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

feat(planner): migrate revoke to planner v2 #6066

Merged
merged 1 commit into from
Jun 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
155 changes: 83 additions & 72 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 @@ -564,6 +568,58 @@ impl Display for TableOption {
}
}

impl Display for AccountMgrSource {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
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}")?;
} else {
write!(f, " {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}")?;
} else {
write!(f, " {table_name}")?;
}
}
}
}
}
Ok(())
}
}

impl Display for DatabaseEngine {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if let DatabaseEngine::Github(token) = self {
Expand Down Expand Up @@ -1014,11 +1070,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,72 +1124,27 @@ 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(", ")
)?;
write!(f, " ON")?;
match level {
GrantLevel::Global => write!(f, " *.*")?,
GrantLevel::Database(database_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.*")?;
}
}
GrantLevel::Table(database_name, table_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.{table_name}")?;
}
}
}
}
GrantSource::ALL { level, .. } => {
write!(f, " ALL PRIVILEGES")?;
write!(f, " ON")?;
match level {
GrantLevel::Global => write!(f, " *.*")?,
GrantLevel::Database(database_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.*")?;
} else {
write!(f, " *")?;
}
}
GrantLevel::Table(database_name, table_name) => {
if let Some(database_name) = database_name {
write!(f, " {database_name}.{table_name}")?;
}
}
}
}
}
write!(f, "{source}")?;

write!(f, " TO")?;
match principal {
PrincipalIdentity::User(user) => write!(f, " USER {user}")?,
PrincipalIdentity::Role(role) => write!(f, " ROLE {role}")?,
}
write!(f, "{principal}")?;
}
Statement::ShowGrants { principal } => {
write!(f, "SHOW GRANTS")?;
if let Some(principal) = principal {
write!(f, " FOR")?;
match principal {
PrincipalIdentity::User(user) => write!(f, " USER {user}")?,
PrincipalIdentity::Role(role) => write!(f, " ROLE {role}")?,
}
write!(f, "{principal}")?;
}
}
Statement::Revoke(AccountMgrStatement { source, principal }) => {
write!(f, "REVOKE")?;
write!(f, "{source}")?;

write!(f, " FROM")?;
write!(f, "{principal}")?;
}
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
7 changes: 7 additions & 0 deletions common/ast/tests/it/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,15 @@ fn test_statement() {
r#"GRANT SELECT ON db01.tb1 TO 'test-grant'@'localhost';"#,
r#"GRANT SELECT ON db01.tb1 TO USER 'test-grant'@'localhost';"#,
r#"GRANT SELECT ON db01.tb1 TO ROLE 'role1';"#,
r#"GRANT SELECT ON tb1 TO ROLE 'role1';"#,
r#"GRANT ALL ON tb1 TO 'u1';"#,
r#"SHOW GRANTS;"#,
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';"#,
r#"REVOKE SELECT ON tb1 FROM ROLE 'role1';"#,
r#"REVOKE ALL ON tb1 FROM 'u1';"#,
];

for case in cases {
Expand Down Expand Up @@ -187,6 +192,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
Loading