From 2b1af986d8b5dd56b092963bf280b3960167b862 Mon Sep 17 00:00:00 2001 From: David Dworken Date: Sun, 22 Oct 2023 11:43:56 -0700 Subject: [PATCH] Add support for running hishtory redact while offline, even though this may lead to syncing inconsistency bugs --- client/cmd/redact.go | 24 ++++++++++++++++++------ client/lib/lib.go | 4 ++-- client/lib/lib_test.go | 4 ++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/client/cmd/redact.go b/client/cmd/redact.go index 8f0af68..a2e9dbf 100644 --- a/client/cmd/redact.go +++ b/client/cmd/redact.go @@ -26,14 +26,26 @@ var redactCmd = &cobra.Command{ DisableFlagParsing: true, Run: func(cmd *cobra.Command, args []string) { ctx := hctx.MakeContext() + skipOnlineRedaction := false + if !lib.CanReachHishtoryServer(ctx) { + fmt.Printf("Cannot reach hishtory backend (is this device offline?) so redaction will only apply to this device and not other synced devices. Would you like to continue with a local-only redaction anyways? [y/N] ") + reader := bufio.NewReader(os.Stdin) + resp, err := reader.ReadString('\n') + lib.CheckFatalError(err) + if strings.TrimSpace(resp) != "y" { + fmt.Printf("Aborting redact per user response of %#v\n", strings.TrimSpace(resp)) + return + } + skipOnlineRedaction = true + } lib.CheckFatalError(lib.RetrieveAdditionalEntriesFromRemote(ctx, "redact")) lib.CheckFatalError(lib.ProcessDeletionRequests(ctx)) query := strings.Join(args, " ") - lib.CheckFatalError(redact(ctx, query, os.Getenv("HISHTORY_REDACT_FORCE") != "")) + lib.CheckFatalError(redact(ctx, query, os.Getenv("HISHTORY_REDACT_FORCE") != "", skipOnlineRedaction)) }, } -func redact(ctx context.Context, query string, force bool) error { +func redact(ctx context.Context, query string, skipUserConfirmation, skipOnlineRedaction bool) error { tx, err := lib.MakeWhereQueryFromSearch(ctx, hctx.GetDb(ctx), query) if err != nil { return err @@ -43,17 +55,17 @@ func redact(ctx context.Context, query string, force bool) error { if res.Error != nil { return res.Error } - if force { + if skipUserConfirmation { fmt.Printf("Permanently deleting %d entries\n", len(historyEntries)) } else { - fmt.Printf("This will permanently delete %d entries, are you sure? [y/N]", len(historyEntries)) + fmt.Printf("This will permanently delete %d entries, are you sure? [y/N] ", len(historyEntries)) reader := bufio.NewReader(os.Stdin) resp, err := reader.ReadString('\n') if err != nil { return fmt.Errorf("failed to read response: %w", err) } if strings.TrimSpace(resp) != "y" { - fmt.Printf("Aborting delete per user response of %#v\n", strings.TrimSpace(resp)) + fmt.Printf("Aborting redact per user response of %#v\n", strings.TrimSpace(resp)) return nil } } @@ -69,7 +81,7 @@ func redact(ctx context.Context, query string, force bool) error { return fmt.Errorf("DB deleted %d rows, when we only expected to delete %d rows, something may have gone wrong", res.RowsAffected, len(historyEntries)) } err = deleteOnRemoteInstances(ctx, historyEntries) - if err != nil { + if err != nil && !skipOnlineRedaction { return err } return nil diff --git a/client/lib/lib.go b/client/lib/lib.go index 3a1cbe5..a0234dc 100644 --- a/client/lib/lib.go +++ b/client/lib/lib.go @@ -569,7 +569,7 @@ func IsOfflineError(ctx context.Context, err error) bool { strings.Contains(err.Error(), "connect: connection refused") { return true } - if !isHishtoryServerUp(ctx) { + if !CanReachHishtoryServer(ctx) { // If the backend server is down, then treat all errors as offline errors return true } @@ -577,7 +577,7 @@ func IsOfflineError(ctx context.Context, err error) bool { return false } -func isHishtoryServerUp(ctx context.Context) bool { +func CanReachHishtoryServer(ctx context.Context) bool { _, err := ApiGet(ctx, "/api/v1/ping") return err == nil } diff --git a/client/lib/lib_test.go b/client/lib/lib_test.go index c0cbb8b..1b007c8 100644 --- a/client/lib/lib_test.go +++ b/client/lib/lib_test.go @@ -291,11 +291,11 @@ func TestAugmentedIsOfflineError(t *testing.T) { ctx := hctx.MakeContext() // By default, when the hishtory server is up, then IsOfflineError checks the error msg - require.True(t, isHishtoryServerUp(ctx)) + require.True(t, CanReachHishtoryServer(ctx)) require.False(t, IsOfflineError(ctx, fmt.Errorf("unchecked error type"))) // When the hishtory server is down, then all error messages are treated as being due to offline errors os.Setenv("HISHTORY_SIMULATE_NETWORK_ERROR", "1") - require.False(t, isHishtoryServerUp(ctx)) + require.False(t, CanReachHishtoryServer(ctx)) require.True(t, IsOfflineError(ctx, fmt.Errorf("unchecked error type"))) }