Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Commit

Permalink
Remember when fsck was last run and remind after 90d (gopasspw#1792)
Browse files Browse the repository at this point in the history
This adds a reminder when fsck was not run within the last 90d (or never).

RELEASE_NOTES=[ENHANCEMENT] Remind to run gopass update/fsck/audit after 90d
RELEASE_NOTES=[ENHANCEMENT] Added a env var to disable reminders
  • Loading branch information
dominikschulz authored Feb 15, 2021
1 parent 08b7d56 commit 203806f
Show file tree
Hide file tree
Showing 26 changed files with 177 additions and 8 deletions.
1 change: 1 addition & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Some configuration options are only available through setting environment variab
| `GOPASS_HOMEDIR` | `string` | Set this to the absolute path of the directory containing the `.config/` tree |
| `GOPASS_FORCE_UPDATE` | `bool` | Set to any non-empty value to force an update (if available) |
| `GOPASS_NO_NOTIFY` | `bool` | Set to any non-empty value to prevent notifications |
| `GOPASS_NO_REMINDER` | `bool` | Set to any non-empty value to prevent reminders |

Variables not exclusively used by gopass

Expand Down
14 changes: 12 additions & 2 deletions internal/action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path/filepath"

"github.com/gopasspw/gopass/internal/config"
"github.com/gopasspw/gopass/internal/reminder"
"github.com/gopasspw/gopass/internal/store/root"

"github.com/blang/semver/v4"
Expand All @@ -22,14 +23,15 @@ type Action struct {
Store *root.Store
cfg *config.Config
version semver.Version
rem *reminder.Store
}

// New returns a new Action wrapper
func New(cfg *config.Config, sv semver.Version) (*Action, error) {
return newAction(cfg, sv)
return newAction(cfg, sv, true)
}

func newAction(cfg *config.Config, sv semver.Version) (*Action, error) {
func newAction(cfg *config.Config, sv semver.Version, remind bool) (*Action, error) {
name := "gopass"
if len(os.Args) > 0 {
name = filepath.Base(os.Args[0])
Expand All @@ -42,6 +44,14 @@ func newAction(cfg *config.Config, sv semver.Version) (*Action, error) {
Store: root.New(cfg),
}

if remind {
r, err := reminder.New()
if err != nil {
return nil, err
}
act.rem = r
}

return act, nil
}

Expand Down
7 changes: 6 additions & 1 deletion internal/action/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/gopasspw/gopass/internal/backend"
"github.com/gopasspw/gopass/internal/backend/crypto/plain"
"github.com/gopasspw/gopass/internal/config"
"github.com/gopasspw/gopass/pkg/ctxutil"
"github.com/gopasspw/gopass/tests/gptest"

"github.com/blang/semver/v4"
Expand All @@ -26,16 +27,18 @@ func newMock(ctx context.Context, u *gptest.Unit) (*Action, error) {

ctx = backend.WithCryptoBackend(ctx, backend.Plain)
ctx = backend.WithStorageBackend(ctx, backend.GitFS)
act, err := newAction(cfg, semver.Version{})
act, err := newAction(cfg, semver.Version{}, false)
if err != nil {
return nil, err
}

fs := flag.NewFlagSet("default", flag.ContinueOnError)
c := cli.NewContext(cli.NewApp(), fs, nil)
c.Context = ctx
if err := act.IsInitialized(c); err != nil {
return nil, err
}

return act, nil
}

Expand All @@ -44,6 +47,8 @@ func TestAction(t *testing.T) {
defer u.Remove()

ctx := context.Background()
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
7 changes: 4 additions & 3 deletions internal/action/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ import (

// Audit validates passwords against common flaws
func (s *Action) Audit(c *cli.Context) error {
filter := c.Args().First()
s.rem.Reset("audit")

filter := c.Args().First()
ctx := ctxutil.WithGlobalFlags(c)

out.Printf(ctx, "Auditing passwords for common flaws ...")

out.Print(ctx, "Auditing passwords for common flaws ...")
t, err := s.Store.Tree(ctx)
if err != nil {
return ExitError(ExitList, err, "failed to get store tree: %s", err)
}

if filter != "" {
subtree, err := t.FindFolder(filter)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/action/clone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestCloneBackendIsStoredForMount(t *testing.T) {
cfg := config.Load()
cfg.Path = u.StoreDir("")

act, err := newAction(cfg, semver.Version{})
act, err := newAction(cfg, semver.Version{}, false)
require.NoError(t, err)
require.NotNil(t, act)

Expand Down
2 changes: 2 additions & 0 deletions internal/action/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"testing"

"github.com/gopasspw/gopass/pkg/ctxutil"
"github.com/gopasspw/gopass/tests/gptest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -36,6 +37,7 @@ func TestCommands(t *testing.T) {
defer u.Remove()

ctx := context.Background()
ctx = ctxutil.WithInteractive(ctx, false)
act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
2 changes: 2 additions & 0 deletions internal/action/completion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"github.com/gopasspw/gopass/internal/out"
"github.com/gopasspw/gopass/pkg/ctxutil"
"github.com/gopasspw/gopass/tests/gptest"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -34,6 +35,7 @@ func TestComplete(t *testing.T) {
}()

ctx := context.Background()
ctx = ctxutil.WithInteractive(ctx, false)
act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
2 changes: 2 additions & 0 deletions internal/action/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/gopasspw/gopass/internal/out"
"github.com/gopasspw/gopass/pkg/ctxutil"
"github.com/gopasspw/gopass/tests/gptest"

"github.com/stretchr/testify/assert"
Expand All @@ -19,6 +20,7 @@ func TestConfig(t *testing.T) {
defer u.Remove()

ctx := context.Background()
ctx = ctxutil.WithInteractive(ctx, false)
act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
1 change: 1 addition & 0 deletions internal/action/copy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func TestCopy(t *testing.T) {
defer u.Remove()

ctx := context.Background()
ctx = ctxutil.WithInteractive(ctx, false)
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithAutoClip(ctx, false)

Expand Down
1 change: 1 addition & 0 deletions internal/action/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestDelete(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)
act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
2 changes: 2 additions & 0 deletions internal/action/fsck.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (

// Fsck checks the store integrity
func (s *Action) Fsck(c *cli.Context) error {
s.rem.Reset("fsck")

ctx := ctxutil.WithGlobalFlags(c)
if c.IsSet("decrypt") {
ctx = leaf.WithFsckDecrypt(ctx, c.Bool("decrypt"))
Expand Down
1 change: 1 addition & 0 deletions internal/action/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func TestGenerate(t *testing.T) {
ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithAutoClip(ctx, false)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
Expand Down
1 change: 1 addition & 0 deletions internal/action/grep_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestGrep(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)
act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
4 changes: 3 additions & 1 deletion internal/action/history_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ func TestHistory(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

ctx = backend.WithCryptoBackend(ctx, backend.Plain)
ctx = backend.WithStorageBackend(ctx, backend.GitFS)

cfg := config.New()
cfg.Path = u.StoreDir("")
act, err := newAction(cfg, semver.Version{})
act, err := newAction(cfg, semver.Version{}, false)
require.NoError(t, err)
require.NotNil(t, act)

Expand Down
1 change: 1 addition & 0 deletions internal/action/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func (s *Action) IsInitialized(c *cli.Context) error {
}
if inited {
debug.Log("Store is already initialized")
s.printReminder(ctx)
return nil
}

Expand Down
2 changes: 2 additions & 0 deletions internal/action/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestList(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
Expand Down Expand Up @@ -95,6 +96,7 @@ func TestListLimit(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
Expand Down
2 changes: 2 additions & 0 deletions internal/action/move_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func TestMove(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
2 changes: 2 additions & 0 deletions internal/action/otp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ func TestOTP(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
2 changes: 2 additions & 0 deletions internal/action/recipients_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ func TestRecipients(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
39 changes: 39 additions & 0 deletions internal/action/reminder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package action

import (
"context"
"os"

"github.com/gopasspw/gopass/internal/out"
"github.com/gopasspw/gopass/pkg/ctxutil"
)

func (s *Action) printReminder(ctx context.Context) {
if !ctxutil.IsInteractive(ctx) {
return
}
if !ctxutil.IsTerminal(ctx) {
return
}
if sv := os.Getenv("GOPASS_NO_REMINDER"); sv != "" {
return
}

// Note: We only want to print one reminder per day (at most).
// So we intentionally return after printing one, leaving the others
// for the following days.
if s.rem.Overdue("update") {
out.Notice(ctx, "You haven't checked for updates in a while. Run 'gopass version' or 'gopass update' to check.")
return
}

if s.rem.Overdue("fsck") {
out.Notice(ctx, "You haven't run 'gopass fsck' in a while.")
return
}

if s.rem.Overdue("audit") {
out.Notice(ctx, "You haven't run 'gopass audit' in a while.")
return
}
}
8 changes: 8 additions & 0 deletions internal/action/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ func TestShowMulti(t *testing.T) {
ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithTerminal(ctx, false)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down Expand Up @@ -212,6 +214,8 @@ func TestShowAutoClip(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down Expand Up @@ -327,6 +331,8 @@ func TestShowHandleRevision(t *testing.T) {
ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithTerminal(ctx, false)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down Expand Up @@ -380,6 +386,8 @@ func TestShowPrintQR(t *testing.T) {
ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithTerminal(ctx, false)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)
require.NotNil(t, act)
Expand Down
2 changes: 2 additions & 0 deletions internal/action/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (

// Update will start the interactive update assistant
func (s *Action) Update(c *cli.Context) error {
s.rem.Reset("update")

ctx := ctxutil.WithGlobalFlags(c)

if s.version.String() == "0.0.0+HEAD" {
Expand Down
1 change: 1 addition & 0 deletions internal/action/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func (s *Action) checkVersion(ctx context.Context, u chan string) {
notice += " or via your package manager"
u <- color.YellowString(notice)
} else {
s.rem.Reset("update")
debug.Log("gopass is up-to-date (local: %q, GitHub: %q)", s.version, r.Version)
}
u <- ""
Expand Down
2 changes: 2 additions & 0 deletions internal/action/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func TestVersion(t *testing.T) {

ctx := context.Background()
ctx = ctxutil.WithAlwaysYes(ctx, true)
ctx = ctxutil.WithInteractive(ctx, false)

act, err := newMock(ctx, u)
require.NoError(t, err)

Expand Down
4 changes: 4 additions & 0 deletions internal/backend/storage/gitfs/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,9 @@ func (g *Git) Path() string {

// Fsck checks the storage integrity
func (g *Git) Fsck(ctx context.Context) error {
// ensure sane git config
if err := g.fixConfig(ctx); err != nil {
return fmt.Errorf("failed to fix git config: %w", err)
}
return g.fs.Fsck(ctx)
}
Loading

0 comments on commit 203806f

Please sign in to comment.