Skip to content

Commit 601b6cf

Browse files
committed
Updates: coderabbit suggestions
1 parent 7d8c259 commit 601b6cf

File tree

8 files changed

+171
-230
lines changed

8 files changed

+171
-230
lines changed

src/handlers/http/modal/ingest/ingestor_rbac.rs

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use tokio::sync::Mutex;
2424
use crate::{
2525
handlers::http::{modal::utils::rbac_utils::get_metadata, rbac::RBACError},
2626
rbac::{
27+
map::roles,
2728
user::{self, User as ParseableUser},
2829
Users,
2930
},
@@ -73,38 +74,6 @@ pub async fn delete_user(username: web::Path<String>) -> Result<impl Responder,
7374
Ok(format!("deleted user: {username}"))
7475
}
7576

76-
// // Handler PUT /user/{username}/roles => Put roles for user
77-
// // Put roles for given user
78-
// pub async fn put_role(
79-
// username: web::Path<String>,
80-
// role: web::Json<HashSet<String>>,
81-
// ) -> Result<String, RBACError> {
82-
// let username = username.into_inner();
83-
// let role = role.into_inner();
84-
85-
// if !Users.contains(&username) {
86-
// return Err(RBACError::UserDoesNotExist);
87-
// };
88-
// // update parseable.json first
89-
// let mut metadata = get_metadata().await?;
90-
// if let Some(user) = metadata
91-
// .users
92-
// .iter_mut()
93-
// .find(|user| user.username() == username)
94-
// {
95-
// user.roles.clone_from(&role);
96-
// } else {
97-
// // should be unreachable given state is always consistent
98-
// return Err(RBACError::UserDoesNotExist);
99-
// }
100-
101-
// let _ = storage::put_staging_metadata(&metadata);
102-
// // update in mem table
103-
// Users.add_roles(&username.clone(), role.clone());
104-
105-
// Ok(format!("Roles updated successfully for {username}"))
106-
// }
107-
10877
// Handler PATCH /user/{username}/role/sync/add => Add roles to a user
10978
pub async fn add_roles_to_user(
11079
username: web::Path<String>,
@@ -116,6 +85,19 @@ pub async fn add_roles_to_user(
11685
if !Users.contains(&username) {
11786
return Err(RBACError::UserDoesNotExist);
11887
};
88+
89+
// check if all roles exist
90+
let mut non_existent_roles = Vec::new();
91+
roles_to_add.iter().for_each(|r| {
92+
if roles().get(r).is_none() {
93+
non_existent_roles.push(r.clone());
94+
}
95+
});
96+
97+
if !non_existent_roles.is_empty() {
98+
return Err(RBACError::RolesDoNotExist(non_existent_roles));
99+
}
100+
119101
// update parseable.json first
120102
let mut metadata = get_metadata().await?;
121103
if let Some(user) = metadata
@@ -147,6 +129,30 @@ pub async fn remove_roles_from_user(
147129
if !Users.contains(&username) {
148130
return Err(RBACError::UserDoesNotExist);
149131
};
132+
133+
// check if all roles exist
134+
let mut non_existent_roles = Vec::new();
135+
roles_to_remove.iter().for_each(|r| {
136+
if roles().get(r).is_none() {
137+
non_existent_roles.push(r.clone());
138+
}
139+
});
140+
141+
if !non_existent_roles.is_empty() {
142+
return Err(RBACError::RolesDoNotExist(non_existent_roles));
143+
}
144+
145+
// check that user actually has these roles
146+
let user_roles: HashSet<String> = HashSet::from_iter(Users.get_role(&username));
147+
let roles_not_with_user: HashSet<String> =
148+
HashSet::from_iter(roles_to_remove.difference(&user_roles).cloned());
149+
150+
if !roles_not_with_user.is_empty() {
151+
return Err(RBACError::RolesNotAssigned(Vec::from_iter(
152+
roles_not_with_user,
153+
)));
154+
}
155+
150156
// update parseable.json first
151157
let mut metadata = get_metadata().await?;
152158
if let Some(user) = metadata

src/handlers/http/rbac.rs

Lines changed: 29 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,17 @@ pub async fn post_user(
115115
if user_roles.is_empty() {
116116
return Err(RBACError::RoleValidationError);
117117
} else {
118-
let mut non_existant_roles = Vec::new();
118+
let mut non_existent_roles = Vec::new();
119119
user_roles
120120
.iter()
121121
.map(|r| {
122122
if !roles().contains_key(r) {
123-
non_existant_roles.push(r.clone());
123+
non_existent_roles.push(r.clone());
124124
}
125125
})
126126
.for_each(drop);
127-
if !non_existant_roles.is_empty() {
128-
return Err(RBACError::RolesDoNotExist(non_existant_roles));
127+
if !non_existent_roles.is_empty() {
128+
return Err(RBACError::RolesDoNotExist(non_existent_roles));
129129
}
130130
}
131131
let _ = UPDATE_LOCK.lock().await;
@@ -237,24 +237,23 @@ pub async fn delete_user(username: web::Path<String>) -> Result<impl Responder,
237237
let mut metadata = get_metadata().await?;
238238
metadata.users.retain(|user| user.username() != username);
239239

240-
// also delete from user groups
240+
// Remove user from all groups
241241
let user_groups = Users.get_user_groups(&username);
242-
let mut groups_to_update = Vec::new();
243-
for user_group in user_groups {
244-
if let Some(ug) = write_user_groups().get_mut(&user_group) {
245-
ug.remove_users(HashSet::from_iter([username.clone()]))?;
246-
groups_to_update.push(ug.clone());
247-
// ug.update_in_metadata().await?;
248-
} else {
249-
continue;
250-
};
242+
{
243+
let mut groups = write_user_groups();
244+
for group_name in &user_groups {
245+
if let Some(group) = groups.get_mut(group_name) {
246+
group.remove_users(HashSet::from_iter([username.clone()]))?;
247+
}
248+
}
251249
}
252250

253-
// update in metadata user groups
254-
metadata
255-
.user_groups
256-
.retain(|x| !groups_to_update.contains(x));
257-
metadata.user_groups.extend(groups_to_update);
251+
// Update metadata with modified groups
252+
for group in metadata.user_groups.iter_mut() {
253+
if user_groups.contains(&group.name) {
254+
group.users.retain(|u| u != &username);
255+
}
256+
}
258257
put_metadata(&metadata).await?;
259258

260259
// update in mem table
@@ -274,17 +273,17 @@ pub async fn add_roles_to_user(
274273
return Err(RBACError::UserDoesNotExist);
275274
};
276275

277-
let mut non_existant_roles = Vec::new();
276+
let mut non_existent_roles = Vec::new();
278277

279278
// check if the role exists
280279
roles_to_add.iter().for_each(|r| {
281280
if roles().get(r).is_none() {
282-
non_existant_roles.push(r.clone());
281+
non_existent_roles.push(r.clone());
283282
}
284283
});
285284

286-
if !non_existant_roles.is_empty() {
287-
return Err(RBACError::RolesDoNotExist(non_existant_roles));
285+
if !non_existent_roles.is_empty() {
286+
return Err(RBACError::RolesDoNotExist(non_existent_roles));
288287
}
289288

290289
// update parseable.json first
@@ -319,17 +318,17 @@ pub async fn remove_roles_from_user(
319318
return Err(RBACError::UserDoesNotExist);
320319
};
321320

322-
let mut non_existant_roles = Vec::new();
321+
let mut non_existent_roles = Vec::new();
323322

324323
// check if the role exists
325324
roles_to_remove.iter().for_each(|r| {
326325
if roles().get(r).is_none() {
327-
non_existant_roles.push(r.clone());
326+
non_existent_roles.push(r.clone());
328327
}
329328
});
330329

331-
if !non_existant_roles.is_empty() {
332-
return Err(RBACError::RolesDoNotExist(non_existant_roles));
330+
if !non_existent_roles.is_empty() {
331+
return Err(RBACError::RolesDoNotExist(non_existent_roles));
333332
}
334333

335334
// check for role not present with user
@@ -368,31 +367,13 @@ pub async fn remove_roles_from_user(
368367
#[serde(rename = "camelCase")]
369368
pub struct InvalidUserGroupError {
370369
pub valid_name: bool,
371-
pub non_existant_roles: Vec<String>,
372-
pub non_existant_users: Vec<String>,
370+
pub non_existent_roles: Vec<String>,
371+
pub non_existent_users: Vec<String>,
373372
pub roles_not_in_group: Vec<String>,
374373
pub users_not_in_group: Vec<String>,
375374
pub comments: String,
376375
}
377376

378-
// impl Display for InvalidUserGroupRequestStruct {
379-
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
380-
// if !self.invalid_name {
381-
// write!(
382-
// f,
383-
// "Invalid user group request- {{invalidName: {}\nnonExistantRoles: {:?}\nnonExistantUsers: {:?}\nThe name should follow this regex- ^[A-Za-z0-9_-]+$}}",
384-
// self.invalid_name, self.non_existant_roles, self.non_existant_users
385-
// )
386-
// } else {
387-
// write!(
388-
// f,
389-
// "Invalid user group request- {{nonExistantRoles: {:?}\nnonExistantUsers: {:?}}}",
390-
// self.non_existant_roles, self.non_existant_users
391-
// )
392-
// }
393-
// }
394-
// }
395-
396377
#[derive(Debug, thiserror::Error)]
397378
pub enum RBACError {
398379
#[error("User exists already")]
@@ -461,7 +442,7 @@ impl actix_web::ResponseError for RBACError {
461442
RBACError::RolesDoNotExist(obj) => actix_web::HttpResponse::build(self.status_code())
462443
.insert_header(ContentType::plaintext())
463444
.json(json!({
464-
"non_existant_roles": obj
445+
"non_existent_roles": obj
465446
})),
466447
RBACError::InvalidUserGroupRequest(obj) => {
467448
actix_web::HttpResponse::build(self.status_code())

src/handlers/http/role.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
*
1717
*/
1818

19-
use std::collections::HashSet;
20-
2119
use actix_web::{
2220
http::header::ContentType,
2321
web::{self, Json},
@@ -103,23 +101,21 @@ pub async fn delete(name: web::Path<String>) -> Result<impl Responder, RoleError
103101
};
104102
}
105103

104+
// remove role from all user groups that have it
106105
let mut groups_to_update = Vec::new();
107-
for user_group in group_names {
108-
if let Some(ug) = write_user_groups().get_mut(&user_group) {
109-
ug.remove_roles(HashSet::from_iter([name.clone()]))
110-
.map_err(|e| RoleError::Anyhow(anyhow::Error::msg(e.to_string())))?;
111-
groups_to_update.push(ug.clone());
112-
// ug.update_in_metadata().await?;
113-
} else {
114-
continue;
115-
};
106+
for group in write_user_groups().values_mut() {
107+
if group.roles.remove(&name) {
108+
groups_to_update.push(group.clone());
109+
}
116110
}
117111

118-
// update in metadata
119-
metadata
120-
.user_groups
121-
.retain(|x| !groups_to_update.contains(x));
122-
metadata.user_groups.extend(groups_to_update);
112+
// update metadata only if there are changes
113+
if !groups_to_update.is_empty() {
114+
metadata
115+
.user_groups
116+
.retain(|x| !groups_to_update.contains(x));
117+
metadata.user_groups.extend(groups_to_update);
118+
}
123119
put_metadata(&metadata).await?;
124120

125121
Ok(HttpResponse::Ok().finish())

src/migration/mod.rs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ use crate::{
4141
},
4242
};
4343

44+
fn get_version(metadata: &serde_json::Value) -> Option<&str> {
45+
metadata
46+
.as_object()
47+
.and_then(|meta| meta.get("version"))
48+
.and_then(|version| version.as_str())
49+
}
50+
4451
/// Migrate the metdata from v1 or v2 to v3
4552
/// This is a one time migration
4653
pub async fn run_metadata_migration(
@@ -55,13 +62,6 @@ pub async fn run_metadata_migration(
5562
}
5663
let staging_metadata = get_staging_metadata(config)?;
5764

58-
fn get_version(metadata: &serde_json::Value) -> Option<&str> {
59-
metadata
60-
.as_object()
61-
.and_then(|meta| meta.get("version"))
62-
.and_then(|version| version.as_str())
63-
}
64-
6565
// if storage metadata is none do nothing
6666
if let Some(storage_metadata) = storage_metadata {
6767
match get_version(&storage_metadata) {
@@ -117,37 +117,42 @@ pub async fn run_metadata_migration(
117117

118118
// if staging metadata is none do nothing
119119
if let Some(staging_metadata) = staging_metadata {
120-
match get_version(&staging_metadata) {
121-
Some("v1") => {
122-
let mut metadata = metadata_migration::v1_v3(staging_metadata);
123-
metadata = metadata_migration::v3_v4(metadata);
124-
put_staging_metadata(config, &metadata)?;
125-
}
126-
Some("v2") => {
127-
let mut metadata = metadata_migration::v2_v3(staging_metadata);
128-
metadata = metadata_migration::v3_v4(metadata);
129-
put_staging_metadata(config, &metadata)?;
130-
}
131-
Some("v3") => {
132-
let metadata = metadata_migration::v3_v4(staging_metadata);
133-
put_staging_metadata(config, &metadata)?;
134-
}
135-
Some("v4") => {
136-
let metadata = metadata_migration::v4_v5(staging_metadata);
137-
let metadata = metadata_migration::v5_v6(metadata);
138-
put_staging_metadata(config, &metadata)?;
139-
}
140-
Some("v5") => {
141-
let metadata = metadata_migration::v5_v6(staging_metadata);
142-
put_staging_metadata(config, &metadata)?;
143-
}
144-
_ => (),
145-
}
120+
migrate_staging(config, staging_metadata)?;
146121
}
147122

148123
Ok(())
149124
}
150125

126+
fn migrate_staging(config: &Parseable, staging_metadata: Value) -> anyhow::Result<()> {
127+
match get_version(&staging_metadata) {
128+
Some("v1") => {
129+
let mut metadata = metadata_migration::v1_v3(staging_metadata);
130+
metadata = metadata_migration::v3_v4(metadata);
131+
put_staging_metadata(config, &metadata)?;
132+
}
133+
Some("v2") => {
134+
let mut metadata = metadata_migration::v2_v3(staging_metadata);
135+
metadata = metadata_migration::v3_v4(metadata);
136+
put_staging_metadata(config, &metadata)?;
137+
}
138+
Some("v3") => {
139+
let metadata = metadata_migration::v3_v4(staging_metadata);
140+
put_staging_metadata(config, &metadata)?;
141+
}
142+
Some("v4") => {
143+
let metadata = metadata_migration::v4_v5(staging_metadata);
144+
let metadata = metadata_migration::v5_v6(metadata);
145+
put_staging_metadata(config, &metadata)?;
146+
}
147+
Some("v5") => {
148+
let metadata = metadata_migration::v5_v6(staging_metadata);
149+
put_staging_metadata(config, &metadata)?;
150+
}
151+
_ => (),
152+
}
153+
Ok(())
154+
}
155+
151156
/// run the migration for all streams concurrently
152157
pub async fn run_migration(config: &Parseable) -> anyhow::Result<()> {
153158
let storage = config.storage.get_object_store();

0 commit comments

Comments
 (0)