Skip to content

Commit c3fee76

Browse files
authored
feat(rbac): procedure object support rbac (#18730)
* eat(rbac): procedure object support rbac * 1. replace p_id to procedure_id 2. add new function create_id_value_with_cleanup process ownership kv 3. modify test * no need to assert the seq of ownership key * refactor create_id_value * refactor cleanup_old_fn * fix
1 parent 28c6106 commit c3fee76

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1081
-144
lines changed

src/meta/api/src/catalog_api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ where
7171
)]
7272
},
7373
|_, _| Ok(vec![]),
74+
|_, _| {},
7475
)
7576
.await?;
7677

src/meta/api/src/dictionary_api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ where
7373
false,
7474
|_| vec![],
7575
|_, _| Ok(vec![]),
76+
|_, _| {},
7677
)
7778
.await?;
7879

src/meta/api/src/index_api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ where
110110
mark_index_as_deleted(name_ident.tenant(), value.table_id, *index_id)
111111
.map(|(k, v)| vec![(k, v)])
112112
},
113+
|_, _| {},
113114
)
114115
.await?;
115116

src/meta/api/src/name_id_value_api.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ where
6565
IdRsc: TenantResource + Send + Sync + 'static,
6666
IdRsc::ValueType: FromToProto + Send + Sync + 'static,
6767
{
68-
/// Create a two level `name -> id -> value` mapping.
68+
/// Create a two level `name -> id -> value` mapping with cleanup support for old resources.
6969
///
7070
/// `associated_records` is used to generate additional key-values to add or remove along with the main operation.
7171
/// Such operations do not have any condition constraints.
@@ -76,17 +76,25 @@ where
7676
///
7777
/// If there is already a `name_ident` exists, return the existing id in a `Ok(Err(exist))`.
7878
/// Otherwise, create `name -> id -> value` and returns the created id in a `Ok(Ok(created))`.
79-
async fn create_id_value<A, M>(
79+
///
80+
/// `on_override_fn` is called with the old id and txn when override_exist is true and an existing
81+
/// resource is being replaced. It can add custom operations to the transaction.
82+
///
83+
/// This eliminates the need for callers to manually handle cleanup logic after the fact.
84+
/// For example, when a procedure is dropped by `override_exist`, `__fd_object_owners/tenant1/procedure-by-id/<procedure_id>` will be delete
85+
async fn create_id_value<A, M, O>(
8086
&self,
8187
name_ident: &K,
8288
value: &IdRsc::ValueType,
8389
override_exist: bool,
8490
associated_records: A,
8591
mark_delete_records: M,
92+
on_override_fn: O,
8693
) -> Result<Result<DataId<IdRsc>, SeqV<DataId<IdRsc>>>, MetaTxnError>
8794
where
8895
A: Fn(DataId<IdRsc>) -> Vec<(String, Vec<u8>)> + Send,
8996
M: Fn(DataId<IdRsc>, &IdRsc::ValueType) -> Result<Vec<(String, Vec<u8>)>, MetaError> + Send,
97+
O: Fn(DataId<IdRsc>, &mut TxnRequest) + Send,
9098
{
9199
debug!(name_ident :? =name_ident; "NameIdValueApi: {}", func_name!());
92100

@@ -124,6 +132,8 @@ where
124132
for (k, v) in kvs {
125133
txn.if_then.push(TxnOp::put(k, v));
126134
}
135+
// Apply override function if provided
136+
on_override_fn(seq_id.data, &mut txn);
127137
} else {
128138
return Ok(Err(seq_id));
129139
}

src/meta/app/src/principal/ownership_object.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ pub enum OwnershipObject {
6464
Sequence {
6565
name: String,
6666
},
67+
68+
Procedure {
69+
procedure_id: u64,
70+
},
6771
}
6872

6973
impl OwnershipObject {
@@ -95,6 +99,7 @@ impl fmt::Display for OwnershipObject {
9599
OwnershipObject::Warehouse { id } => write!(f, "WAREHOUSE {id}"),
96100
OwnershipObject::Connection { name } => write!(f, "CONNECTION {name}"),
97101
OwnershipObject::Sequence { name } => write!(f, "SEQUENCE {name}"),
102+
OwnershipObject::Procedure { procedure_id } => write!(f, "PROCEDURE {procedure_id}"),
98103
}
99104
}
100105
}
@@ -137,6 +142,9 @@ impl KeyCodec for OwnershipObject {
137142
OwnershipObject::Warehouse { id } => b.push_raw("warehouse-by-id").push_str(id),
138143
OwnershipObject::Connection { name } => b.push_raw("connection-by-name").push_str(name),
139144
OwnershipObject::Sequence { name } => b.push_raw("sequence-by-name").push_str(name),
145+
OwnershipObject::Procedure { procedure_id } => {
146+
b.push_raw("procedure-by-id").push_u64(*procedure_id)
147+
}
140148
}
141149
}
142150

