Add support for running hishtory redact while offline, even though this may lead to syncing inconsistency bugs

This commit is contained in:
David Dworken 2023-10-22 11:43:56 -07:00
parent c613e696b4
commit 2b1af986d8
No known key found for this signature in database
3 changed files with 22 additions and 10 deletions

View File

@ -26,14 +26,26 @@ var redactCmd = &cobra.Command{
DisableFlagParsing: true, DisableFlagParsing: true,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
ctx := hctx.MakeContext() 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.RetrieveAdditionalEntriesFromRemote(ctx, "redact"))
lib.CheckFatalError(lib.ProcessDeletionRequests(ctx)) lib.CheckFatalError(lib.ProcessDeletionRequests(ctx))
query := strings.Join(args, " ") 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) tx, err := lib.MakeWhereQueryFromSearch(ctx, hctx.GetDb(ctx), query)
if err != nil { if err != nil {
return err return err
@ -43,17 +55,17 @@ func redact(ctx context.Context, query string, force bool) error {
if res.Error != nil { if res.Error != nil {
return res.Error return res.Error
} }
if force { if skipUserConfirmation {
fmt.Printf("Permanently deleting %d entries\n", len(historyEntries)) fmt.Printf("Permanently deleting %d entries\n", len(historyEntries))
} else { } 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) reader := bufio.NewReader(os.Stdin)
resp, err := reader.ReadString('\n') resp, err := reader.ReadString('\n')
if err != nil { if err != nil {
return fmt.Errorf("failed to read response: %w", err) return fmt.Errorf("failed to read response: %w", err)
} }
if strings.TrimSpace(resp) != "y" { 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 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)) 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) err = deleteOnRemoteInstances(ctx, historyEntries)
if err != nil { if err != nil && !skipOnlineRedaction {
return err return err
} }
return nil return nil

View File

@ -569,7 +569,7 @@ func IsOfflineError(ctx context.Context, err error) bool {
strings.Contains(err.Error(), "connect: connection refused") { strings.Contains(err.Error(), "connect: connection refused") {
return true return true
} }
if !isHishtoryServerUp(ctx) { if !CanReachHishtoryServer(ctx) {
// If the backend server is down, then treat all errors as offline errors // If the backend server is down, then treat all errors as offline errors
return true return true
} }
@ -577,7 +577,7 @@ func IsOfflineError(ctx context.Context, err error) bool {
return false return false
} }
func isHishtoryServerUp(ctx context.Context) bool { func CanReachHishtoryServer(ctx context.Context) bool {
_, err := ApiGet(ctx, "/api/v1/ping") _, err := ApiGet(ctx, "/api/v1/ping")
return err == nil return err == nil
} }

View File

@ -291,11 +291,11 @@ func TestAugmentedIsOfflineError(t *testing.T) {
ctx := hctx.MakeContext() ctx := hctx.MakeContext()
// By default, when the hishtory server is up, then IsOfflineError checks the error msg // 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"))) 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 // 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") 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"))) require.True(t, IsOfflineError(ctx, fmt.Errorf("unchecked error type")))
} }