Fix workspace creation, reveal sync dir, and don't update timestamps on sync/import

This commit is contained in:
Gregory Schier
2025-01-09 07:50:23 -08:00
parent 0a7257c55a
commit f694456ddc
33 changed files with 312 additions and 219 deletions

View File

@@ -33,6 +33,7 @@
"opener:allow-open-url",
"opener:allow-open-path",
"opener:allow-default-urls",
"opener:allow-reveal-item-in-dir",
"core:webview:allow-set-webview-zoom",
"core:window:allow-close",
"core:window:allow-internal-toggle-maximize",

View File

@@ -1 +1 @@
{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-dir","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"opener:allow-open-url","opener:allow-open-path","opener:allow-default-urls","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-internal-toggle-maximize","core:window:allow-is-fullscreen","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-show","core:window:allow-start-dragging","core:window:allow-theme","core:window:allow-toggle-maximize","core:window:allow-unmaximize","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","yaak-license:default","yaak-sync:default"]}}
{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-dir","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"opener:allow-open-url","opener:allow-open-path","opener:allow-default-urls","opener:allow-reveal-item-in-dir","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-internal-toggle-maximize","core:window:allow-is-fullscreen","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-show","core:window:allow-start-dragging","core:window:allow-theme","core:window:allow-toggle-maximize","core:window:allow-unmaximize","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","yaak-license:default","yaak-sync:default"]}}

View File

