use super::{conflict_free_name, merge_headers}; use crate::client_db::ClientDb; use crate::connection_or_tx::ConnectionOrTx; use crate::error::Result; use crate::models::{ AnyModel, Environment, EnvironmentIden, Folder, FolderIden, GrpcRequest, GrpcRequestIden, HttpRequest, HttpRequestHeader, HttpRequestIden, ResolvedHttpRequestSettings, ResolvedSetting, WebsocketRequest, WebsocketRequestIden, }; use crate::util::UpdateSource; use serde_json::Value; use std::collections::BTreeMap; impl<'a> ClientDb<'a> { pub fn get_folder(&self, id: &str) -> Result { self.find_one(FolderIden::Id, id) } pub fn list_folders(&self, workspace_id: &str) -> Result> { self.find_many(FolderIden::WorkspaceId, workspace_id, None) } pub fn delete_folder(&self, folder: &Folder, source: &UpdateSource) -> Result { match self.conn() { ConnectionOrTx::Connection(_) => {} ConnectionOrTx::Transaction(_) => {} } let fid = &folder.id; for m in self.find_many::(HttpRequestIden::FolderId, fid, None)? { self.delete_http_request(&m, source)?; } for m in self.find_many::(GrpcRequestIden::FolderId, fid, None)? { self.delete_grpc_request(&m, source)?; } for m in self.find_many::(WebsocketRequestIden::FolderId, fid, None)? { self.delete_websocket_request(&m, source)?; } for e in self.find_many(EnvironmentIden::ParentId, fid, None)? { self.delete_environment(&e, source)?; } // Recurse down into child folders for folder in self.find_many::(FolderIden::FolderId, fid, None)? { self.delete_folder(&folder, source)?; } self.delete(folder, source) } pub fn delete_folder_by_id(&self, id: &str, source: &UpdateSource) -> Result { let folder = self.get_folder(id)?; self.delete_folder(&folder, source) } pub fn upsert_folder(&self, folder: &Folder, source: &UpdateSource) -> Result { self.upsert(folder, source) } pub fn duplicate_folder(&self, src_folder: &Folder, source: &UpdateSource) -> Result { let fid = &src_folder.id; let mut folder = Folder { id: "".into(), sort_priority: src_folder.sort_priority + 0.001, ..src_folder.clone() }; let sibling_names = self .list_folders(&folder.workspace_id)? .into_iter() .filter(|f| f.folder_id == folder.folder_id) .map(|f| f.name) .collect::>(); folder.name = conflict_free_name(&folder.name, &sibling_names); let new_folder = self.upsert_folder(&folder, source)?; for m in self.find_many::(HttpRequestIden::FolderId, fid, None)? { self.upsert_http_request( &HttpRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), ..m }, source, )?; } for m in self.find_many::(WebsocketRequestIden::FolderId, fid, None)? { self.upsert_websocket_request( &WebsocketRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), ..m }, source, )?; } for m in self.find_many::(GrpcRequestIden::FolderId, fid, None)? { self.upsert_grpc_request( &GrpcRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), ..m }, source, )?; } for m in self.find_many::(EnvironmentIden::ParentId, fid, None)? { self.upsert_environment( &Environment { id: "".into(), parent_id: Some(new_folder.id.clone()), ..m }, source, )?; } for m in self.find_many::(FolderIden::FolderId, fid, None)? { // Recurse down self.duplicate_folder(&Folder { folder_id: Some(new_folder.id.clone()), ..m }, source)?; } Ok(new_folder) } pub fn resolve_auth_for_folder( &self, folder: &Folder, ) -> Result<(Option, BTreeMap, String)> { if let Some(at) = folder.authentication_type.clone() { return Ok((Some(at), folder.authentication.clone(), folder.id.clone())); } if let Some(folder_id) = folder.folder_id.clone() { let folder = self.get_folder(&folder_id)?; return self.resolve_auth_for_folder(&folder); } let workspace = self.get_workspace(&folder.workspace_id)?; Ok(self.resolve_auth_for_workspace(&workspace)) } pub fn resolve_headers_for_folder(&self, folder: &Folder) -> Result> { let mut headers = Vec::new(); if let Some(folder_id) = folder.folder_id.clone() { let parent_folder = self.get_folder(&folder_id)?; let mut folder_headers = self.resolve_headers_for_folder(&parent_folder)?; // NOTE: Add parent headers first, so overrides are logical headers.append(&mut folder_headers); } else { let workspace = self.get_workspace(&folder.workspace_id)?; let mut workspace_headers = self.resolve_headers_for_workspace(&workspace); headers.append(&mut workspace_headers); } Ok(merge_headers(headers, folder.headers.clone())) } pub fn resolve_settings_for_folder( &self, folder: &Folder, ) -> Result { let parent = if let Some(folder_id) = folder.folder_id.clone() { let parent_folder = self.get_folder(&folder_id)?; self.resolve_settings_for_folder(&parent_folder)? } else { let workspace = self.get_workspace(&folder.workspace_id)?; self.resolve_settings_for_workspace(&workspace) }; Ok(ResolvedHttpRequestSettings { validate_certificates: if folder.setting_validate_certificates.enabled { ResolvedSetting::from_model( folder.setting_validate_certificates.value, AnyModel::Folder(folder.clone()), ) } else { parent.validate_certificates }, follow_redirects: if folder.setting_follow_redirects.enabled { ResolvedSetting::from_model( folder.setting_follow_redirects.value, AnyModel::Folder(folder.clone()), ) } else { parent.follow_redirects }, request_timeout: if folder.setting_request_timeout.enabled { ResolvedSetting::from_model( folder.setting_request_timeout.value, AnyModel::Folder(folder.clone()), ) } else { parent.request_timeout }, request_message_size: if folder.setting_request_message_size.enabled { ResolvedSetting::from_model( folder.setting_request_message_size.value, AnyModel::Folder(folder.clone()), ) } else { parent.request_message_size }, send_cookies: if folder.setting_send_cookies.enabled { ResolvedSetting::from_model( folder.setting_send_cookies.value, AnyModel::Folder(folder.clone()), ) } else { parent.send_cookies }, store_cookies: if folder.setting_store_cookies.enabled { ResolvedSetting::from_model( folder.setting_store_cookies.value, AnyModel::Folder(folder.clone()), ) } else { parent.store_cookies }, }) } }