@@ -195,6 +203,10 @@ impl KeyCodec for OwnershipObject {
195203
let name = p.next_str()?;
196204
Ok(OwnershipObject::Sequence { name })
197205
}
206+
"procedure-by-id" => {
207+
let procedure_id = p.next_u64()?;
208+
Ok(OwnershipObject::Procedure { procedure_id })
209+
}
198210
_ => Err(kvapi::KeyError::InvalidSegment {
199211
i: p.index(),
200212
expect: "database-by-id|database-by-catalog-id|table-by-id|table-by-catalog-id|stage-by-name|udf-by-name|warehouse-by-id|connection-by-name"

src/meta/app/src/principal/tenant_ownership_object_ident.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,19 @@ mod tests {
288288
);
289289
}
290290

291+
#[test]
292+
fn test_ownership_procedure_list_key() {
293+
use databend_common_meta_kvapi::kvapi::Key;
294+
let obj = OwnershipObject::Procedure { procedure_id: 1 };
295+
296+
let ident = TenantOwnershipObjectIdent::new(Tenant::new_literal("tenant1"), obj);
297+
let dir_name = kvapi::DirName::new(ident);
298+
assert_eq!(
299+
dir_name.to_string_key(),
300+
"__fd_object_owners/tenant1/procedure-by-id"
301+
);
302+
}
303+
291304
#[test]
292305
fn test_tenant_ownership_object_with_key_space() {
293306
// TODO(xp): implement this test

src/meta/app/src/principal/user_grant.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub enum GrantObject {
6262
Warehouse(String),
6363
Connection(String),
6464
Sequence(String),
65+
Procedure(u64),
6566
}
6667

6768
impl GrantObject {
@@ -97,6 +98,7 @@ impl GrantObject {
9798
(GrantObject::Warehouse(w), GrantObject::Warehouse(rw)) => w == rw,
9899
(GrantObject::Connection(c), GrantObject::Connection(rc)) => c == rc,
99100
(GrantObject::Sequence(s), GrantObject::Sequence(rs)) => s == rs,
101+
(GrantObject::Procedure(p), GrantObject::Procedure(rp)) => p == rp,
100102
_ => false,
101103
}
102104
}
@@ -126,6 +128,9 @@ impl GrantObject {
126128
GrantObject::Sequence(_) => {
127129
UserPrivilegeSet::available_privileges_on_sequence(available_ownership)
128130
}
131+
GrantObject::Procedure(_) => {
132+
UserPrivilegeSet::available_privileges_on_procedure(available_ownership)
133+
}
129134
}
130135
}
131136

@@ -136,6 +141,7 @@ impl GrantObject {
136141
| GrantObject::UDF(_)
137142
| GrantObject::Warehouse(_)
138143
| GrantObject::Sequence(_)
144+
| GrantObject::Procedure(_)
139145
| GrantObject::Connection(_) => None,
140146
GrantObject::Database(cat, _) | GrantObject::DatabaseById(cat, _) => Some(cat.clone()),
141147
GrantObject::Table(cat, _, _) | GrantObject::TableById(cat, _, _) => Some(cat.clone()),
@@ -160,6 +166,7 @@ impl fmt::Display for GrantObject {
160166
GrantObject::Warehouse(w) => write!(f, "WAREHOUSE {w}"),
161167
GrantObject::Connection(c) => write!(f, "CONNECTION {c}"),
162168
GrantObject::Sequence(s) => write!(f, "SEQUENCE {s}"),
169+
GrantObject::Procedure(p) => write!(f, "PROCEDURE {p}"),
163170
}
164171
}
165172
}