@@ -9,7 +9,7 @@ use crate::models::{
WorkspaceMetaIden,
};
use crate::plugin::SqliteConnection;
use chrono::NaiveDateTime;
use chrono::{NaiveDateTime, Utc};
use log::{debug, error, info, warn};
use nanoid::nanoid;
use rusqlite::OptionalExtension;
@@ -278,8 +278,8 @@ pub async fn upsert_workspace<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, workspace.created_at).into(),
timestamp_for_upsert(update_source, workspace.updated_at).into(),
trimmed_name.into(),
workspace.description.into(),
workspace.setting_follow_redirects.into(),
@@ -297,6 +297,7 @@ pub async fn upsert_workspace<R: Runtime>(
WorkspaceIden::SettingRequestTimeout,
WorkspaceIden::SettingValidateCertificates,
])
.values([(WorkspaceIden::UpdatedAt, CurrentTimestamp.into())])
.to_owned(),
)
.returning_all()
@@ -333,8 +334,8 @@ pub async fn upsert_workspace_meta<R: Runtime>(
.values_panic([
id.as_str().into(),
workspace_meta.workspace_id.into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, workspace_meta.created_at).into(),
timestamp_for_upsert(update_source, workspace_meta.updated_at).into(),
workspace_meta.setting_sync_dir.into(),
])
.on_conflict(
@@ -500,8 +501,8 @@ pub async fn upsert_grpc_request<R: Runtime>(
])
.values_panic([
id.into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, request.created_at).into(),
timestamp_for_upsert(update_source, request.updated_at).into(),
trimmed_name.into(),
request.description.into(),
request.workspace_id.into(),
@@ -612,8 +613,8 @@ pub async fn upsert_grpc_connection<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, connection.created_at).into(),
timestamp_for_upsert(update_source, connection.updated_at).into(),
connection.workspace_id.as_str().into(),
connection.request_id.as_str().into(),
connection.service.as_str().into(),
@@ -771,8 +772,8 @@ pub async fn upsert_grpc_event<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, event.created_at).into(),
timestamp_for_upsert(update_source, event.updated_at).into(),
event.workspace_id.as_str().into(),
event.request_id.as_str().into(),
event.connection_id.as_str().into(),
@@ -859,8 +860,8 @@ pub async fn upsert_cookie_jar<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, cookie_jar.created_at).into(),
timestamp_for_upsert(update_source, cookie_jar.updated_at).into(),
cookie_jar.workspace_id.as_str().into(),
trimmed_name.into(),
serde_json::to_string(&cookie_jar.cookies)?.into(),
@@ -1064,8 +1065,8 @@ pub async fn upsert_environment<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, environment.created_at).into(),
timestamp_for_upsert(update_source, environment.updated_at).into(),
environment.environment_id.into(),
environment.workspace_id.into(),
trimmed_name.into(),
@@ -1174,8 +1175,8 @@ pub async fn upsert_plugin<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
timestamp_for_upsert(update_source, plugin.created_at).into(),
timestamp_for_upsert(update_source, plugin.updated_at).into(),
plugin.checked_at.into(),
plugin.directory.into(),
plugin.url.into(),
@@ -1276,15 +1277,15 @@ pub async fn delete_folder<R: Runtime>(
pub async fn upsert_folder<R: Runtime>(
window: &WebviewWindow<R>,
r: Folder,
folder: Folder,
update_source: &UpdateSource,
) -> Result<Folder> {
let id = match r.id.as_str() {
let id = match folder.id.as_str() {
"" => generate_model_id(ModelType::TypeFolder),
_ => r.id.to_string(),
_ => folder.id.to_string(),
};
let trimmed_name = r.name.trim();
let trimmed_name = folder.name.trim();
let dbm = &*window.app_handle().state::<SqliteConnection>();
let db = dbm.0.lock().await.get().unwrap();
@@ -1303,13 +1304,13 @@ pub async fn upsert_folder<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
r.workspace_id.as_str().into(),
r.folder_id.as_ref().map(|s| s.as_str()).into(),
timestamp_for_upsert(update_source, folder.created_at).into(),
timestamp_for_upsert(update_source, folder.updated_at).into(),
folder.workspace_id.as_str().into(),
folder.folder_id.as_ref().map(|s| s.as_str()).into(),
trimmed_name.into(),
r.description.into(),
r.sort_priority.into(),
folder.description.into(),
folder.sort_priority.into(),
])
.on_conflict(
OnConflict::column(GrpcEventIden::Id)
@@ -1419,14 +1420,14 @@ pub async fn duplicate_folder<R: Runtime>(
pub async fn upsert_http_request<R: Runtime>(
window: &WebviewWindow<R>,
r: HttpRequest,
request: HttpRequest,
update_source: &UpdateSource,
) -> Result<HttpRequest> {
let id = match r.id.as_str() {
let id = match request.id.as_str() {
"" => generate_model_id(ModelType::TypeHttpRequest),
_ => r.id.to_string(),
_ => request.id.to_string(),
};
let trimmed_name = r.name.trim();
let trimmed_name = request.name.trim();
let dbm = &*window.app_handle().state::<SqliteConnection>();
let db = dbm.0.lock().await.get().unwrap();
@@ -1453,21 +1454,21 @@ pub async fn upsert_http_request<R: Runtime>(
])
.values_panic([
id.as_str().into(),
CurrentTimestamp.into(),
CurrentTimestamp.into(),
r.workspace_id.into(),
r.folder_id.as_ref().map(|s| s.as_str()).into(),
timestamp_for_upsert(update_source, request.created_at).into(),
timestamp_for_upsert(update_source, request.updated_at).into(),
request.workspace_id.into(),
request.folder_id.as_ref().map(|s| s.as_str()).into(),
trimmed_name.into(),
r.description.into(),
r.url.into(),
serde_json::to_string(&r.url_parameters)?.into(),
r.method.into(),
serde_json::to_string(&r.body)?.into(),
r.body_type.as_ref().map(|s| s.as_str()).into(),
serde_json::to_string(&r.authentication)?.into(),
r.authentication_type.as_ref().map(|s| s.as_str()).into(),
serde_json::to_string(&r.headers)?.into(),
r.sort_priority.into(),
request.description.into(),
request.url.into(),
serde_json::to_string(&request.url_parameters)?.into(),
request.method.into(),
serde_json::to_string(&request.body)?.into(),
request.body_type.as_ref().map(|s| s.as_str()).into(),
serde_json::to_string(&request.authentication)?.into(),
request.authentication_type.as_ref().map(|s| s.as_str()).into(),
serde_json::to_string(&request.headers)?.into(),
request.sort_priority.into(),
])
.on_conflict(
OnConflict::column(GrpcEventIden::Id)
@@ -2167,7 +2168,7 @@ pub async fn get_workspace_export_resources<R: Runtime>(
let mut data = WorkspaceExport {
yaak_version: mgr.package_info().version.clone().to_string(),
yaak_schema: 2,
timestamp: chrono::Utc::now().naive_utc(),
timestamp: Utc::now().naive_utc(),
resources: BatchUpsertResult {
workspaces: Vec::new(),
environments: Vec::new(),
@@ -2197,3 +2198,21 @@ pub async fn get_workspace_export_resources<R: Runtime>(
data
}
// Generate the created_at or updated_at timestamps for an upsert operation, depending on the ID
// provided.
fn timestamp_for_upsert(update_source: &UpdateSource, dt: NaiveDateTime) -> NaiveDateTime {
match update_source {
// Sync and import operations always preserve timestamps
UpdateSource::Sync | UpdateSource::Import => {
if dt.and_utc().timestamp() == 0 {
// Sometimes data won't have timestamps (partial data)
Utc::now().naive_utc()
} else {
dt
}
},
// Other sources will always update to the latest time
_ => Utc::now().naive_utc(),
}
}

View File

@@ -1,7 +1,7 @@
use crate::error::Result;
use crate::sync::{
apply_sync_ops, apply_sync_state_ops, compute_sync_ops, get_db_candidates, get_fs_candidates,
SyncOp,
FsCandidate, SyncOp,
};
use crate::watch::{watch_directory, WatchEvent};
use chrono::Utc;
@@ -23,16 +23,18 @@ pub async fn calculate<R: Runtime>(
let fs_candidates = get_fs_candidates(sync_dir)
.await?
.into_iter()
// Strip out any non-workspace candidates
// Only keep items in the same workspace
.filter(|fs| fs.model.workspace_id() == workspace_id)
.collect();
.collect::<Vec<FsCandidate>>();
// println!("\ndb_candidates: \n{}\n", serde_json::to_string_pretty(&db_candidates)?);
// println!("\nfs_candidates: \n{}\n", serde_json::to_string_pretty(&fs_candidates)?);
Ok(compute_sync_ops(db_candidates, fs_candidates))
}
#[command]
pub async fn calculate_fs(dir: &Path) -> Result<Vec<SyncOp>> {
let db_candidates = Vec::new();
let fs_candidates = get_fs_candidates(Path::new(&dir)).await?;
let fs_candidates = get_fs_candidates(dir).await?;
Ok(compute_sync_ops(db_candidates, fs_candidates))
}

View File

@@ -76,7 +76,8 @@ impl Display for SyncOp {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub(crate) enum DbCandidate {
Added(SyncModel),
Modified(SyncModel, SyncState),