Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/handlers/http/cluster/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ pub async fn get_demo_data_from_ingestor(action: &str) -> Result<(), PostError>

// forward the role update request to all ingestors to keep them in sync
pub async fn sync_users_with_roles_with_ingestors(
username: &str,
userid: &str,
role: &HashSet<String>,
operation: &str,
) -> Result<(), RBACError> {
Expand All @@ -236,7 +236,7 @@ pub async fn sync_users_with_roles_with_ingestors(
RBACError::SerdeError(err)
})?;

let username = username.to_owned();
let userid = userid.to_owned();

let op = operation.to_string();

Expand All @@ -245,15 +245,15 @@ pub async fn sync_users_with_roles_with_ingestors(
"{}{}/user/{}/role/sync/{}",
ingestor.domain_name,
base_path_without_preceding_slash(),
username,
userid,
op
);

let role_data = role_data.clone();

async move {
let res = INTRA_CLUSTER_CLIENT
.put(url)
.patch(url)
.header(header::AUTHORIZATION, &ingestor.token)
.header(header::CONTENT_TYPE, "application/json")
.body(role_data)
Expand Down Expand Up @@ -282,15 +282,15 @@ pub async fn sync_users_with_roles_with_ingestors(
}

// forward the delete user request to all ingestors to keep them in sync
pub async fn sync_user_deletion_with_ingestors(username: &str) -> Result<(), RBACError> {
let username = username.to_owned();
pub async fn sync_user_deletion_with_ingestors(userid: &str) -> Result<(), RBACError> {
let userid = userid.to_owned();

for_each_live_ingestor(move |ingestor| {
let url = format!(
"{}{}/user/{}/sync",
ingestor.domain_name,
base_path_without_preceding_slash(),
username
userid
);

async move {
Expand Down Expand Up @@ -331,21 +331,21 @@ pub async fn sync_user_creation_with_ingestors(
if let Some(role) = role {
user.roles.clone_from(role);
}
let username = user.username();
let userid = user.userid();

let user_data = to_vec(&user).map_err(|err| {
error!("Fatal: failed to serialize user: {:?}", err);
RBACError::SerdeError(err)
})?;

let username = username.to_string();
let userid = userid.to_string();

for_each_live_ingestor(move |ingestor| {
let url = format!(
"{}{}/user/{}/sync",
ingestor.domain_name,
base_path_without_preceding_slash(),
username
userid
);

let user_data = user_data.clone();
Expand Down
76 changes: 37 additions & 39 deletions src/handlers/http/modal/ingest/ingestor_rbac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@

use std::collections::HashSet;

use actix_web::{Responder, web};
use tokio::sync::Mutex;
use actix_web::{HttpResponse, web};
use http::StatusCode;

use crate::{
handlers::http::{modal::utils::rbac_utils::get_metadata, rbac::RBACError},
handlers::http::{
modal::utils::rbac_utils::get_metadata,
rbac::{RBACError, UPDATE_LOCK},
},
rbac::{
Users,
map::roles,
Expand All @@ -31,18 +34,14 @@ use crate::{
storage,
};

// async aware lock for updating storage metadata and user map atomicically
static UPDATE_LOCK: Mutex<()> = Mutex::const_new(());

// Handler for POST /api/v1/user/{username}
// Creates a new user by username if it does not exists
pub async fn post_user(
username: web::Path<String>,
body: Option<web::Json<serde_json::Value>>,
) -> Result<impl Responder, RBACError> {
) -> Result<HttpResponse, RBACError> {
let username = username.into_inner();

let generated_password = String::default();
let metadata = get_metadata().await?;
if let Some(body) = body {
let user: ParseableUser = serde_json::from_value(body.into_inner())?;
Expand All @@ -52,37 +51,38 @@ pub async fn post_user(
Users.add_roles(&username, created_role.clone());
}

Ok(generated_password)
Ok(HttpResponse::Ok().status(StatusCode::OK).finish())
}

// Handler for DELETE /api/v1/user/delete/{username}
pub async fn delete_user(username: web::Path<String>) -> Result<impl Responder, RBACError> {
let username = username.into_inner();
let _ = UPDATE_LOCK.lock().await;
// Handler for DELETE /api/v1/user/delete/{userid}
pub async fn delete_user(userid: web::Path<String>) -> Result<HttpResponse, RBACError> {
let userid = userid.into_inner();
let _guard = UPDATE_LOCK.lock().await;
// fail this request if the user does not exists
if !Users.contains(&username) {
if !Users.contains(&userid) {
return Err(RBACError::UserDoesNotExist);
};

// delete from parseable.json first
let mut metadata = get_metadata().await?;
metadata.users.retain(|user| user.username() != username);
metadata.users.retain(|user| user.userid() != userid);

let _ = storage::put_staging_metadata(&metadata);

// update in mem table
Users.delete_user(&username);
Ok(format!("deleted user: {username}"))
Users.delete_user(&userid);
Ok(HttpResponse::Ok().status(StatusCode::OK).finish())
}

// Handler PATCH /user/{username}/role/sync/add => Add roles to a user
// Handler PATCH /user/{userid}/role/sync/add => Add roles to a user
pub async fn add_roles_to_user(
username: web::Path<String>,
userid: web::Path<String>,
roles_to_add: web::Json<HashSet<String>>,
) -> Result<String, RBACError> {
let username = username.into_inner();
) -> Result<HttpResponse, RBACError> {
let userid = userid.into_inner();
let roles_to_add = roles_to_add.into_inner();

if !Users.contains(&username) {
if !Users.contains(&userid) {
return Err(RBACError::UserDoesNotExist);
};

Expand All @@ -103,7 +103,7 @@ pub async fn add_roles_to_user(
if let Some(user) = metadata
.users
.iter_mut()
.find(|user| user.username() == username)
.find(|user| user.userid() == userid)
{
user.roles.extend(roles_to_add.clone());
} else {
Expand All @@ -113,20 +113,19 @@ pub async fn add_roles_to_user(

let _ = storage::put_staging_metadata(&metadata);
// update in mem table
Users.add_roles(&username.clone(), roles_to_add.clone());

Ok(format!("Roles updated successfully for {username}"))
Users.add_roles(&userid.clone(), roles_to_add.clone());
Ok(HttpResponse::Ok().status(StatusCode::OK).finish())
}

// Handler PATCH /user/{username}/role/sync/add => Add roles to a user
// Handler PATCH /user/{userid}/role/sync/remove => Remove roles to a user
pub async fn remove_roles_from_user(
username: web::Path<String>,
userid: web::Path<String>,
roles_to_remove: web::Json<HashSet<String>>,
) -> Result<String, RBACError> {
let username = username.into_inner();
) -> Result<HttpResponse, RBACError> {
let userid = userid.into_inner();
let roles_to_remove = roles_to_remove.into_inner();

if !Users.contains(&username) {
if !Users.contains(&userid) {
return Err(RBACError::UserDoesNotExist);
};

Expand All @@ -143,7 +142,7 @@ pub async fn remove_roles_from_user(
}

// check that user actually has these roles
let user_roles: HashSet<String> = HashSet::from_iter(Users.get_role(&username));
let user_roles: HashSet<String> = HashSet::from_iter(Users.get_role(&userid));
let roles_not_with_user: HashSet<String> =
HashSet::from_iter(roles_to_remove.difference(&user_roles).cloned());

Expand All @@ -153,12 +152,12 @@ pub async fn remove_roles_from_user(
)));
}

// update parseable.json first
// update parseable.json in staging first
let mut metadata = get_metadata().await?;
if let Some(user) = metadata
.users
.iter_mut()
.find(|user| user.username() == username)
.find(|user| user.userid() == userid)
{
let diff: HashSet<String> =
HashSet::from_iter(user.roles.difference(&roles_to_remove).cloned());
Expand All @@ -170,14 +169,14 @@ pub async fn remove_roles_from_user(

let _ = storage::put_staging_metadata(&metadata);
// update in mem table
Users.remove_roles(&username.clone(), roles_to_remove.clone());
Users.remove_roles(&userid.clone(), roles_to_remove.clone());

Ok(format!("Roles updated successfully for {username}"))
Ok(HttpResponse::Ok().status(StatusCode::OK).finish())
}

// Handler for POST /api/v1/user/{username}/generate-new-password
// Resets password for the user to a newly generated one and returns it
pub async fn post_gen_password(username: web::Path<String>) -> Result<impl Responder, RBACError> {
pub async fn post_gen_password(username: web::Path<String>) -> Result<HttpResponse, RBACError> {
let username = username.into_inner();
let mut new_hash = String::default();
let mut metadata = get_metadata().await?;
Expand All @@ -197,6 +196,5 @@ pub async fn post_gen_password(username: web::Path<String>) -> Result<impl Respo
return Err(RBACError::UserDoesNotExist);
}
Users.change_password_hash(&username, &new_hash);

Ok("Updated")
Ok(HttpResponse::Ok().status(StatusCode::OK).finish())
}
12 changes: 6 additions & 6 deletions src/handlers/http/modal/ingest/ingestor_role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,21 @@ pub async fn put(
// refresh the sessions of all users using this role
// for this, iterate over all user_groups and users and create a hashset of users
let mut session_refresh_users: HashSet<String> = HashSet::new();
for user_group in read_user_groups().values().cloned() {
for user_group in read_user_groups().values() {
if user_group.roles.contains(&name) {
session_refresh_users.extend(user_group.users);
session_refresh_users.extend(user_group.users.iter().map(|u| u.userid().to_string()));
}
}

// iterate over all users to see if they have this role
for user in users().values().cloned() {
for user in users().values() {
if user.roles.contains(&name) {
session_refresh_users.insert(user.username().to_string());
session_refresh_users.insert(user.userid().to_string());
}
}

for username in session_refresh_users {
mut_sessions().remove_user(&username);
for userid in session_refresh_users {
mut_sessions().remove_user(&userid);
}

Ok(HttpResponse::Ok().finish())
Expand Down
12 changes: 6 additions & 6 deletions src/handlers/http/modal/ingest_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,13 @@ impl IngestServer {
web::scope("/user")
.service(
web::resource("/{username}/sync")
// PUT /user/{username}/sync => Sync creation of a new user
// POST /user/{username}/sync => Sync creation of a new user
.route(
web::post()
.to(ingestor_rbac::post_user)
.authorize(Action::PutUser),
)
// DELETE /user/{username} => Sync deletion of a user
// DELETE /user/{userid} => Sync deletion of a user
.route(
web::delete()
.to(ingestor_rbac::delete_user)
Expand All @@ -199,8 +199,8 @@ impl IngestServer {
.wrap(DisAllowRootUser),
)
.service(
web::resource("/{username}/role/sync/add")
// PATCH /user/{username}/role/sync/add => Add roles to a user
web::resource("/{userid}/role/sync/add")
// PATCH /user/{userid}/role/sync/add => Add roles to a user
.route(
web::patch()
.to(ingestor_rbac::add_roles_to_user)
Expand All @@ -209,8 +209,8 @@ impl IngestServer {
),
)
.service(
web::resource("/{username}/role/sync/remove")
// PATCH /user/{username}/role/sync/remove => Remove roles from a user
web::resource("/{userid}/role/sync/remove")
// PATCH /user/{userid}/role/sync/remove => Remove roles from a user
.route(
web::patch()
.to(ingestor_rbac::remove_roles_from_user)
Expand Down
Loading
Loading