From 34b4df8559cdb4e2c0f1d7a9d49e07ab92c73935 Mon Sep 17 00:00:00 2001 From: Nikhil Sinha Date: Fri, 6 Sep 2024 20:00:49 +0530 Subject: [PATCH 1/3] fix: remove user_id from API requests in Dashboards and Filters Fetch session key from HttpRequest then fetch username from the session updated all APIs, removed user_id from API requests while saving the json, generate hash for user_id Dashboard API changes: GET /dashboards/{user_id} -> GET /dashboards this fetches all dashboards for user fetched from HttpRequest GET /dashboards/dashboard/{dashboard_id} -> GET /dashboards/{dashboard_id} DELETE /dashboards/dashboard/{dashboard_id} -> DELETE /dashboards/{dashboard_id} PUT /dashboards/dashboard/{dashboard_id} -> PUT /dashboards/{dashboard_id} Filter API changes: GET /filters/{user_id} -> GET /filters this fetches all filters for user fetched from HttpRequest GET /filters/filter/{filter_id} -> GET /filters/{filter_id} DELETE /filters/filter/{filter_id} -> DELETE /filters/{filter_id} PUT /filters/filter/{filter_id} -> PUT /filters/{filter_id} --- server/src/handlers/http/modal/server.rs | 96 +++++++++----------- server/src/handlers/http/users/dashboards.rs | 51 +++++------ server/src/handlers/http/users/filters.rs | 41 ++++----- server/src/rbac.rs | 4 + server/src/rbac/map.rs | 4 + server/src/users/dashboards.rs | 10 +- server/src/users/filters.rs | 4 +- server/src/utils.rs | 21 +++++ 8 files changed, 120 insertions(+), 111 deletions(-) diff --git a/server/src/handlers/http/modal/server.rs b/server/src/handlers/http/modal/server.rs index 08fd8eee2..67586be94 100644 --- a/server/src/handlers/http/modal/server.rs +++ b/server/src/handlers/http/modal/server.rs @@ -197,40 +197,35 @@ impl Server { pub fn get_dashboards_webscope() -> Scope { web::scope("/dashboards") .service( - web::resource("").route( - web::post() - .to(dashboards::post) - .authorize(Action::CreateDashboard), - ), - ) - .service( - web::scope("/dashboard").service( - web::resource("/{dashboard_id}") - .route( - web::get() - .to(dashboards::get) - .authorize(Action::GetDashboard), - ) - .route( - web::delete() - .to(dashboards::delete) - .authorize(Action::DeleteDashboard), - ) - .route( - web::put() - .to(dashboards::update) - .authorize(Action::CreateDashboard), - ), - ), - ) - .service( - web::scope("/{user_id}").service( - web::resource("").route( + web::resource("") + .route( + web::post() + .to(dashboards::post) + .authorize(Action::CreateDashboard), + ) + .route( web::get() .to(dashboards::list) .authorize(Action::ListDashboard), ), - ), + ) + .service( + web::resource("/{dashboard_id}") + .route( + web::get() + .to(dashboards::get) + .authorize(Action::GetDashboard), + ) + .route( + web::delete() + .to(dashboards::delete) + .authorize(Action::DeleteDashboard), + ) + .route( + web::put() + .to(dashboards::update) + .authorize(Action::CreateDashboard), + ), ) } @@ -238,31 +233,28 @@ impl Server { pub fn get_filters_webscope() -> Scope { web::scope("/filters") .service( - web::resource("").route( - web::post() - .to(filters::post) - .authorize(Action::CreateFilter), - ), + web::resource("") + .route( + web::post() + .to(filters::post) + .authorize(Action::CreateFilter), + ) + .route(web::get().to(filters::list).authorize(Action::ListFilter)), ) .service( - web::scope("/filter").service( - web::resource("/{filter_id}") - .route(web::get().to(filters::get).authorize(Action::GetFilter)) - .route( - web::delete() - .to(filters::delete) - .authorize(Action::DeleteFilter), - ) - .route( - web::put() - .to(filters::update) - .authorize(Action::CreateFilter), - ), - ), + web::resource("/{filter_id}") + .route(web::get().to(filters::get).authorize(Action::GetFilter)) + .route( + web::delete() + .to(filters::delete) + .authorize(Action::DeleteFilter), + ) + .route( + web::put() + .to(filters::update) + .authorize(Action::CreateFilter), + ), ) - .service(web::scope("/{user_id}").service( - web::resource("").route(web::get().to(filters::list).authorize(Action::ListFilter)), - )) } // get the query factory diff --git a/server/src/handlers/http/users/dashboards.rs b/server/src/handlers/http/users/dashboards.rs index 89e47d614..928b84e65 100644 --- a/server/src/handlers/http/users/dashboards.rs +++ b/server/src/handlers/http/users/dashboards.rs @@ -17,10 +17,11 @@ */ use crate::{ - handlers::http::ingest::PostError, + handlers::http::rbac::RBACError, option::CONFIG, storage::{object_storage::dashboard_path, ObjectStorageError}, users::dashboards::{Dashboard, CURRENT_DASHBOARD_VERSION, DASHBOARDS}, + utils::{get_hash, get_user_from_request}, }; use actix_web::{http::header::ContentType, web, HttpRequest, HttpResponse, Responder}; use bytes::Bytes; @@ -30,11 +31,8 @@ use http::StatusCode; use serde_json::Error as SerdeError; pub async fn list(req: HttpRequest) -> Result { - let user_id = req - .match_info() - .get("user_id") - .ok_or(DashboardError::Metadata("No User Id Provided"))?; - let dashboards = DASHBOARDS.list_dashboards_by_user(user_id); + let user_id = get_user_from_request(&req)?; + let dashboards = DASHBOARDS.list_dashboards_by_user(&get_hash(&user_id)); Ok((web::Json(dashboards), StatusCode::OK)) } @@ -52,21 +50,19 @@ pub async fn get(req: HttpRequest) -> Result { Err(DashboardError::Metadata("Dashboard does not exist")) } -pub async fn post(body: Bytes) -> Result { +pub async fn post(req: HttpRequest, body: Bytes) -> Result { + let user_id = get_user_from_request(&req)?; let mut dashboard: Dashboard = serde_json::from_slice(&body)?; - let dashboard_id = format!("{}.{}", &dashboard.user_id, Utc::now().timestamp_millis()); + let dashboard_id = get_hash(Utc::now().timestamp_micros().to_string().as_str()); dashboard.dashboard_id = Some(dashboard_id.clone()); dashboard.version = Some(CURRENT_DASHBOARD_VERSION.to_string()); + dashboard.user_id = Some(get_hash(&user_id)); for tile in dashboard.tiles.iter_mut() { - tile.tile_id = Some(format!( - "{}.{}", - &dashboard.user_id, - Utc::now().timestamp_micros() - )); + tile.tile_id = Some(get_hash(Utc::now().timestamp_micros().to_string().as_str())); } DASHBOARDS.update(&dashboard); - let path = dashboard_path(&dashboard.user_id, &format!("{}.json", dashboard_id)); + let path = dashboard_path(&user_id, &format!("{}.json", dashboard_id)); let store = CONFIG.storage().get_object_store(); let dashboard_bytes = serde_json::to_vec(&dashboard)?; @@ -77,31 +73,26 @@ pub async fn post(body: Bytes) -> Result { Ok((web::Json(dashboard), StatusCode::OK)) } -pub async fn update(req: HttpRequest, body: Bytes) -> Result { +pub async fn update(req: HttpRequest, body: Bytes) -> Result { + let user_id = get_user_from_request(&req)?; let dashboard_id = req .match_info() .get("dashboard_id") .ok_or(DashboardError::Metadata("No Dashboard Id Provided"))?; if DASHBOARDS.get_dashboard(dashboard_id).is_none() { - return Err(PostError::DashboardError(DashboardError::Metadata( - "Dashboard does not exist", - ))); + return Err(DashboardError::Metadata("Dashboard does not exist")); } let mut dashboard: Dashboard = serde_json::from_slice(&body)?; dashboard.dashboard_id = Some(dashboard_id.to_string()); dashboard.version = Some(CURRENT_DASHBOARD_VERSION.to_string()); for tile in dashboard.tiles.iter_mut() { if tile.tile_id.is_none() { - tile.tile_id = Some(format!( - "{}.{}", - &dashboard.user_id, - Utc::now().timestamp_micros() - )); + tile.tile_id = Some(get_hash(Utc::now().timestamp_micros().to_string().as_str())); } } DASHBOARDS.update(&dashboard); - let path = dashboard_path(&dashboard.user_id, &format!("{}.json", dashboard_id)); + let path = dashboard_path(&user_id, &format!("{}.json", dashboard_id)); let store = CONFIG.storage().get_object_store(); let dashboard_bytes = serde_json::to_vec(&dashboard)?; @@ -112,16 +103,13 @@ pub async fn update(req: HttpRequest, body: Bytes) -> Result Result { +pub async fn delete(req: HttpRequest) -> Result { + let user_id = get_user_from_request(&req)?; let dashboard_id = req .match_info() .get("dashboard_id") .ok_or(DashboardError::Metadata("No Dashboard Id Provided"))?; - let dashboard = DASHBOARDS - .get_dashboard(dashboard_id) - .ok_or(DashboardError::Metadata("Dashboard does not exist"))?; - - let path = dashboard_path(&dashboard.user_id, &format!("{}.json", dashboard_id)); + let path = dashboard_path(&user_id, &format!("{}.json", dashboard_id)); let store = CONFIG.storage().get_object_store(); store.delete_object(&path).await?; @@ -138,6 +126,8 @@ pub enum DashboardError { Serde(#[from] SerdeError), #[error("Cannot perform this operation: {0}")] Metadata(&'static str), + #[error("User does not exist")] + UserDoesNotExist(#[from] RBACError), } impl actix_web::ResponseError for DashboardError { @@ -146,6 +136,7 @@ impl actix_web::ResponseError for DashboardError { Self::ObjectStorage(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::Serde(_) => StatusCode::BAD_REQUEST, Self::Metadata(_) => StatusCode::BAD_REQUEST, + Self::UserDoesNotExist(_) => StatusCode::NOT_FOUND, } } diff --git a/server/src/handlers/http/users/filters.rs b/server/src/handlers/http/users/filters.rs index c6776840d..1d4d6695b 100644 --- a/server/src/handlers/http/users/filters.rs +++ b/server/src/handlers/http/users/filters.rs @@ -17,10 +17,11 @@ */ use crate::{ - handlers::http::ingest::PostError, + handlers::http::rbac::RBACError, option::CONFIG, storage::{object_storage::filter_path, ObjectStorageError}, users::filters::{Filter, CURRENT_FILTER_VERSION, FILTERS}, + utils::{get_hash, get_user_from_request}, }; use actix_web::{http::header::ContentType, web, HttpRequest, HttpResponse, Responder}; use bytes::Bytes; @@ -29,12 +30,8 @@ use http::StatusCode; use serde_json::Error as SerdeError; pub async fn list(req: HttpRequest) -> Result { - let user_id = req - .match_info() - .get("user_id") - .ok_or(FiltersError::Metadata("No User Id Provided"))?; - let filters = FILTERS.list_filters_by_user(user_id); - + let user_id = get_user_from_request(&req)?; + let filters = FILTERS.list_filters_by_user(&get_hash(&user_id)); Ok((web::Json(filters), StatusCode::OK)) } @@ -51,20 +48,17 @@ pub async fn get(req: HttpRequest) -> Result { Err(FiltersError::Metadata("Filter does not exist")) } -pub async fn post(body: Bytes) -> Result { +pub async fn post(req: HttpRequest, body: Bytes) -> Result { + let user_id = get_user_from_request(&req)?; let mut filter: Filter = serde_json::from_slice(&body)?; - let filter_id = format!( - "{}.{}.{}", - &filter.user_id, - &filter.stream_name, - Utc::now().timestamp_millis() - ); + let filter_id = get_hash(Utc::now().timestamp_micros().to_string().as_str()); filter.filter_id = Some(filter_id.clone()); + filter.user_id = Some(get_hash(&user_id)); filter.version = Some(CURRENT_FILTER_VERSION.to_string()); FILTERS.update(&filter); let path = filter_path( - &filter.user_id, + &user_id, &filter.stream_name, &format!("{}.json", filter_id), ); @@ -76,15 +70,14 @@ pub async fn post(body: Bytes) -> Result { Ok((web::Json(filter), StatusCode::OK)) } -pub async fn update(req: HttpRequest, body: Bytes) -> Result { +pub async fn update(req: HttpRequest, body: Bytes) -> Result { + let user_id = get_user_from_request(&req)?; let filter_id = req .match_info() .get("filter_id") .ok_or(FiltersError::Metadata("No Filter Id Provided"))?; if FILTERS.get_filter(filter_id).is_none() { - return Err(PostError::FiltersError(FiltersError::Metadata( - "Filter does not exist", - ))); + return Err(FiltersError::Metadata("Filter does not exist")); } let mut filter: Filter = serde_json::from_slice(&body)?; filter.filter_id = Some(filter_id.to_string()); @@ -92,7 +85,7 @@ pub async fn update(req: HttpRequest, body: Bytes) -> Result Result Result { +pub async fn delete(req: HttpRequest) -> Result { + let user_id = get_user_from_request(&req)?; let filter_id = req .match_info() .get("filter_id") @@ -114,7 +108,7 @@ pub async fn delete(req: HttpRequest) -> Result { .ok_or(FiltersError::Metadata("Filter does not exist"))?; let path = filter_path( - &filter.user_id, + &user_id, &filter.stream_name, &format!("{}.json", filter_id), ); @@ -134,6 +128,8 @@ pub enum FiltersError { Serde(#[from] SerdeError), #[error("Operation cannot be performed: {0}")] Metadata(&'static str), + #[error("User does not exist")] + UserDoesNotExist(#[from] RBACError), } impl actix_web::ResponseError for FiltersError { @@ -142,6 +138,7 @@ impl actix_web::ResponseError for FiltersError { Self::ObjectStorage(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::Serde(_) => StatusCode::BAD_REQUEST, Self::Metadata(_) => StatusCode::BAD_REQUEST, + Self::UserDoesNotExist(_) => StatusCode::NOT_FOUND, } } diff --git a/server/src/rbac.rs b/server/src/rbac.rs index bfd1be817..1679d7ffa 100644 --- a/server/src/rbac.rs +++ b/server/src/rbac.rs @@ -168,6 +168,10 @@ impl Users { Response::UnAuthorized } + + pub fn get_username_from_session(&self, session: &SessionKey) -> Option { + sessions().get_username(session).cloned() + } } fn roles_to_permission(roles: Vec) -> Vec { diff --git a/server/src/rbac/map.rs b/server/src/rbac/map.rs index b5b92e5a7..49db5af7f 100644 --- a/server/src/rbac/map.rs +++ b/server/src/rbac/map.rs @@ -224,6 +224,10 @@ impl Sessions { }) }) } + + pub fn get_username(&self, key: &SessionKey) -> Option<&String> { + self.active_sessions.get(key).map(|(username, _)| username) + } } // UserMap is a map of [username --> User] diff --git a/server/src/users/dashboards.rs b/server/src/users/dashboards.rs index fe666da16..420bc5172 100644 --- a/server/src/users/dashboards.rs +++ b/server/src/users/dashboards.rs @@ -78,7 +78,7 @@ pub struct Dashboard { name: String, description: String, pub dashboard_id: Option, - pub user_id: String, + pub user_id: Option, pub time_filter: Option, refresh_interval: u64, pub tiles: Vec, @@ -107,13 +107,13 @@ impl Dashboards { pub fn update(&self, dashboard: &Dashboard) { let mut s = self.0.write().expect(LOCK_EXPECT); - s.retain(|f| f.dashboard_id != dashboard.dashboard_id); + s.retain(|d| d.dashboard_id != dashboard.dashboard_id); s.push(dashboard.clone()); } pub fn delete_dashboard(&self, dashboard_id: &str) { let mut s = self.0.write().expect(LOCK_EXPECT); - s.retain(|f| f.dashboard_id != Some(dashboard_id.to_string())); + s.retain(|d| d.dashboard_id != Some(dashboard_id.to_string())); } pub fn get_dashboard(&self, dashboard_id: &str) -> Option { @@ -121,7 +121,7 @@ impl Dashboards { .read() .expect(LOCK_EXPECT) .iter() - .find(|f| f.dashboard_id == Some(dashboard_id.to_string())) + .find(|d| d.dashboard_id == Some(dashboard_id.to_string())) .cloned() } @@ -130,7 +130,7 @@ impl Dashboards { .read() .expect(LOCK_EXPECT) .iter() - .filter(|f| f.user_id == user_id) + .filter(|d| d.user_id.as_ref().unwrap() == user_id) .cloned() .collect() } diff --git a/server/src/users/filters.rs b/server/src/users/filters.rs index 33356270d..7ce5e2e11 100644 --- a/server/src/users/filters.rs +++ b/server/src/users/filters.rs @@ -28,7 +28,7 @@ pub const CURRENT_FILTER_VERSION: &str = "v1"; #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct Filter { pub version: Option, - pub user_id: String, + pub user_id: Option, pub stream_name: String, pub filter_name: String, pub filter_id: Option, @@ -111,7 +111,7 @@ impl Filters { .read() .expect(LOCK_EXPECT) .iter() - .filter(|f| f.user_id == user_id) + .filter(|f| f.user_id.as_ref().unwrap() == user_id) .cloned() .collect() } diff --git a/server/src/utils.rs b/server/src/utils.rs index 34630c375..1516b2ac1 100644 --- a/server/src/utils.rs +++ b/server/src/utils.rs @@ -22,7 +22,11 @@ pub mod header_parsing; pub mod json; pub mod uid; pub mod update; +use crate::handlers::http::rbac::RBACError; use crate::option::CONFIG; +use crate::rbac::Users; +use actix::extract_session_key_from_req; +use actix_web::HttpRequest; use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc}; use itertools::Itertools; use regex::Regex; @@ -321,6 +325,23 @@ pub fn extract_datetime(path: &str) -> Option { } } +pub fn get_user_from_request(req: &HttpRequest) -> Result { + let session_key = extract_session_key_from_req(req).unwrap(); + let user_id = Users.get_username_from_session(&session_key); + if user_id.is_none() { + return Err(RBACError::UserDoesNotExist); + } + let user_id = user_id.unwrap(); + Ok(user_id) +} + +pub fn get_hash(key: &str) -> String { + let mut hasher = Sha256::new(); + hasher.update(key); + let result = format!("{:x}", hasher.finalize()); + result +} + #[cfg(test)] mod tests { use chrono::DateTime; From 0df2645594ad65cdaed4764cafc9c743fbba7723 Mon Sep 17 00:00:00 2001 From: Nikhil Sinha Date: Tue, 10 Sep 2024 15:45:46 +0530 Subject: [PATCH 2/3] migration of existing dashboards and filters from v1 to v2 --- server/src/users/dashboards.rs | 49 +++++++++++++++++++++++++++--- server/src/users/filters.rs | 55 +++++++++++++++++++++++++++++++--- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/server/src/users/dashboards.rs b/server/src/users/dashboards.rs index 420bc5172..562dc6306 100644 --- a/server/src/users/dashboards.rs +++ b/server/src/users/dashboards.rs @@ -20,13 +20,17 @@ use std::sync::RwLock; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; +use serde_json::Value; -use crate::{metadata::LOCK_EXPECT, option::CONFIG}; +use crate::{ + metadata::LOCK_EXPECT, migration::to_bytes, option::CONFIG, + storage::object_storage::dashboard_path, utils::get_hash, +}; use super::TimeFilter; pub static DASHBOARDS: Lazy = Lazy::new(Dashboards::default); -pub const CURRENT_DASHBOARD_VERSION: &str = "v1"; +pub const CURRENT_DASHBOARD_VERSION: &str = "v2"; #[derive(Debug, Serialize, Deserialize, Default, Clone)] pub struct Tiles { @@ -94,8 +98,31 @@ impl Dashboards { let dashboards = store.get_all_dashboards().await.unwrap_or_default(); for dashboard in dashboards { - if let Ok(dashboard) = serde_json::from_slice::(&dashboard) { - this.push(dashboard); + if dashboard.is_empty() { + continue; + } + let mut dashboard_value = serde_json::from_slice::(&dashboard)?; + if let Some(meta) = dashboard_value.clone().as_object() { + let version = meta.get("version").and_then(|version| version.as_str()); + let user_id = meta.get("user_id").and_then(|user_id| user_id.as_str()); + let dashboard_id = meta + .get("dashboard_id") + .and_then(|dashboard_id| dashboard_id.as_str()); + + if version == Some("v1") { + dashboard_value = migrate_v1_v2(dashboard_value); + if let (Some(user_id), Some(dashboard_id)) = (user_id, dashboard_id) { + let path = dashboard_path(user_id, &format!("{}.json", dashboard_id)); + let dashboard_bytes = to_bytes(&dashboard_value); + store.put_object(&path, dashboard_bytes.clone()).await?; + if let Ok(dashboard) = serde_json::from_slice::(&dashboard_bytes) + { + this.push(dashboard); + } + } + } else if let Ok(dashboard) = serde_json::from_slice::(&dashboard) { + this.push(dashboard); + } } } @@ -135,3 +162,17 @@ impl Dashboards { .collect() } } + +fn migrate_v1_v2(mut dashboard_meta: Value) -> Value { + let dashboard_meta_map = dashboard_meta.as_object_mut().unwrap(); + let user_id = dashboard_meta_map.get("user_id").unwrap().clone(); + let str_user_id = user_id.as_str().unwrap(); + let user_id_hash = get_hash(str_user_id); + dashboard_meta_map.insert("user_id".to_owned(), Value::String(user_id_hash)); + dashboard_meta_map.insert( + "version".to_owned(), + Value::String(CURRENT_DASHBOARD_VERSION.into()), + ); + + dashboard_meta +} diff --git a/server/src/users/filters.rs b/server/src/users/filters.rs index 7ce5e2e11..358fab05b 100644 --- a/server/src/users/filters.rs +++ b/server/src/users/filters.rs @@ -18,13 +18,17 @@ use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; +use serde_json::Value; use std::sync::RwLock; use super::TimeFilter; -use crate::{metadata::LOCK_EXPECT, option::CONFIG}; +use crate::{ + metadata::LOCK_EXPECT, migration::to_bytes, option::CONFIG, + storage::object_storage::filter_path, utils::get_hash, +}; pub static FILTERS: Lazy = Lazy::new(Filters::default); -pub const CURRENT_FILTER_VERSION: &str = "v1"; +pub const CURRENT_FILTER_VERSION: &str = "v2"; #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct Filter { pub version: Option, @@ -75,8 +79,37 @@ impl Filters { let filters = store.get_all_saved_filters().await.unwrap_or_default(); for filter in filters { - if let Ok(filter) = serde_json::from_slice::(&filter) { - this.push(filter); + if filter.is_empty() { + continue; + } + + let mut filter_value = serde_json::from_slice::(&filter)?; + if let Some(meta) = filter_value.clone().as_object() { + let version = meta.get("version").and_then(|version| version.as_str()); + let user_id = meta.get("user_id").and_then(|user_id| user_id.as_str()); + let filter_id = meta + .get("filter_id") + .and_then(|filter_id| filter_id.as_str()); + let stream_name = meta + .get("stream_name") + .and_then(|stream_name| stream_name.as_str()); + + if version == Some("v1") { + filter_value = migrate_v1_v2(filter_value); + if let (Some(user_id), Some(stream_name), Some(filter_id)) = + (user_id, stream_name, filter_id) + { + let path = + filter_path(user_id, stream_name, &format!("{}.json", filter_id)); + let filter_bytes = to_bytes(&filter_value); + store.put_object(&path, filter_bytes.clone()).await?; + if let Ok(filter) = serde_json::from_slice::(&filter_bytes) { + this.push(filter); + } + } + } else if let Ok(filter) = serde_json::from_slice::(&filter) { + this.push(filter); + } } } @@ -116,3 +149,17 @@ impl Filters { .collect() } } + +fn migrate_v1_v2(mut filter_meta: Value) -> Value { + let filter_meta_map = filter_meta.as_object_mut().unwrap(); + let user_id = filter_meta_map.get("user_id").unwrap().clone(); + let str_user_id = user_id.as_str().unwrap(); + let user_id_hash = get_hash(str_user_id); + filter_meta_map.insert("user_id".to_owned(), Value::String(user_id_hash)); + filter_meta_map.insert( + "version".to_owned(), + Value::String(CURRENT_FILTER_VERSION.into()), + ); + + filter_meta +} From 9cff8586e6ac673bf9d743918ba0de7ba9adbe3d Mon Sep 17 00:00:00 2001 From: Nikhil Sinha Date: Tue, 10 Sep 2024 20:40:55 +0530 Subject: [PATCH 3/3] updated logic to get filter/dashboard based on user_id and filer_id/dashboard_id --- server/src/handlers/http/users/dashboards.rs | 14 ++++++++++++-- server/src/handlers/http/users/filters.rs | 7 ++++--- server/src/users/dashboards.rs | 9 ++++++--- server/src/users/filters.rs | 8 +++++--- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/server/src/handlers/http/users/dashboards.rs b/server/src/handlers/http/users/dashboards.rs index 928b84e65..65a020c97 100644 --- a/server/src/handlers/http/users/dashboards.rs +++ b/server/src/handlers/http/users/dashboards.rs @@ -38,12 +38,13 @@ pub async fn list(req: HttpRequest) -> Result { } pub async fn get(req: HttpRequest) -> Result { + let user_id = get_user_from_request(&req)?; let dashboard_id = req .match_info() .get("dashboard_id") .ok_or(DashboardError::Metadata("No Dashboard Id Provided"))?; - if let Some(dashboard) = DASHBOARDS.get_dashboard(dashboard_id) { + if let Some(dashboard) = DASHBOARDS.get_dashboard(dashboard_id, &get_hash(&user_id)) { return Ok((web::Json(dashboard), StatusCode::OK)); } @@ -79,7 +80,10 @@ pub async fn update(req: HttpRequest, body: Bytes) -> Result Result { .match_info() .get("dashboard_id") .ok_or(DashboardError::Metadata("No Dashboard Id Provided"))?; + if DASHBOARDS + .get_dashboard(dashboard_id, &get_hash(&user_id)) + .is_none() + { + return Err(DashboardError::Metadata("Dashboard does not exist")); + } let path = dashboard_path(&user_id, &format!("{}.json", dashboard_id)); let store = CONFIG.storage().get_object_store(); store.delete_object(&path).await?; diff --git a/server/src/handlers/http/users/filters.rs b/server/src/handlers/http/users/filters.rs index 1d4d6695b..5a924ea92 100644 --- a/server/src/handlers/http/users/filters.rs +++ b/server/src/handlers/http/users/filters.rs @@ -36,12 +36,13 @@ pub async fn list(req: HttpRequest) -> Result { } pub async fn get(req: HttpRequest) -> Result { + let user_id = get_user_from_request(&req)?; let filter_id = req .match_info() .get("filter_id") .ok_or(FiltersError::Metadata("No Filter Id Provided"))?; - if let Some(filter) = FILTERS.get_filter(filter_id) { + if let Some(filter) = FILTERS.get_filter(filter_id, &get_hash(&user_id)) { return Ok((web::Json(filter), StatusCode::OK)); } @@ -76,7 +77,7 @@ pub async fn update(req: HttpRequest, body: Bytes) -> Result Result { .get("filter_id") .ok_or(FiltersError::Metadata("No Filter Id Provided"))?; let filter = FILTERS - .get_filter(filter_id) + .get_filter(filter_id, &get_hash(&user_id)) .ok_or(FiltersError::Metadata("Filter does not exist"))?; let path = filter_path( diff --git a/server/src/users/dashboards.rs b/server/src/users/dashboards.rs index 562dc6306..fa9434614 100644 --- a/server/src/users/dashboards.rs +++ b/server/src/users/dashboards.rs @@ -143,12 +143,15 @@ impl Dashboards { s.retain(|d| d.dashboard_id != Some(dashboard_id.to_string())); } - pub fn get_dashboard(&self, dashboard_id: &str) -> Option { + pub fn get_dashboard(&self, dashboard_id: &str, user_id: &str) -> Option { self.0 .read() .expect(LOCK_EXPECT) .iter() - .find(|d| d.dashboard_id == Some(dashboard_id.to_string())) + .find(|d| { + d.dashboard_id == Some(dashboard_id.to_string()) + && d.user_id == Some(user_id.to_string()) + }) .cloned() } @@ -157,7 +160,7 @@ impl Dashboards { .read() .expect(LOCK_EXPECT) .iter() - .filter(|d| d.user_id.as_ref().unwrap() == user_id) + .filter(|d| d.user_id == Some(user_id.to_string())) .cloned() .collect() } diff --git a/server/src/users/filters.rs b/server/src/users/filters.rs index 358fab05b..45d2421dc 100644 --- a/server/src/users/filters.rs +++ b/server/src/users/filters.rs @@ -130,12 +130,14 @@ impl Filters { s.retain(|f| f.filter_id != Some(filter_id.to_string())); } - pub fn get_filter(&self, filter_id: &str) -> Option { + pub fn get_filter(&self, filter_id: &str, user_id: &str) -> Option { self.0 .read() .expect(LOCK_EXPECT) .iter() - .find(|f| f.filter_id == Some(filter_id.to_string())) + .find(|f| { + f.filter_id == Some(filter_id.to_string()) && f.user_id == Some(user_id.to_string()) + }) .cloned() } @@ -144,7 +146,7 @@ impl Filters { .read() .expect(LOCK_EXPECT) .iter() - .filter(|f| f.user_id.as_ref().unwrap() == user_id) + .filter(|f| f.user_id == Some(user_id.to_string())) .cloned() .collect() }