src/meta/app/src/principal/user_privilege.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ pub enum UserPrivilegeType {
8686
CreateSequence = 1 << 24,
8787
// Privilege to Access Sequence
8888
AccessSequence = 1 << 25,
89+
// Privilege to Create Procedure
90+
CreateProcedure = 1 << 26,
91+
// Privilege to Access Procedure
92+
AccessProcedure = 1 << 27,
8993
// Discard Privilege Type
9094
Set = 1 << 4,
9195
}
@@ -147,6 +151,8 @@ impl Display for UserPrivilegeType {
147151
UserPrivilegeType::AccessConnection => "ACCESS CONNECTION",
148152
UserPrivilegeType::CreateSequence => "CREATE SEQUENCE",
149153
UserPrivilegeType::AccessSequence => "ACCESS SEQUENCE",
154+
UserPrivilegeType::CreateProcedure => "CREATE PROCEDURE",
155+
UserPrivilegeType::AccessProcedure => "ACCESS PROCEDURE",
150156
})
151157
}
152158
}
@@ -199,6 +205,12 @@ impl From<databend_common_ast::ast::UserPrivilegeType> for UserPrivilegeType {
199205
databend_common_ast::ast::UserPrivilegeType::AccessSequence => {
200206
UserPrivilegeType::AccessSequence
201207
}
208+
databend_common_ast::ast::UserPrivilegeType::CreateProcedure => {
209+
UserPrivilegeType::CreateProcedure
210+
}
211+
databend_common_ast::ast::UserPrivilegeType::AccessProcedure => {
212+
UserPrivilegeType::AccessProcedure
213+
}
202214
databend_common_ast::ast::UserPrivilegeType::Set => UserPrivilegeType::Set,
203215
}
204216
}
@@ -235,7 +247,7 @@ impl UserPrivilegeSet {
235247
let wh_privs_without_ownership = Self::available_privileges_on_warehouse(false);
236248
let connection_privs_without_ownership = Self::available_privileges_on_connection(false);
237249
let seq_privs_without_ownership = Self::available_privileges_on_sequence(false);
238-
let privs = make_bitflags!(UserPrivilegeType::{ Usage | Super | CreateUser | DropUser | CreateRole | DropRole | CreateDatabase | Grant | CreateDataMask | CreateWarehouse | CreateConnection | CreateSequence });
250+
let privs = make_bitflags!(UserPrivilegeType::{ Usage | Super | CreateUser | DropUser | CreateRole | DropRole | CreateDatabase | Grant | CreateDataMask | CreateWarehouse | CreateConnection | CreateSequence | CreateProcedure });
239251
(database_privs.privileges
240252
| privs
241253
| stage_privs_without_ownership.privileges
@@ -297,6 +309,14 @@ impl UserPrivilegeSet {
297309
}
298310
}
299311

312+
pub fn available_privileges_on_procedure(available_ownership: bool) -> Self {
313+
if available_ownership {
314+
make_bitflags!(UserPrivilegeType::{ AccessProcedure | Ownership }).into()
315+
} else {
316+
make_bitflags!(UserPrivilegeType::{ AccessProcedure }).into()
317+
}
318+
}
319+
300320
pub fn available_privileges_on_udf(available_ownership: bool) -> Self {
301321
if available_ownership {
302322
make_bitflags!(UserPrivilegeType::{ Usage | Ownership }).into()

src/meta/proto-conv/src/ownership_from_to_protobuf_impl.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ impl FromToProto for mt::principal::OwnershipObject {
9797
pb::ownership_object::Object::Sequence(
9898
pb::ownership_object::OwnershipSequenceObject { sequence },
9999
) => Ok(mt::principal::OwnershipObject::Sequence { name: sequence }),
100+
pb::ownership_object::Object::Procedure(
101+
pb::ownership_object::OwnershipProcedureObject { procedure_id },
102+
) => Ok(mt::principal::OwnershipObject::Procedure { procedure_id }),
100103
}
101104
}
102105

@@ -151,6 +154,13 @@ impl FromToProto for mt::principal::OwnershipObject {
151154
},
152155
))
153156
}
157+
mt::principal::OwnershipObject::Procedure { procedure_id } => {
158+
Some(pb::ownership_object::Object::Procedure(
159+
pb::ownership_object::OwnershipProcedureObject {
160+
procedure_id: *procedure_id,
161+
},
162+
))
163+
}
154164
};
155165
Ok(pb::OwnershipObject {
156166
ver: VER,

src/meta/proto-conv/src/user_from_to_protobuf_impl.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ impl FromToProto for mt::principal::GrantObject {
200200
pb::grant_object::Object::Sequence(pb::grant_object::GrantSequenceObject {
201201
sequence,
202202
}) => Ok(mt::principal::GrantObject::Sequence(sequence)),
203+
pb::grant_object::Object::Procedure(pb::grant_object::GrantProcedureObject {
204+
procedure_id,
205+
}) => Ok(mt::principal::GrantObject::Procedure(procedure_id)),
203206
}
204207
}
205208

@@ -257,6 +260,9 @@ impl FromToProto for mt::principal::GrantObject {
257260
sequence: s.clone(),
258261
},
259262
)),
263+
mt::principal::GrantObject::Procedure(p) => Some(pb::grant_object::Object::Procedure(
264+
pb::grant_object::GrantProcedureObject { procedure_id: *p },
265+
)),
260266
};
261267
Ok(pb::GrantObject {
262268
ver: VER,

0 commit comments

Comments
 (0)