Skip to content

Commit e582dde

Browse files
authored
chore(query): add function current_available_roles and current_secondary_roles (#18290)
1 parent 6d6e573 commit e582dde

File tree

11 files changed

+89
-5
lines changed

11 files changed

+89
-5
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/query/catalog/src/table_context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ pub trait TableContext: Send + Sync {
214214
fn get_current_database(&self) -> String;
215215
fn get_current_user(&self) -> Result<UserInfo>;
216216
fn get_current_role(&self) -> Option<RoleInfo>;
217+
fn get_secondary_roles(&self) -> Option<Vec<String>>;
217218
fn get_current_session_id(&self) -> String {
218219
unimplemented!()
219220
}

src/query/service/src/sessions/query_ctx.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,11 @@ impl TableContext for QueryContext {
881881
fn get_current_role(&self) -> Option<RoleInfo> {
882882
self.shared.get_current_role()
883883
}
884+
885+
fn get_secondary_roles(&self) -> Option<Vec<String>> {
886+
self.shared.get_secondary_roles()
887+
}
888+
884889
async fn get_all_available_roles(&self) -> Result<Vec<RoleInfo>> {
885890
self.get_current_session().get_all_available_roles().await
886891
}

src/query/service/src/sessions/query_ctx_shared.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,10 @@ impl QueryContextShared {
434434
self.session.get_current_role()
435435
}
436436

437+
pub fn get_secondary_roles(&self) -> Option<Vec<String>> {
438+
self.session.get_secondary_roles()
439+
}
440+
437441
/// Get all tables that already attached in this query.
438442
pub fn get_tables_refs(&self) -> Vec<Arc<dyn Table>> {
439443
let tables = self.tables_refs.lock();

src/query/service/tests/it/sql/exec/get_table_bind_test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,9 @@ impl TableContext for CtxDelegation {
661661
fn get_current_role(&self) -> Option<RoleInfo> {
662662
todo!()
663663
}
664+
fn get_secondary_roles(&self) -> Option<Vec<String>> {
665+
todo!()
666+
}
664667
async fn get_all_available_roles(&self) -> Result<Vec<RoleInfo>> {
665668
todo!()
666669
}

src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/equivalent_constants_visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use databend_query::sessions::QueryContext;
3333
use databend_query::test_kits::TestFixture;
3434
use parking_lot::RwLock;
3535

36-
#[tokio::test]
36+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
3737
async fn test_equivalent_constants() -> Result<()> {
3838
let fixture = TestFixture::setup().await?;
3939
let ctx = fixture.new_query_ctx().await?;

src/query/service/tests/it/storages/fuse/operations/commit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ impl TableContext for CtxDelegation {
573573
fn get_current_role(&self) -> Option<RoleInfo> {
574574
todo!()
575575
}
576+
fn get_secondary_roles(&self) -> Option<Vec<String>> {
577+
todo!()
578+
}
576579
async fn get_all_available_roles(&self) -> Result<Vec<RoleInfo>> {
577580
todo!()
578581
}

src/query/sql/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ recursive = { workspace = true }
6767
regex = { workspace = true }
6868
roaring = { workspace = true }
6969
serde = { workspace = true }
70+
serde_json = { workspace = true }
7071
sha2 = { workspace = true }
7172
similar = { workspace = true }
7273
simsearch = { workspace = true }

src/query/sql/src/planner/semantic/type_check.rs

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ use itertools::Itertools;
118118
use jsonb::keypath::parse_key_paths;
119119
use jsonb::keypath::KeyPath;
120120
use jsonb::keypath::KeyPaths;
121+
use serde_json::json;
122+
use serde_json::to_string;
121123
use simsearch::SimSearch;
122124
use unicase::Ascii;
123125

@@ -2871,9 +2873,9 @@ impl<'a> TypeChecker<'a> {
28712873
arguments: &[&Expr],
28722874
) -> Result<Box<(ScalarExpr, DataType)>> {
28732875
// Check if current function is a virtual function, e.g. `database`, `version`
2874-
if let Some(rewritten_func_result) =
2875-
self.try_rewrite_sugar_function(span, func_name, arguments)
2876-
{
2876+
if let Some(rewritten_func_result) = databend_common_base::runtime::block_on(
2877+
self.try_rewrite_sugar_function(span, func_name, arguments),
2878+
) {
28772879
return rewritten_func_result;
28782880
}
28792881

@@ -3610,6 +3612,8 @@ impl<'a> TypeChecker<'a> {
36103612
Ascii::new("currentuser"),
36113613
Ascii::new("current_user"),
36123614
Ascii::new("current_role"),
3615+
Ascii::new("current_secondary_roles"),
3616+
Ascii::new("current_available_roles"),
36133617
Ascii::new("connection_id"),
36143618
Ascii::new("timezone"),
36153619
Ascii::new("nullif"),
@@ -3637,7 +3641,7 @@ impl<'a> TypeChecker<'a> {
36373641
FUNCTIONS
36383642
}
36393643

3640-
fn try_rewrite_sugar_function(
3644+
async fn try_rewrite_sugar_function(
36413645
&mut self,
36423646
span: Span,
36433647
func_name: &str,
@@ -3676,6 +3680,60 @@ impl<'a> TypeChecker<'a> {
36763680
),
36773681
}),
36783682
),
3683+
("current_secondary_roles", &[]) => {
3684+
let mut res = self
3685+
.ctx
3686+
.get_all_effective_roles()
3687+
.await
3688+
.unwrap_or_default()
3689+
.iter()
3690+
.map(|r| r.name.clone())
3691+
.collect::<Vec<String>>();
3692+
res.sort();
3693+
let roles_comma_separated_string = res.iter().join(",");
3694+
let res = if self.ctx.get_secondary_roles().is_none() {
3695+
json!({
3696+
"roles": roles_comma_separated_string,
3697+
"value": "ALL"
3698+
})
3699+
} else {
3700+
json!({
3701+
"roles": roles_comma_separated_string,
3702+
"value": "None"
3703+
})
3704+
};
3705+
match to_string(&res) {
3706+
Ok(res) => Some(self.resolve(&Expr::Literal {
3707+
span,
3708+
value: Literal::String(res),
3709+
})),
3710+
Err(e) => Some(Err(ErrorCode::IllegalRole(format!(
3711+
"Failed to serialize secondary roles into JSON string: {}",
3712+
e
3713+
)))),
3714+
}
3715+
}
3716+
("current_available_roles", &[]) => {
3717+
let mut res = self
3718+
.ctx
3719+
.get_all_available_roles()
3720+
.await
3721+
.unwrap_or_default()
3722+
.iter()
3723+
.map(|r| r.name.clone())
3724+
.collect::<Vec<String>>();
3725+
res.sort();
3726+
match to_string(&res) {
3727+
Ok(res) => Some(self.resolve(&Expr::Literal {
3728+
span,
3729+
value: Literal::String(res),
3730+
})),
3731+
Err(e) => Some(Err(ErrorCode::IllegalRole(format!(
3732+
"Failed to serialize available roles into JSON string: {}",
3733+
e
3734+
)))),
3735+
}
3736+
}
36793737
("connection_id", &[]) => Some(self.resolve(&Expr::Literal {
36803738
span,
36813739
value: Literal::String(self.ctx.get_connection_id()),

tests/suites/0_stateless/18_rbac/18_0009_set_role.result

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@ Error: APIError: QueryFailed: [1063]Permission denied: privilege [Insert] is req
1414
0
1515
-- test 5: set role as testrole3, secondary roles as NONE, can access table2, can not access table1, because role3 inherited from role2
1616
Error: APIError: QueryFailed: [1063]Permission denied: privilege [Insert] is required on 'default'.'default'.'t20_0015_table1' for user 'testuser1'@'%' with roles [testrole3,public,testrole2]
17+
"{""roles"":""public"",""value"":""None""}"
18+
"[""public"",""testrole1"",""testrole2"",""testrole3""]"
1719
0
1820
-- test 6: set role as testrole1, secondary roles as ALL, can access both table1 and table2
1921
0
22+
"{""roles"":""public,testrole1,testrole2,testrole3"",""value"":""ALL""}"
23+
"[""public"",""testrole1"",""testrole2"",""testrole3""]"
2024
0
2125
-- test 7: set role as testrole1, testrole2, secondary roles defaults as ALL, can both table1 and table2
2226
0

0 commit comments

Comments
 (0)