mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-21 00:49:17 +01:00
194 lines
6.8 KiB
Rust
194 lines
6.8 KiB
Rust
use crate::db_context::DbContext;
|
|
use crate::error::Error::{MissingBaseEnvironment, MultipleBaseEnvironments};
|
|
use crate::error::Result;
|
|
use crate::models::{Environment, EnvironmentIden, EnvironmentVariable};
|
|
use crate::util::UpdateSource;
|
|
use log::{info, warn};
|
|
|
|
impl<'a> DbContext<'a> {
|
|
pub fn get_environment(&self, id: &str) -> Result<Environment> {
|
|
self.find_one(EnvironmentIden::Id, id)
|
|
}
|
|
|
|
pub fn get_environment_by_folder_id(&self, folder_id: &str) -> Result<Option<Environment>> {
|
|
let mut environments: Vec<Environment> =
|
|
self.find_many(EnvironmentIden::ParentId, folder_id, None)?;
|
|
// Sort so we return the most recently updated environment
|
|
environments.sort_by(|a, b| b.updated_at.cmp(&a.updated_at));
|
|
Ok(environments.get(0).cloned())
|
|
}
|
|
|
|
pub fn get_base_environment(&self, workspace_id: &str) -> Result<Environment> {
|
|
let environments = self.list_environments_ensure_base(workspace_id)?;
|
|
let base_environments = environments
|
|
.into_iter()
|
|
.filter(|e| e.parent_model == "workspace")
|
|
.collect::<Vec<Environment>>();
|
|
|
|
if base_environments.len() > 1 {
|
|
return Err(MultipleBaseEnvironments(workspace_id.to_string()));
|
|
}
|
|
|
|
Ok(base_environments.first().cloned().ok_or(
|
|
// Should never happen because one should be created above if it does not exist
|
|
MissingBaseEnvironment(workspace_id.to_string()),
|
|
)?)
|
|
}
|
|
|
|
/// Lists environments and will create a base environment if one doesn't exist
|
|
pub fn list_environments_ensure_base(&self, workspace_id: &str) -> Result<Vec<Environment>> {
|
|
let mut environments = self.list_environments_dangerous(workspace_id)?;
|
|
|
|
let base_environment = environments.iter().find(|e| e.parent_model == "workspace");
|
|
|
|
if let None = base_environment {
|
|
let e = self.upsert_environment(
|
|
&Environment {
|
|
workspace_id: workspace_id.to_string(),
|
|
name: "Global Variables".to_string(),
|
|
parent_model: "workspace".to_string(),
|
|
..Default::default()
|
|
},
|
|
&UpdateSource::Background,
|
|
)?;
|
|
info!("Created base environment {} for {workspace_id}", e.id);
|
|
environments.push(e);
|
|
}
|
|
|
|
Ok(environments)
|
|
}
|
|
|
|
/// List environments for a workspace. Prefer list_environments_ensure_base()
|
|
fn list_environments_dangerous(&self, workspace_id: &str) -> Result<Vec<Environment>> {
|
|
Ok(self.find_many::<Environment>(EnvironmentIden::WorkspaceId, workspace_id, None)?)
|
|
}
|
|
|
|
pub fn delete_environment(
|
|
&self,
|
|
environment: &Environment,
|
|
source: &UpdateSource,
|
|
) -> Result<Environment> {
|
|
let deleted_environment = self.delete(environment, source)?;
|
|
|
|
// Recreate the base environment if we happened to delete it
|
|
self.list_environments_ensure_base(&environment.workspace_id)?;
|
|
|
|
Ok(deleted_environment)
|
|
}
|
|
|
|
pub fn delete_environment_by_id(&self, id: &str, source: &UpdateSource) -> Result<Environment> {
|
|
let environment = self.get_environment(id)?;
|
|
self.delete_environment(&environment, source)
|
|
}
|
|
|
|
pub fn duplicate_environment(
|
|
&self,
|
|
environment: &Environment,
|
|
source: &UpdateSource,
|
|
) -> Result<Environment> {
|
|
let mut environment = environment.clone();
|
|
environment.id = "".to_string();
|
|
self.upsert_environment(&environment, source)
|
|
}
|
|
|
|
/// Find other environments with the same parent folder
|
|
fn list_duplicate_folder_environments(&self, environment: &Environment) -> Vec<Environment> {
|
|
if environment.parent_model != "folder" {
|
|
return Vec::new();
|
|
}
|
|
|
|
self.list_environments_dangerous(&environment.workspace_id)
|
|
.unwrap_or_default()
|
|
.into_iter()
|
|
.filter(|e| {
|
|
e.id != environment.id
|
|
&& e.parent_model == "folder"
|
|
&& e.parent_id == environment.parent_id
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
pub fn upsert_environment(
|
|
&self,
|
|
environment: &Environment,
|
|
source: &UpdateSource,
|
|
) -> Result<Environment> {
|
|
let cleaned_variables = environment
|
|
.variables
|
|
.iter()
|
|
.filter(|v| !v.name.is_empty() || !v.value.is_empty())
|
|
.cloned()
|
|
.collect::<Vec<EnvironmentVariable>>();
|
|
|
|
// Sometimes a new environment can be created via sync/import, so we'll just delete
|
|
// the others when that happens. Not the best, but it's good for now.
|
|
let duplicates = self.list_duplicate_folder_environments(environment);
|
|
for duplicate in duplicates {
|
|
warn!(
|
|
"Deleting duplicate environment {} for folder {:?}",
|
|
duplicate.id, environment.parent_id
|
|
);
|
|
_ = self.delete(&duplicate, source);
|
|
}
|
|
|
|
// Automatically update the environment name based on the folder name
|
|
let mut name = environment.name.clone();
|
|
match (environment.parent_model.as_str(), environment.parent_id.as_deref()) {
|
|
("folder", Some(folder_id)) => {
|
|
if let Ok(folder) = self.get_folder(folder_id) {
|
|
name = format!("{} Environment", folder.name);
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
self.upsert(
|
|
&Environment {
|
|
name,
|
|
variables: cleaned_variables,
|
|
..environment.clone()
|
|
},
|
|
source,
|
|
)
|
|
}
|
|
|
|
pub fn resolve_environments(
|
|
&self,
|
|
workspace_id: &str,
|
|
folder_id: Option<&str>,
|
|
active_environment_id: Option<&str>,
|
|
) -> Result<Vec<Environment>> {
|
|
let mut environments = Vec::new();
|
|
|
|
if let Some(folder_id) = folder_id {
|
|
let folder = self.get_folder(folder_id)?;
|
|
|
|
// Add current folder's environment
|
|
if let Some(e) = self.get_environment_by_folder_id(folder_id)? {
|
|
environments.push(e);
|
|
};
|
|
|
|
// Recurse up
|
|
let ancestors = self.resolve_environments(
|
|
workspace_id,
|
|
folder.folder_id.as_deref(),
|
|
active_environment_id,
|
|
)?;
|
|
environments.extend(ancestors);
|
|
} else {
|
|
// Add active and base environments
|
|
if let Some(id) = active_environment_id {
|
|
if let Ok(e) = self.get_environment(&id) {
|
|
// Add active sub environment
|
|
environments.push(e);
|
|
};
|
|
};
|
|
|
|
// Add the base environment
|
|
environments.push(self.get_base_environment(workspace_id)?);
|
|
}
|
|
|
|
Ok(environments)
|
|
}
|
|
}
|