From 351ed3d227b1b4359d09a25675942e4c0abf0b40 Mon Sep 17 00:00:00 2001 From: taichong Date: Wed, 20 Dec 2023 14:37:56 +0800 Subject: [PATCH] add GrantObject::Table/DatabaseById meta proto test --- src/meta/proto-conv/src/util.rs | 1 + src/meta/proto-conv/tests/it/main.rs | 2 + .../proto-conv/tests/it/v063_connection.rs | 4 +- .../proto-conv/tests/it/v068_user_grant_id.rs | 68 +++++++++++++++++++ .../interpreters/access/privilege_access.rs | 18 +++-- 5 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 src/meta/proto-conv/tests/it/v068_user_grant_id.rs diff --git a/src/meta/proto-conv/src/util.rs b/src/meta/proto-conv/src/util.rs index b69d88460e4b..fb54160b6abb 100644 --- a/src/meta/proto-conv/src/util.rs +++ b/src/meta/proto-conv/src/util.rs @@ -97,6 +97,7 @@ const META_CHANGE_LOG: &[(u64, &str)] = &[ (65, "2023-11-16: Retype: use Datetime instead of u64 to in lvt.time", ), (66, "2023-12-15: Add: stage.proto/StageInfo::created_on", ), (67, "2023-12-19: Add: user.proto/PasswordPolicy and UserOption::password_policy", ), + (68, "2023-12-20: Add: user.proto/GrantTableIdObject and GrantDatabaseIdObject", ), // Dear developer: // If you're gonna add a new metadata version, you'll have to add a test for it. // You could just copy an existing test file(e.g., `../tests/it/v024_table_meta.rs`) diff --git a/src/meta/proto-conv/tests/it/main.rs b/src/meta/proto-conv/tests/it/main.rs index 90ace4942797..07a17943fb60 100644 --- a/src/meta/proto-conv/tests/it/main.rs +++ b/src/meta/proto-conv/tests/it/main.rs @@ -70,4 +70,6 @@ mod v063_connection; mod v064_ndjson_format_params; mod v065_least_visible_time; mod v066_stage_create_on; + mod v067_password_policy; +mod v068_user_grant_id; diff --git a/src/meta/proto-conv/tests/it/v063_connection.rs b/src/meta/proto-conv/tests/it/v063_connection.rs index 038b581014a3..bea52c56b1e2 100644 --- a/src/meta/proto-conv/tests/it/v063_connection.rs +++ b/src/meta/proto-conv/tests/it/v063_connection.rs @@ -32,7 +32,7 @@ use crate::common; fn test_decode_v62_connection() -> anyhow::Result<()> { let user_defined_connection_v62 = vec![ 10, 7, 109, 121, 95, 99, 111, 110, 110, 18, 2, 115, 51, 26, 10, 10, 3, 107, 101, 121, 18, - 3, 118, 97, 108, 160, 6, 62, 168, 6, 24, + 3, 118, 97, 108, 160, 6, 63, 168, 6, 24, ]; let want = || UserDefinedConnection { name: "my_conn".to_string(), @@ -43,7 +43,7 @@ fn test_decode_v62_connection() -> anyhow::Result<()> { common::test_load_old( func_name!(), user_defined_connection_v62.as_slice(), - 62, + 63, want(), )?; Ok(()) diff --git a/src/meta/proto-conv/tests/it/v068_user_grant_id.rs b/src/meta/proto-conv/tests/it/v068_user_grant_id.rs new file mode 100644 index 000000000000..24eadcd1d634 --- /dev/null +++ b/src/meta/proto-conv/tests/it/v068_user_grant_id.rs @@ -0,0 +1,68 @@ +// Copyright 2023 Datafuse Labs. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::collections::HashSet; + +use databend_common_meta_app as mt; +use databend_common_meta_app::principal::UserGrantSet; +use databend_common_meta_app::principal::UserPrivilegeType; +use enumflags2::make_bitflags; +use minitrace::func_name; + +use crate::common; + +// These bytes are built when a new version in introduced, +// and are kept for backward compatibility test. +// +// ************************************************************* +// * These messages should never be updated, * +// * only be added when a new version is added, * +// * or be removed when an old version is no longer supported. * +// ************************************************************* +// +// The user_info_v67 bytes are built from the output of `test_pb_from_to()` +#[test] +fn test_decode_v68_user() -> anyhow::Result<()> { + let user_info_v68 = vec![ + 10, 2, 117, 49, 18, 1, 37, 26, 8, 10, 0, 160, 6, 68, 168, 6, 24, 34, 70, 10, 31, 10, 21, + 58, 13, 10, 7, 100, 101, 102, 97, 117, 108, 116, 16, 1, 24, 10, 160, 6, 68, 168, 6, 24, 16, + 4, 160, 6, 68, 168, 6, 24, 10, 29, 10, 19, 50, 11, 10, 7, 100, 101, 102, 97, 117, 108, 116, + 16, 1, 160, 6, 68, 168, 6, 24, 16, 2, 160, 6, 68, 168, 6, 24, 160, 6, 68, 168, 6, 24, 42, + 6, 160, 6, 68, 168, 6, 24, 50, 6, 160, 6, 68, 168, 6, 24, 160, 6, 68, 168, 6, 24, + ]; + let want = || mt::principal::UserInfo { + name: "u1".to_string(), + hostname: "%".to_string(), + auth_info: Default::default(), + grants: UserGrantSet::new( + vec![ + mt::principal::GrantEntry::new( + mt::principal::GrantObject::TableById("default".to_string(), 1, 10), + make_bitflags!(UserPrivilegeType::{Select}), + ), + mt::principal::GrantEntry::new( + mt::principal::GrantObject::DatabaseById("default".to_string(), 1), + make_bitflags!(UserPrivilegeType::{Create}), + ), + ], + HashSet::new(), + ), + quota: Default::default(), + option: Default::default(), + }; + common::test_pb_from_to(func_name!(), want())?; + common::test_load_old(func_name!(), user_info_v68.as_slice(), 68, want())?; + + Ok(()) +} diff --git a/src/query/service/src/interpreters/access/privilege_access.rs b/src/query/service/src/interpreters/access/privilege_access.rs index 31563859abd8..26953dda9b15 100644 --- a/src/query/service/src/interpreters/access/privilege_access.rs +++ b/src/query/service/src/interpreters/access/privilege_access.rs @@ -214,7 +214,7 @@ impl PrivilegeAccess { match object { GrantObject::Database(_, db_name) => { - if db_name == "information_schema" + if db_name.to_lowercase() == "information_schema" && privileges.contains(&UserPrivilegeType::Select) && len == 1 { @@ -222,7 +222,10 @@ impl PrivilegeAccess { } } GrantObject::Table(_, db_name, table_name) => { - if (db_name == "information_schema" || (db_name == "system" && table_name == "one")) + let db_name = db_name.to_lowercase(); + let table_name = table_name.to_lowercase(); + if (db_name.to_lowercase() == "information_schema" + || (db_name == "system" && table_name == "one")) && privileges.contains(&UserPrivilegeType::Select) && len == 1 { @@ -231,7 +234,7 @@ impl PrivilegeAccess { } GrantObject::DatabaseById(catalog_name, db_id) => { let catalog = self.ctx.get_catalog(catalog_name).await?; - db_name = catalog.get_db_name_by_id(*db_id).await?; + db_name = catalog.get_db_name_by_id(*db_id).await?.to_lowercase(); if db_name == "information_schema" && privileges.contains(&UserPrivilegeType::Select) && len == 1 @@ -241,8 +244,11 @@ impl PrivilegeAccess { } GrantObject::TableById(catalog_name, db_id, table_id) => { let catalog = self.ctx.get_catalog(catalog_name).await?; - db_name = catalog.get_db_name_by_id(*db_id).await?; - table_name = catalog.get_table_name_by_id(*table_id).await?; + db_name = catalog.get_db_name_by_id(*db_id).await?.to_lowercase(); + table_name = catalog + .get_table_name_by_id(*table_id) + .await? + .to_lowercase(); if (db_name == "information_schema" || (db_name == "system" && table_name == "one")) && privileges.contains(&UserPrivilegeType::Select) && len == 1 @@ -958,7 +964,7 @@ async fn has_priv( table_id: Option, grant_set: UserGrantSet, ) -> Result { - if db_name == "information_schema" { + if db_name.to_lowercase() == "information_schema" { return Ok(true); } Ok(RoleCacheManager::instance()