diff --git a/doc/sql/query.ebnf b/doc/sql/query.ebnf index 388dfdd1d0552c58a17ab4a25b0c68628583ebcf..6632d84c378d1b95b3f330e60e242fb8d3201091 100644 --- a/doc/sql/query.ebnf +++ b/doc/sql/query.ebnf @@ -13,6 +13,8 @@ privilege ::= (('CREATE' | 'ALTER' | 'DROP') 'USER') | ('DROP' 'ON' 'ROLE' (role | user)) | (('READ' | 'WRITE' | 'CREATE' | 'ALTER' | 'DROP') 'TABLE') | (('ALTER' | 'DROP' | 'READ' | 'WRITE') 'ON' 'TABLE'? table) + | (('CREATE' | 'EXECUTE') 'PROCEDURE') + | ('EXECUTE' 'PROCEDURE' procedure ('(' type (',' type)* ')')?) | role create_procedure ::= 'CREATE PROCEDURE' procedure '(' type (',' type)* ')' ('language' 'SQL')? (('as' '$$' body '$$') | ('begin' 'atomic' body 'end')) diff --git a/sbroad-core/src/frontend/sql.rs b/sbroad-core/src/frontend/sql.rs index bb5cd6f798ac549cd1b2c2536520711c50cc7fab..453e945ec52b04e8fdb3740c808ab3839b68dc1f 100644 --- a/sbroad-core/src/frontend/sql.rs +++ b/sbroad-core/src/frontend/sql.rs @@ -655,6 +655,15 @@ fn parse_grant_revoke( let table_name = parse_identifier(ast, *table_node_id)?; GrantRevokeType::specific_table(privilege, table_name)? } + Rule::PrivBlockProcedure => GrantRevokeType::procedure(privilege)?, + Rule::PrivBlockSpecificProcedure => { + let proc_node_id = inner_privilege_block_node.children.first().expect( + "Expected to see Name as a first child of PrivBlockSpecificProcedure", + ); + let proc_node = ast.nodes.get_node(*proc_node_id)?; + let (proc_name, proc_params) = parse_proc_with_optional_params(ast, proc_node)?; + GrantRevokeType::specific_procedure(privilege, proc_name, proc_params)? + } _ => { return Err(SbroadError::Invalid( Entity::ParseNode, diff --git a/sbroad-core/src/frontend/sql/query.pest b/sbroad-core/src/frontend/sql/query.pest index ba399ce5e3d05e8d7cbe5094ff57d979d5a9e0ee..ae0fd58c0e8e885e3352101379ef30b574e44968 100644 --- a/sbroad-core/src/frontend/sql/query.pest +++ b/sbroad-core/src/frontend/sql/query.pest @@ -30,7 +30,8 @@ ACL = _{ DropRole | DropUser | CreateRole | CreateUser | AlterUser | GrantPrivil RevokePrivilege = { ^"revoke" ~ PrivBlock ~ ^"from" ~ Identifier ~ TimeoutOption? } PrivBlock = _{ PrivBlockPrivilege | PrivBlockRolePass } PrivBlockPrivilege = {Privilege ~ (PrivBlockUser | PrivBlockSpecificUser | PrivBlockRole - | PrivBlockSpecificRole | PrivBlockTable | PrivBlockSpecificTable)} + | PrivBlockSpecificRole | PrivBlockTable | PrivBlockSpecificTable + | PrivBlockProcedure | PrivBlockSpecificProcedure)} PrivBlockUser = { ^"user" } PrivBlockSpecificUser = { ^"on" ~ ^"user" ~ Identifier } PrivBlockRole = { ^"role" } @@ -38,6 +39,8 @@ ACL = _{ DropRole | DropUser | CreateRole | CreateUser | AlterUser | GrantPrivil PrivBlockTable = { ^"table" } PrivBlockSpecificTable = { ^"on" ~ ^"table" ~ Table } PrivBlockRolePass = { Identifier } + PrivBlockProcedure = { ^"procedure" } + PrivBlockSpecificProcedure = { ^"on" ~ ^"procedure" ~ ProcWithOptionalParams } Privilege = _{ PrivilegeRead | PrivilegeWrite | PrivilegeExecute | PrivilegeCreate | PrivilegeAlter | PrivilegeDrop | PrivilegeSession | PrivilegeUsage } diff --git a/sbroad-core/src/ir/acl.rs b/sbroad-core/src/ir/acl.rs index 339c9e1d46d3134baf5c043ebef143da804f95e1..1bfb77377ec332664af239e3388b5dac04a56a14 100644 --- a/sbroad-core/src/ir/acl.rs +++ b/sbroad-core/src/ir/acl.rs @@ -2,6 +2,8 @@ use crate::ir::{Entity, Node, Plan, SbroadError}; use serde::{Deserialize, Serialize}; use tarantool::decimal::Decimal; +use super::ddl::ParamDef; + ::tarantool::define_str_enum! { /// Revoked or granted privilege. pub enum Privilege { @@ -43,6 +45,14 @@ pub enum GrantRevokeType { privilege: Privilege, table_name: String, }, + Procedure { + privilege: Privilege, + }, + SpecificProcedure { + privilege: Privilege, + proc_name: String, + proc_params: Option<Vec<ParamDef>>, + }, RolePass { role_name: String, }, @@ -131,6 +141,31 @@ impl GrantRevokeType { }) } + /// # Errors + /// - Unacceptable privilege for procedure was passed. + pub fn procedure(privilege: Privilege) -> Result<Self, SbroadError> { + check_privilege( + privilege, + &[Privilege::Create, Privilege::Drop, Privilege::Execute], + )?; + Ok(Self::Procedure { privilege }) + } + + /// # Errors + /// - Unacceptable privilege for specific procedure was passed. + pub fn specific_procedure( + privilege: Privilege, + proc_name: String, + proc_params: Option<Vec<ParamDef>>, + ) -> Result<Self, SbroadError> { + check_privilege(privilege, &[Privilege::Drop, Privilege::Execute])?; + Ok(Self::SpecificProcedure { + privilege, + proc_name, + proc_params, + }) + } + #[must_use] pub fn role_pass(role_name: String) -> Self { Self::RolePass { role_name }