diff --git a/Makefile b/Makefile index 568334e..533f874 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ cover: test go tool cover -html=coverage.txt fmt: - find . -name '*.go' | while read -r file; do gofumpt -w -s "$$file"; gofumports -w "$$file"; done + find . -name '*.go' | while read -r file; do gofumpt -w "$$file"; gofumports -w "$$file"; done lint: golangci-lint run diff --git a/cache.go b/cache.go index e9a64d7..b00f8e2 100644 --- a/cache.go +++ b/cache.go @@ -3,8 +3,9 @@ package sncli import ( "errors" "fmt" - "github.com/jonhadfield/gosn-v2/cache" "os" + + "github.com/jonhadfield/gosn-v2/cache" ) func Resync(s *cache.Session, cacheDBDir, appName string) error { diff --git a/cmd/sncli/main.go b/cmd/sncli/main.go index e15f9e7..32236a4 100644 --- a/cmd/sncli/main.go +++ b/cmd/sncli/main.go @@ -1,10 +1,10 @@ package main import ( + "bytes" "encoding/json" "errors" "fmt" - "golang.org/x/term" "os" "sort" "strconv" @@ -12,11 +12,13 @@ import ( "syscall" "time" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" + "github.com/jonhadfield/gosn-v2/session" sncli "github.com/jonhadfield/sn-cli" "github.com/spf13/viper" "github.com/urfave/cli" + "golang.org/x/term" "gopkg.in/yaml.v2" ) @@ -76,7 +78,6 @@ func getOpts(c *cli.Context) (out configOptsOutput, err error) { if viper.GetString("server") != "" { out.server = viper.GetString("server") - } out.cacheDBDir = viper.GetString("cachedb_dir") @@ -410,6 +411,37 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { msg, err = processDeleteNote(c, opts) + return err + }, + }, + { + Name: "item", + Usage: "delete any standard notes item", + BashComplete: func(c *cli.Context) { + delNoteOpts := []string{"--uuid"} + if c.NArg() > 0 { + return + } + for _, t := range delNoteOpts { + fmt.Println(t) + } + }, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "uuid", + Usage: "unique id of item to delete (separate multiple with commas)", + }, + }, + Action: func(c *cli.Context) error { + opts, err := getOpts(c) + if err != nil { + return err + } + + useStdOut = opts.useStdOut + + msg, err = processDeleteItems(c, opts) + return err }, }, @@ -504,43 +536,43 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { count := c.Bool("count") - getSettingssIF := gosn.ItemFilters{ + getSettingssIF := items.ItemFilters{ MatchAny: matchAny, - Filters: []gosn.Filter{ + Filters: []items.Filter{ {Type: "Setting"}, }, } - session, _, err := cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + sess, _, err := cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) if err != nil { return err } - ss := session.Gosn() + ss := sess.Gosn() // sync to get keys - gsi := gosn.SyncInput{ + gsi := items.SyncInput{ Session: &ss, } - _, err = gosn.Sync(gsi) + _, err = items.Sync(gsi) if err != nil { return err } var cacheDBPath string - cacheDBPath, err = cache.GenCacheDBPath(session, opts.cacheDBDir, snAppName) + cacheDBPath, err = cache.GenCacheDBPath(sess, opts.cacheDBDir, snAppName) if err != nil { return err } - session.CacheDBPath = cacheDBPath + sess.CacheDBPath = cacheDBPath // TODO: validate output output := c.String("output") appGetSettingsConfig := sncli.GetSettingsConfig{ - Session: &session, + Session: &sess, Filters: getSettingssIF, Output: output, Debug: opts.debug, } - var rawSettings gosn.Items + var rawSettings items.Items rawSettings, err = appGetSettingsConfig.Run() if err != nil { return err @@ -552,46 +584,46 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { numResults++ if !count && sncli.StringInSlice(output, yamlAbbrevs, false) { tagContentOrgStandardNotesSNDetailYAML := sncli.OrgStandardNotesSNDetailYAML{ - ClientUpdatedAt: rt.(*gosn.Component).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, + ClientUpdatedAt: rt.(*items.Component).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, } tagContentAppDataContent := sncli.AppDataContentYAML{ OrgStandardNotesSN: tagContentOrgStandardNotesSNDetailYAML, } settingContentYAML := sncli.SettingContentYAML{ - Title: rt.(*gosn.Component).Content.GetTitle(), - ItemReferences: sncli.ItemRefsToYaml(rt.(*gosn.Component).Content.References()), + Title: rt.(*items.Component).Content.GetTitle(), + ItemReferences: sncli.ItemRefsToYaml(rt.(*items.Component).Content.References()), AppData: tagContentAppDataContent, } settingsYAML = append(settingsYAML, sncli.SettingYAML{ - UUID: rt.(*gosn.Component).UUID, - ContentType: rt.(*gosn.Component).ContentType, + UUID: rt.(*items.Component).UUID, + ContentType: rt.(*items.Component).ContentType, Content: settingContentYAML, - UpdatedAt: rt.(*gosn.Component).UpdatedAt, - CreatedAt: rt.(*gosn.Component).CreatedAt, + UpdatedAt: rt.(*items.Component).UpdatedAt, + CreatedAt: rt.(*items.Component).CreatedAt, }) } if !count && strings.ToLower(output) == "json" { settingContentOrgStandardNotesSNDetailJSON := sncli.OrgStandardNotesSNDetailJSON{ - ClientUpdatedAt: rt.(*gosn.Component).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, + ClientUpdatedAt: rt.(*items.Component).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, } settingContentAppDataContent := sncli.AppDataContentJSON{ OrgStandardNotesSN: settingContentOrgStandardNotesSNDetailJSON, } settingContentJSON := sncli.SettingContentJSON{ - Title: rt.(*gosn.Component).Content.GetTitle(), - ItemReferences: sncli.ItemRefsToJSON(rt.(*gosn.Component).Content.References()), + Title: rt.(*items.Component).Content.GetTitle(), + ItemReferences: sncli.ItemRefsToJSON(rt.(*items.Component).Content.References()), AppData: settingContentAppDataContent, } settingsJSON = append(settingsJSON, sncli.SettingJSON{ - UUID: rt.(*gosn.Component).UUID, - ContentType: rt.(*gosn.Component).ContentType, + UUID: rt.(*items.Component).UUID, + ContentType: rt.(*items.Component).ContentType, Content: settingContentJSON, - UpdatedAt: rt.(*gosn.Component).UpdatedAt, - CreatedAt: rt.(*gosn.Component).CreatedAt, + UpdatedAt: rt.(*items.Component).UpdatedAt, + CreatedAt: rt.(*items.Component).CreatedAt, }) } } @@ -759,127 +791,127 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { }, }, }, - { - Name: "export", - Usage: "export data", - Hidden: true, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "path", - Usage: "choose directory to place export in (default: current directory)", - }, - }, - Action: func(c *cli.Context) error { - var opts configOptsOutput - opts, err = getOpts(c) - if err != nil { - return err - } - useStdOut = opts.useStdOut - - outputPath := strings.TrimSpace(c.String("output")) - if outputPath == "" { - outputPath, err = os.Getwd() - if err != nil { - return err - } - } - - timeStamp := time.Now().UTC().Format("20060102150405") - filePath := fmt.Sprintf("standard_notes_export_%s.json", timeStamp) - outputPath += string(os.PathSeparator) + filePath - - var sess cache.Session - sess, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) - if err != nil { - return err - } - - var cacheDBPath string - cacheDBPath, err = cache.GenCacheDBPath(sess, opts.cacheDBDir, snAppName) - if err != nil { - return err - } - - sess.Debug = opts.debug - - sess.CacheDBPath = cacheDBPath - appExportConfig := sncli.ExportConfig{ - Session: &sess, - Decrypted: c.Bool("decrypted"), - File: outputPath, - } - err = appExportConfig.Run() - if err == nil { - msg = fmt.Sprintf("encrypted export written to: %s", outputPath) - } - - return err - }, - }, - { - Name: "import", - Usage: "import data", - Hidden: true, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "file", - Usage: "path of file to import", - }, - cli.BoolFlag{ - Name: "experiment", - Usage: "test import functionality - only use after taking backup as this is experimental", - }, - }, - Action: func(c *cli.Context) error { - var opts configOptsOutput - opts, err = getOpts(c) - if err != nil { - return err - } - - useStdOut = opts.useStdOut - - inputPath := strings.TrimSpace(c.String("file")) - if inputPath == "" { - return errors.New("please specify path using --file") - } - - if !c.Bool("experiment") { - fmt.Printf("\nWARNING: The import functionality is currently for testing only\nDo not use unless you have a backup of your data and intend to restore after testing\nTo proceed run the command with flag --experiment\n") - return nil - } - - var session cache.Session - session, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) - if err != nil { - return err - } - - session.CacheDBPath, err = cache.GenCacheDBPath(session, opts.cacheDBDir, snAppName) - if err != nil { - return err - } - - appImportConfig := sncli.ImportConfig{ - Session: &session, - File: inputPath, - Format: c.String("format"), - Debug: opts.debug, - UseStdOut: opts.useStdOut, - } - - var imported int - imported, err = appImportConfig.Run() - if err == nil { - msg = fmt.Sprintf("imported %d items", imported) - } else { - msg = "import failed" - } - - return err - }, - }, + // { + // Name: "export", + // Usage: "export data", + // Hidden: true, + // Flags: []cli.Flag{ + // cli.StringFlag{ + // Name: "path", + // Usage: "choose directory to place export in (default: current directory)", + // }, + // }, + // Action: func(c *cli.Context) error { + // var opts configOptsOutput + // opts, err = getOpts(c) + // if err != nil { + // return err + // } + // useStdOut = opts.useStdOut + // + // outputPath := strings.TrimSpace(c.String("output")) + // if outputPath == "" { + // outputPath, err = os.Getwd() + // if err != nil { + // return err + // } + // } + // + // timeStamp := time.Now().UTC().Format("20060102150405") + // filePath := fmt.Sprintf("standard_notes_export_%s.json", timeStamp) + // outputPath += string(os.PathSeparator) + filePath + // + // var sess cache.Session + // sess, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + // if err != nil { + // return err + // } + // + // var cacheDBPath string + // cacheDBPath, err = cache.GenCacheDBPath(sess, opts.cacheDBDir, snAppName) + // if err != nil { + // return err + // } + // + // sess.Debug = opts.debug + // + // sess.CacheDBPath = cacheDBPath + // appExportConfig := sncli.ExportConfig{ + // Session: &sess, + // Decrypted: c.Bool("decrypted"), + // File: outputPath, + // } + // err = appExportConfig.Run() + // if err == nil { + // msg = fmt.Sprintf("encrypted export written to: %s", outputPath) + // } + // + // return err + // }, + // }, + // { + // Name: "import", + // Usage: "import data", + // Hidden: true, + // Flags: []cli.Flag{ + // cli.StringFlag{ + // Name: "file", + // Usage: "path of file to import", + // }, + // cli.BoolFlag{ + // Name: "experiment", + // Usage: "test import functionality - only use after taking backup as this is experimental", + // }, + // }, + // Action: func(c *cli.Context) error { + // var opts configOptsOutput + // opts, err = getOpts(c) + // if err != nil { + // return err + // } + // + // useStdOut = opts.useStdOut + // + // inputPath := strings.TrimSpace(c.String("file")) + // if inputPath == "" { + // return errors.New("please specify path using --file") + // } + // + // if !c.Bool("experiment") { + // fmt.Printf("\nWARNING: The import functionality is currently for testing only\nDo not use unless you have a backup of your data and intend to restore after testing\nTo proceed run the command with flag --experiment\n") + // return nil + // } + // + // var session cache.Session + // session, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + // if err != nil { + // return err + // } + // + // session.CacheDBPath, err = cache.GenCacheDBPath(session, opts.cacheDBDir, snAppName) + // if err != nil { + // return err + // } + // + // appImportConfig := sncli.ImportConfig{ + // Session: &session, + // File: inputPath, + // Format: c.String("format"), + // Debug: opts.debug, + // UseStdOut: opts.useStdOut, + // } + // + // var imported int + // imported, err = appImportConfig.Run() + // if err == nil { + // msg = fmt.Sprintf("imported %d items", imported) + // } else { + // msg = "import failed" + // } + // + // return err + // }, + // }, { Name: "register", Usage: "register a new user", @@ -959,17 +991,17 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { if err != nil { return err } - var session cache.Session - session, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + var sess cache.Session + sess, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) if err != nil { return err } - session.CacheDBPath, err = cache.GenCacheDBPath(session, opts.cacheDBDir, snAppName) + sess.CacheDBPath, err = cache.GenCacheDBPath(sess, opts.cacheDBDir, snAppName) if err != nil { return err } statsConfig := sncli.StatsConfig{ - Session: session, + Session: sess, } return statsConfig.Run() @@ -996,21 +1028,21 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { } useStdOut = opts.useStdOut - var session cache.Session - session, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + var cacheSession cache.Session + cacheSession, _, err = cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) if err != nil { return err } var cacheDBPath string - cacheDBPath, err = cache.GenCacheDBPath(session, opts.cacheDBDir, snAppName) + cacheDBPath, err = cache.GenCacheDBPath(cacheSession, opts.cacheDBDir, snAppName) if err != nil { return err } - session.CacheDBPath = cacheDBPath + cacheSession.CacheDBPath = cacheDBPath wipeConfig := sncli.WipeConfig{ - Session: &session, + Session: &cacheSession, UseStdOut: useStdOut, Everything: c.Bool("everything"), Debug: opts.debug, @@ -1021,7 +1053,7 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { if c.Bool("yes") { proceed = true } else { - fmt.Printf("wipe all items for account %s? ", session.Session.KeyParams.Identifier) + fmt.Printf("wipe all items for account %s? ", cacheSession.Session.KeyParams.Identifier) var input string _, err = fmt.Scanln(&input) if err == nil && sncli.StringInSlice(input, []string{"y", "yes"}, false) { @@ -1118,15 +1150,15 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { } useStdOut = opts.useStdOut - var session gosn.Session + var sess session.Session - session, _, err = gosn.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + sess, _, err = session.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) if err != nil { return err } err = sncli.ItemKeysHealthcheck(sncli.ItemsKeysHealthcheckInput{ - Session: session, + Session: sess, UseStdOut: useStdOut, DeleteInvalid: c.Bool("delete-invalid"), }) @@ -1183,15 +1215,15 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { } useStdOut = opts.useStdOut - var session gosn.Session + var sess session.Session - session, _, err = gosn.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + sess, _, err = session.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) if err != nil { return err } var res string res, err = sncli.DecryptString(sncli.DecryptStringInput{ - Session: session, + Session: sess, UseStdOut: useStdOut, Key: c.String("key"), In: str, @@ -1231,15 +1263,15 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { } useStdOut = opts.useStdOut - var session gosn.Session + var sess session.Session - session, _, err = gosn.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + sess, _, err = session.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) if err != nil { return err } err = sncli.OutputSession(sncli.OutputSessionInput{ - Session: session, + Session: sess, UseStdOut: useStdOut, OutputMasterKey: c.Bool("master-key"), }) @@ -1247,38 +1279,38 @@ func startCLI(args []string) (msg string, useStdOut bool, err error) { return err }, }, - { - Name: "create-itemskey", - Usage: "creates and displays an items key without syncing", - BashComplete: func(c *cli.Context) { - hcKeysOpts := []string{"--master-key"} - if c.NArg() > 0 { - return - } - for _, ano := range hcKeysOpts { - fmt.Println(ano) - } - }, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "master-key", - Usage: "master key to encrypt the encrypted item key with", - }, - }, - Action: func(c *cli.Context) error { - var opts configOptsOutput - opts, err = getOpts(c) - if err != nil { - return err - } - useStdOut = opts.useStdOut - - return sncli.CreateItemsKey(sncli.CreateItemsKeyInput{ - Debug: opts.debug, - MasterKey: c.String("master-key"), - }) - }, - }, + // { + // Name: "create-itemskey", + // Usage: "creates and displays an items key without syncing", + // BashComplete: func(c *cli.Context) { + // hcKeysOpts := []string{"--master-key"} + // if c.NArg() > 0 { + // return + // } + // for _, ano := range hcKeysOpts { + // fmt.Println(ano) + // } + // }, + // Flags: []cli.Flag{ + // cli.StringFlag{ + // Name: "master-key", + // Usage: "master key to encrypt the encrypted item key with", + // }, + // }, + // Action: func(c *cli.Context) error { + // var opts configOptsOutput + // opts, err = getOpts(c) + // if err != nil { + // return err + // } + // useStdOut = opts.useStdOut + // + // return sncli.CreateItemsKey(sncli.CreateItemsKeyInput{ + // Debug: opts.debug, + // MasterKey: c.String("master-key"), + // }) + // }, + // }, }, }, } @@ -1296,7 +1328,7 @@ func getPassword() (res string, err error) { return } - if len(string(bytePassword)) < sncli.MinPasswordLength { + if len(bytePassword) < sncli.MinPasswordLength { err = fmt.Errorf("\rpassword must be at least %d characters", sncli.MinPasswordLength) return @@ -1305,11 +1337,10 @@ func getPassword() (res string, err error) { var bytePassword2 []byte fmt.Printf("\rconfirm password: ") if bytePassword2, err = term.ReadPassword(int(syscall.Stdin)); err != nil { - return } - if string(bytePassword) != string(bytePassword2) { + if !bytes.Equal(bytePassword, bytePassword2) { fmt.Printf("\rpasswords do not match") fmt.Println() @@ -1323,7 +1354,6 @@ func getPassword() (res string, err error) { return } } - } func numTrue(in ...bool) (total int) { diff --git a/cmd/sncli/main_test.go b/cmd/sncli/main_test.go index be9651b..d3ccf99 100644 --- a/cmd/sncli/main_test.go +++ b/cmd/sncli/main_test.go @@ -1,9 +1,10 @@ package main import ( - "github.com/stretchr/testify/require" "testing" "time" + + "github.com/stretchr/testify/require" ) func TestWipe(t *testing.T) { diff --git a/cmd/sncli/note.go b/cmd/sncli/note.go index 21db9bb..8396438 100644 --- a/cmd/sncli/note.go +++ b/cmd/sncli/note.go @@ -14,14 +14,14 @@ import ( "github.com/asdine/storm/v3/q" "github.com/divan/num2words" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" sncli "github.com/jonhadfield/sn-cli" "github.com/urfave/cli" "gopkg.in/yaml.v2" ) -func getNoteByUUID(sess cache.Session, uuid string) (tag gosn.Note, err error) { +func getNoteByUUID(sess cache.Session, uuid string) (tag items.Note, err error) { if sess.CacheDBPath == "" { return tag, errors.New("CacheDBPath missing from sess") } @@ -57,13 +57,13 @@ func getNoteByUUID(sess cache.Session, uuid string) (tag gosn.Note, err error) { return } - var rawEncItems gosn.Items + var rawEncItems items.Items rawEncItems, err = encNotes.ToItems(&sess) - return *rawEncItems[0].(*gosn.Note), err + return *rawEncItems[0].(*items.Note), err } -func getNotesByTitle(sess cache.Session, title string, close bool) (notes gosn.Notes, err error) { +func getNotesByTitle(sess cache.Session, title string, close bool) (notes items.Notes, err error) { if sess.CacheDB == nil { var so cache.SyncOutput @@ -98,13 +98,13 @@ func getNotesByTitle(sess cache.Session, title string, close bool) (notes gosn.N } // decrypt all notes - var allRawNotes gosn.Items + var allRawNotes items.Items allRawNotes, err = allEncNotes.ToItems(&sess) - var matchingRawNotes gosn.Notes + var matchingRawNotes items.Notes for _, rt := range allRawNotes { - t := rt.(*gosn.Note) + t := rt.(*items.Note) if t.Content.Title == title { matchingRawNotes = append(matchingRawNotes, *t) } @@ -213,9 +213,9 @@ func processEditNote(c *cli.Context, opts configOptsOutput) (msg string, err err cSession.CacheDB = cso.DB - var note gosn.Note + var note items.Note - var notes gosn.Notes + var notes items.Notes // if uuid was passed then retrieve note from db using uuid if inUUID != "" { @@ -264,7 +264,7 @@ func processEditNote(c *cli.Context, opts configOptsOutput) (msg string, err err note.Content.SetUpdateTime(time.Now().UTC()) // save note to db - notes = gosn.Notes{note} + notes = items.Notes{note} if err = cache.SaveNotes(&cSession, cSession.CacheDB, notes, false); err != nil { return @@ -307,16 +307,16 @@ func processGetNotes(c *cli.Context, opts configOptsOutput) (msg string, err err count := c.Bool("count") output := c.String("output") - noteFilter := gosn.Filter{ + noteFilter := items.Filter{ Type: "Note", } - getNotesIF := gosn.ItemFilters{ + getNotesIF := items.ItemFilters{ MatchAny: false, - Filters: []gosn.Filter{noteFilter}, + Filters: []items.Filter{noteFilter}, } if !c.Bool("include-trash") { - includeTrashFilter := gosn.Filter{ + includeTrashFilter := items.Filter{ Type: "Note", Key: "Trash", Comparison: "!=", @@ -326,7 +326,7 @@ func processGetNotes(c *cli.Context, opts configOptsOutput) (msg string, err err } if uuid != "" { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "uuid", Comparison: "==", @@ -336,7 +336,7 @@ func processGetNotes(c *cli.Context, opts configOptsOutput) (msg string, err err } if title != "" { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "Title", Comparison: "contains", @@ -346,7 +346,7 @@ func processGetNotes(c *cli.Context, opts configOptsOutput) (msg string, err err } if text != "" { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "Text", Comparison: "contains", @@ -359,7 +359,7 @@ func processGetNotes(c *cli.Context, opts configOptsOutput) (msg string, err err if len(processedTags) > 0 { for _, t := range processedTags { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "Tag", Comparison: "contains", @@ -398,15 +398,15 @@ func processGetTrash(c *cli.Context, opts configOptsOutput) (msg string, err err count := c.Bool("count") output := c.String("output") - noteFilter := gosn.Filter{ + noteFilter := items.Filter{ Type: "Note", } - getNotesIF := gosn.ItemFilters{ + getNotesIF := items.ItemFilters{ MatchAny: false, - Filters: []gosn.Filter{noteFilter}, + Filters: []items.Filter{noteFilter}, } - TrashFilter := gosn.Filter{ + TrashFilter := items.Filter{ Type: "Note", Key: "Trash", Comparison: "==", @@ -415,7 +415,7 @@ func processGetTrash(c *cli.Context, opts configOptsOutput) (msg string, err err getNotesIF.Filters = append(getNotesIF.Filters, TrashFilter) if uuid != "" { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "uuid", Comparison: "==", @@ -425,7 +425,7 @@ func processGetTrash(c *cli.Context, opts configOptsOutput) (msg string, err err } if title != "" { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "Title", Comparison: "contains", @@ -435,7 +435,7 @@ func processGetTrash(c *cli.Context, opts configOptsOutput) (msg string, err err } if text != "" { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "Text", Comparison: "contains", @@ -448,7 +448,7 @@ func processGetTrash(c *cli.Context, opts configOptsOutput) (msg string, err err if len(processedTags) > 0 { for _, t := range processedTags { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Note", Key: "Tag", Comparison: "contains", @@ -482,7 +482,7 @@ func processGetTrash(c *cli.Context, opts configOptsOutput) (msg string, err err } func outputNotes(c *cli.Context, count bool, output string, getNoteConfig sncli.GetNoteConfig) (msg string, err error) { - var rawNotes gosn.Items + var rawNotes items.Items rawNotes, err = getNoteConfig.Run() if err != nil { @@ -502,66 +502,66 @@ func outputNotes(c *cli.Context, count bool, output string, getNoteConfig sncli. if !count && sncli.StringInSlice(output, yamlAbbrevs, false) { noteContentOrgStandardNotesSNDetailYAML := sncli.OrgStandardNotesSNDetailYAML{ - ClientUpdatedAt: rt.(*gosn.Note).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, + ClientUpdatedAt: rt.(*items.Note).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, } noteContentAppDataContent := sncli.AppDataContentYAML{ OrgStandardNotesSN: noteContentOrgStandardNotesSNDetailYAML, - OrgStandardNotesSNComponents: rt.(*gosn.Note).Content.GetAppData().OrgStandardNotesSNComponents, + OrgStandardNotesSNComponents: rt.(*items.Note).Content.GetAppData().OrgStandardNotesSNComponents, } var isTrashed *bool - if rt.(*gosn.Note).Content.Trashed != nil { - isTrashed = rt.(*gosn.Note).Content.Trashed + if rt.(*items.Note).Content.Trashed != nil { + isTrashed = rt.(*items.Note).Content.Trashed } noteContentYAML := sncli.NoteContentYAML{ - Title: rt.(*gosn.Note).Content.GetTitle(), - Text: rt.(*gosn.Note).Content.GetText(), - ItemReferences: sncli.ItemRefsToYaml(rt.(*gosn.Note).Content.References()), + Title: rt.(*items.Note).Content.GetTitle(), + Text: rt.(*items.Note).Content.GetText(), + ItemReferences: sncli.ItemRefsToYaml(rt.(*items.Note).Content.References()), AppData: noteContentAppDataContent, - PreviewPlain: rt.(*gosn.Note).Content.PreviewPlain, + PreviewPlain: rt.(*items.Note).Content.PreviewPlain, Trashed: isTrashed, } notesYAML = append(notesYAML, sncli.NoteYAML{ - UUID: rt.(*gosn.Note).UUID, - ContentType: rt.(*gosn.Note).ContentType, + UUID: rt.(*items.Note).UUID, + ContentType: rt.(*items.Note).ContentType, Content: noteContentYAML, - UpdatedAt: rt.(*gosn.Note).UpdatedAt, - CreatedAt: rt.(*gosn.Note).CreatedAt, + UpdatedAt: rt.(*items.Note).UpdatedAt, + CreatedAt: rt.(*items.Note).CreatedAt, }) } if !count && strings.ToLower(output) == "json" { noteContentOrgStandardNotesSNDetailJSON := sncli.OrgStandardNotesSNDetailJSON{ - ClientUpdatedAt: rt.(*gosn.Note).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, - Pinned: rt.(*gosn.Note).Content.GetAppData().OrgStandardNotesSN.Pinned, - PrefersPlainEditor: rt.(*gosn.Note).Content.GetAppData().OrgStandardNotesSN.PrefersPlainEditor, + ClientUpdatedAt: rt.(*items.Note).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, + Pinned: rt.(*items.Note).Content.GetAppData().OrgStandardNotesSN.Pinned, + PrefersPlainEditor: rt.(*items.Note).Content.GetAppData().OrgStandardNotesSN.PrefersPlainEditor, } noteContentAppDataContent := sncli.AppDataContentJSON{ OrgStandardNotesSN: noteContentOrgStandardNotesSNDetailJSON, - OrgStandardNotesSNComponents: rt.(*gosn.Note).Content.GetAppData().OrgStandardNotesSNComponents, + OrgStandardNotesSNComponents: rt.(*items.Note).Content.GetAppData().OrgStandardNotesSNComponents, } var isTrashed *bool - if rt.(*gosn.Note).Content.Trashed != nil { - isTrashed = rt.(*gosn.Note).Content.Trashed + if rt.(*items.Note).Content.Trashed != nil { + isTrashed = rt.(*items.Note).Content.Trashed } noteContentJSON := sncli.NoteContentJSON{ - Title: rt.(*gosn.Note).Content.GetTitle(), - Text: rt.(*gosn.Note).Content.GetText(), - ItemReferences: sncli.ItemRefsToJSON(rt.(*gosn.Note).Content.References()), + Title: rt.(*items.Note).Content.GetTitle(), + Text: rt.(*items.Note).Content.GetText(), + ItemReferences: sncli.ItemRefsToJSON(rt.(*items.Note).Content.References()), AppData: noteContentAppDataContent, - PreviewPlain: rt.(*gosn.Note).Content.PreviewPlain, + PreviewPlain: rt.(*items.Note).Content.PreviewPlain, Trashed: isTrashed, } notesJSON = append(notesJSON, sncli.NoteJSON{ - UUID: rt.(*gosn.Note).UUID, - ContentType: rt.(*gosn.Note).ContentType, + UUID: rt.(*items.Note).UUID, + ContentType: rt.(*items.Note).ContentType, Content: noteContentJSON, - UpdatedAt: rt.(*gosn.Note).UpdatedAt, - CreatedAt: rt.(*gosn.Note).CreatedAt, + UpdatedAt: rt.(*items.Note).UpdatedAt, + CreatedAt: rt.(*items.Note).CreatedAt, }) } } @@ -694,3 +694,43 @@ func processDeleteNote(c *cli.Context, opts configOptsOutput) (msg string, err e return msg, err } + +func processDeleteItems(c *cli.Context, opts configOptsOutput) (msg string, err error) { + uuid := strings.TrimSpace(c.String("uuid")) + + sess, _, err := cache.GetSession(opts.useSession, opts.sessKey, opts.server, opts.debug) + if err != nil { + return msg, err + } + + processedUUIDs := sncli.CommaSplit(uuid) + + var cacheDBPath string + cacheDBPath, err = cache.GenCacheDBPath(sess, opts.cacheDBDir, snAppName) + + if err != nil { + return msg, err + } + + sess.CacheDBPath = cacheDBPath + DeleteItemConfig := sncli.DeleteItemConfig{ + Session: &sess, + ItemsUUIDs: processedUUIDs, + Debug: opts.debug, + } + + var noDeleted int + + if noDeleted, err = DeleteItemConfig.Run(); err != nil { + return msg, fmt.Errorf("failed to delete items. %+v", err) + } + + strItem := "items" + if noDeleted == 1 { + strItem = "item" + } + + msg = sncli.Green(fmt.Sprintf("%s %s %s", msgDeleted, num2words.Convert(noDeleted), strItem)) + + return msg, err +} diff --git a/cmd/sncli/session.go b/cmd/sncli/session.go index 286d936..539e4a2 100644 --- a/cmd/sncli/session.go +++ b/cmd/sncli/session.go @@ -3,7 +3,7 @@ package main import ( "os" - "github.com/jonhadfield/gosn-v2" + "github.com/jonhadfield/gosn-v2/session" "github.com/urfave/cli" ) @@ -14,7 +14,7 @@ func processSession(c *cli.Context, opts configOptsOutput) (msg string, err erro sessKey := c.String("session-key") if sStatus || sRemove { - if err = gosn.SessionExists(nil); err != nil { + if err = session.SessionExists(nil); err != nil { return "", err } } @@ -27,19 +27,19 @@ func processSession(c *cli.Context, opts configOptsOutput) (msg string, err erro } if sAdd { - msg, err = gosn.AddSession(opts.server, sessKey, nil, opts.debug) + msg, err = session.AddSession(opts.server, sessKey, nil, opts.debug) return msg, err } if sRemove { - msg = gosn.RemoveSession(nil) + msg = session.RemoveSession(nil) return msg, nil } if sStatus { - msg, err = gosn.SessionStatus(sessKey, nil) + msg, err = session.SessionStatus(sessKey, nil) } return msg, err diff --git a/cmd/sncli/tag.go b/cmd/sncli/tag.go index b3464ac..ce74f5e 100644 --- a/cmd/sncli/tag.go +++ b/cmd/sncli/tag.go @@ -10,14 +10,14 @@ import ( "strings" "github.com/asdine/storm/v3/q" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" sncli "github.com/jonhadfield/sn-cli" "github.com/urfave/cli" "gopkg.in/yaml.v2" ) -func getTagByUUID(sess *cache.Session, uuid string) (tag gosn.Tag, err error) { +func getTagByUUID(sess *cache.Session, uuid string) (tag items.Tag, err error) { if sess.CacheDBPath == "" { return tag, errors.New("CacheDBPath missing from sess") } @@ -53,13 +53,13 @@ func getTagByUUID(sess *cache.Session, uuid string) (tag gosn.Tag, err error) { return } - var rawEncItems gosn.Items + var rawEncItems items.Items rawEncItems, err = encTags.ToItems(sess) - return *rawEncItems[0].(*gosn.Tag), err + return *rawEncItems[0].(*items.Tag), err } -func getTagsByTitle(sess cache.Session, title string) (tags gosn.Tags, err error) { +func getTagsByTitle(sess cache.Session, title string) (tags items.Tags, err error) { var so cache.SyncOutput si := cache.SyncInput{ @@ -90,13 +90,13 @@ func getTagsByTitle(sess cache.Session, title string) (tags gosn.Tags, err error } // decrypt all tags - var allRawTags gosn.Items + var allRawTags items.Items allRawTags, err = allEncTags.ToItems(&sess) - var matchingRawTags gosn.Tags + var matchingRawTags items.Tags for _, rt := range allRawTags { - t := rt.(*gosn.Tag) + t := rt.(*items.Tag) if t.Content.Title == title { matchingRawTags = append(matchingRawTags, *t) } @@ -131,9 +131,9 @@ func processEditTag(c *cli.Context, opts configOptsOutput) (msg string, err erro sess.CacheDBPath = cacheDBPath - var tag gosn.Tag + var tag items.Tag - var tags gosn.Tags + var tags items.Tags // if uuid was passed then retrieve tag from db using uuid if inUUID != "" { @@ -189,7 +189,7 @@ func processEditTag(c *cli.Context, opts configOptsOutput) (msg string, err erro return } - tags = gosn.Tags{tag} + tags = items.Tags{tag} if err = cache.SaveTags(so.DB, &sess, tags, false); err != nil { return @@ -214,14 +214,14 @@ func processGetTags(c *cli.Context, opts configOptsOutput) (msg string, err erro regex := c.Bool("regex") count := c.Bool("count") - getTagsIF := gosn.ItemFilters{ + getTagsIF := items.ItemFilters{ MatchAny: matchAny, } // add uuid filters if inUUID != "" { for _, uuid := range sncli.CommaSplit(inUUID) { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Tag", Key: "uuid", Comparison: "==", @@ -238,7 +238,7 @@ func processGetTags(c *cli.Context, opts configOptsOutput) (msg string, err erro if inTitle != "" { for _, title := range sncli.CommaSplit(inTitle) { - titleFilter := gosn.Filter{ + titleFilter := items.Filter{ Type: "Tag", Key: "Title", Comparison: comparison, @@ -249,7 +249,7 @@ func processGetTags(c *cli.Context, opts configOptsOutput) (msg string, err erro } if inTitle == "" && inUUID == "" { - getTagsIF.Filters = append(getTagsIF.Filters, gosn.Filter{ + getTagsIF.Filters = append(getTagsIF.Filters, items.Filter{ Type: "Tag", }) } @@ -280,7 +280,7 @@ func processGetTags(c *cli.Context, opts configOptsOutput) (msg string, err erro Debug: opts.debug, } - var rawTags gosn.Items + var rawTags items.Items rawTags, err = appGetTagConfig.Run() if err != nil { @@ -301,47 +301,47 @@ func processGetTags(c *cli.Context, opts configOptsOutput) (msg string, err erro if !count && sncli.StringInSlice(output, yamlAbbrevs, false) { tagContentOrgStandardNotesSNDetailYAML := sncli.OrgStandardNotesSNDetailYAML{ - ClientUpdatedAt: rt.(*gosn.Tag).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, + ClientUpdatedAt: rt.(*items.Tag).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, } tagContentAppDataContent := sncli.AppDataContentYAML{ OrgStandardNotesSN: tagContentOrgStandardNotesSNDetailYAML, } tagContentYAML := sncli.TagContentYAML{ - Title: rt.(*gosn.Tag).Content.GetTitle(), - ItemReferences: sncli.ItemRefsToYaml(rt.(*gosn.Tag).Content.References()), + Title: rt.(*items.Tag).Content.GetTitle(), + ItemReferences: sncli.ItemRefsToYaml(rt.(*items.Tag).Content.References()), AppData: tagContentAppDataContent, } tagsYAML = append(tagsYAML, sncli.TagYAML{ - UUID: rt.(*gosn.Tag).UUID, - ContentType: rt.(*gosn.Tag).ContentType, + UUID: rt.(*items.Tag).UUID, + ContentType: rt.(*items.Tag).ContentType, Content: tagContentYAML, - UpdatedAt: rt.(*gosn.Tag).UpdatedAt, - CreatedAt: rt.(*gosn.Tag).CreatedAt, + UpdatedAt: rt.(*items.Tag).UpdatedAt, + CreatedAt: rt.(*items.Tag).CreatedAt, }) } if !count && strings.ToLower(output) == "json" { tagContentOrgStandardNotesSNDetailJSON := sncli.OrgStandardNotesSNDetailJSON{ - ClientUpdatedAt: rt.(*gosn.Tag).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, + ClientUpdatedAt: rt.(*items.Tag).Content.GetAppData().OrgStandardNotesSN.ClientUpdatedAt, } tagContentAppDataContent := sncli.AppDataContentJSON{ OrgStandardNotesSN: tagContentOrgStandardNotesSNDetailJSON, } tagContentJSON := sncli.TagContentJSON{ - Title: rt.(*gosn.Tag).Content.GetTitle(), - ItemReferences: sncli.ItemRefsToJSON(rt.(*gosn.Tag).Content.References()), + Title: rt.(*items.Tag).Content.GetTitle(), + ItemReferences: sncli.ItemRefsToJSON(rt.(*items.Tag).Content.References()), AppData: tagContentAppDataContent, } tagsJSON = append(tagsJSON, sncli.TagJSON{ - UUID: rt.(*gosn.Tag).UUID, - ContentType: rt.(*gosn.Tag).ContentType, + UUID: rt.(*items.Tag).UUID, + ContentType: rt.(*items.Tag).ContentType, Content: tagContentJSON, - UpdatedAt: rt.(*gosn.Tag).UpdatedAt, - CreatedAt: rt.(*gosn.Tag).CreatedAt, + UpdatedAt: rt.(*items.Tag).UpdatedAt, + CreatedAt: rt.(*items.Tag).CreatedAt, }) } } diff --git a/cmd/sncli/tag_test.go b/cmd/sncli/tag_test.go index 00a81cc..80243f9 100644 --- a/cmd/sncli/tag_test.go +++ b/cmd/sncli/tag_test.go @@ -2,7 +2,12 @@ package main import ( "fmt" - "github.com/stretchr/testify/require" + "github.com/jonhadfield/gosn-v2/auth" + "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/common" + "github.com/jonhadfield/gosn-v2/items" + "github.com/jonhadfield/gosn-v2/session" + sncli "github.com/jonhadfield/sn-cli" "log" "os" "strconv" @@ -10,14 +15,12 @@ import ( "testing" "time" - "github.com/jonhadfield/gosn-v2" - "github.com/jonhadfield/gosn-v2/cache" - sncli "github.com/jonhadfield/sn-cli" + "github.com/stretchr/testify/require" ) var ( testSession *cache.Session - gTtestSession *gosn.Session + gTtestSession *session.Session testUserEmail string testUserPassword string ) @@ -27,7 +30,7 @@ func localTestMain() { testUserEmail = fmt.Sprintf("ramea-%s", strconv.FormatInt(time.Now().UnixNano(), 16)) testUserPassword = "secretsanta" - rInput := gosn.RegisterInput{ + rInput := auth.RegisterInput{ Password: testUserPassword, Email: testUserEmail, APIServer: localServer, @@ -43,37 +46,141 @@ func localTestMain() { signIn(localServer, testUserEmail, testUserPassword) } +// +// func signIn(server, email, password string) { +// ts, err := auth.CliSignIn(email, password, server, true) +// if err != nil { +// log.Fatal(err) +// } +// +// gTtestSession = &session.Session{ +// Debug: true, +// HTTPClient: common.NewHTTPClient(), +// SchemaValidation: false, +// Server: ts.Server, +// FilesServerUrl: ts.FilesServerUrl, +// Token: "", +// MasterKey: ts.MasterKey, +// ItemsKeys: nil, +// DefaultItemsKey: session.SessionItemsKey{}, +// KeyParams: ts.KeyParams, +// AccessToken: ts.AccessToken, +// RefreshToken: ts.RefreshToken, +// AccessExpiration: ts.AccessExpiration, +// RefreshExpiration: ts.RefreshExpiration, +// ReadOnlyAccess: ts.ReadOnlyAccess, +// PasswordNonce: "", +// Schemas: nil, +// } +// } + func signIn(server, email, password string) { - ts, err := gosn.CliSignIn(email, password, server, true) + ts, err := auth.CliSignIn(email, password, server, true) if err != nil { log.Fatal(err) } - gTtestSession = &ts + if server == "" { + server = session.SNServerURL + } + + gTtestSession = &session.Session{ + Debug: true, + HTTPClient: common.NewHTTPClient(), + SchemaValidation: false, + Server: server, + FilesServerUrl: ts.FilesServerUrl, + Token: "", + MasterKey: ts.MasterKey, + ItemsKeys: nil, + DefaultItemsKey: session.SessionItemsKey{}, + KeyParams: auth.KeyParams{}, + AccessToken: ts.AccessToken, + RefreshToken: ts.RefreshToken, + AccessExpiration: ts.AccessExpiration, + RefreshExpiration: ts.RefreshExpiration, + ReadOnlyAccess: ts.ReadOnlyAccess, + PasswordNonce: ts.PasswordNonce, + Schemas: nil, + } + + testSession = &cache.Session{ + Session: gTtestSession, + CacheDB: nil, + CacheDBPath: "", + } } +// func TestMain(m *testing.M) { +// if strings.Contains(os.Getenv("SN_SERVER"), "ramea") { +// localTestMain() +// } else { +// signIn(os.Getenv("SN_SERVER"), os.Getenv("SN_EMAIL"), os.Getenv("SN_PASSWORD")) +// } +// +// if _, err := items.Sync(items.SyncInput{Session: gTtestSession}); err != nil { +// log.Fatal(err) +// } +// +// if gTtestSession.DefaultItemsKey.ItemsKey == "" { +// panic("failed in TestMain due to empty default items key") +// } +// +// var err error +// testSession, err = cache.ImportSession(gTtestSession, "") +// if err != nil { +// return +// } +// +// testSession.CacheDBPath, err = cache.GenCacheDBPath(*testSession, "", gosn.LibName) +// if err != nil { +// panic(err) +// } +// +// os.Exit(m.Run()) +// } + func TestMain(m *testing.M) { + // if os.Getenv("SN_SERVER") == "" || strings.Contains(os.Getenv("SN_SERVER"), "ramea") { if strings.Contains(os.Getenv("SN_SERVER"), "ramea") { localTestMain() } else { - signIn(os.Getenv("SN_SERVER"), os.Getenv("SN_EMAIL"), os.Getenv("SN_PASSWORD")) + signIn(session.SNServerURL, os.Getenv("SN_EMAIL"), os.Getenv("SN_PASSWORD")) } - if _, err := gosn.Sync(gosn.SyncInput{Session: gTtestSession}); err != nil { + if _, err := items.Sync(items.SyncInput{Session: gTtestSession}); err != nil { log.Fatal(err) } if gTtestSession.DefaultItemsKey.ItemsKey == "" { panic("failed in TestMain due to empty default items key") } + if strings.TrimSpace(gTtestSession.Server) == "" { + panic("failed in TestMain due to empty server") + } var err error - testSession, err = cache.ImportSession(gTtestSession, "") + testSession, err = cache.ImportSession(&auth.SignInResponseDataSession{ + Debug: gTtestSession.Debug, + HTTPClient: gTtestSession.HTTPClient, + SchemaValidation: false, + Server: gTtestSession.Server, + FilesServerUrl: gTtestSession.FilesServerUrl, + Token: "", + MasterKey: gTtestSession.MasterKey, + KeyParams: gTtestSession.KeyParams, + AccessToken: gTtestSession.AccessToken, + RefreshToken: gTtestSession.RefreshToken, + AccessExpiration: gTtestSession.AccessExpiration, + RefreshExpiration: gTtestSession.RefreshExpiration, + ReadOnlyAccess: gTtestSession.ReadOnlyAccess, + PasswordNonce: gTtestSession.PasswordNonce, + }, "") if err != nil { return } - testSession.CacheDBPath, err = cache.GenCacheDBPath(*testSession, "", gosn.LibName) + testSession.CacheDBPath, err = cache.GenCacheDBPath(*testSession, "", common.LibName) if err != nil { panic(err) } @@ -93,7 +200,7 @@ func TestGetTagsByTitleAndUUID(t *testing.T) { require.Contains(t, ato.Added, "TestTagTwo") require.Empty(t, ato.Existing) - var tags gosn.Tags + var tags items.Tags tags, err = getTagsByTitle(*testSession, "TestTagOne") require.NoError(t, err) require.Len(t, tags, 1) @@ -101,7 +208,7 @@ func TestGetTagsByTitleAndUUID(t *testing.T) { tagUUID := tags[0].UUID - var tag gosn.Tag + var tag items.Tag tag, err = getTagByUUID(testSession, tagUUID) require.NoError(t, err) require.Equal(t, "TestTagOne", tag.Content.Title) diff --git a/debug.go b/debug.go index 743f8e1..aa4d7ef 100644 --- a/debug.go +++ b/debug.go @@ -3,12 +3,15 @@ package sncli import ( "encoding/base64" "fmt" - "github.com/jonhadfield/gosn-v2" "strings" + + "github.com/jonhadfield/gosn-v2/crypto" + "github.com/jonhadfield/gosn-v2/items" + "github.com/jonhadfield/gosn-v2/session" ) type DecryptStringInput struct { - Session gosn.Session + Session session.Session In string UseStdOut bool Key string @@ -18,7 +21,6 @@ func DecryptString(input DecryptStringInput) (plaintext string, err error) { key1 := input.Session.MasterKey if input.Key != "" { key1 = input.Key - } // trim noise @@ -42,7 +44,7 @@ func DecryptString(input DecryptStringInput) (plaintext string, err error) { } fmt.Printf("Decoded Auth Data: %+v\n", string(bad)) - pb, err := gosn.DecryptCipherText(cipherText, key1, nonce, authData) + pb, err := crypto.DecryptCipherText(cipherText, key1, nonce, authData) if err != nil { return } @@ -51,7 +53,7 @@ func DecryptString(input DecryptStringInput) (plaintext string, err error) { } type OutputSessionInput struct { - Session gosn.Session + Session session.Session In string UseStdOut bool OutputMasterKey bool @@ -72,7 +74,7 @@ func OutputSession(input OutputSessionInput) error { fmt.Println() } - _, err := gosn.Sync(gosn.SyncInput{Session: &input.Session}) + _, err := items.Sync(items.SyncInput{Session: &input.Session}) if err != nil { return err } @@ -97,12 +99,12 @@ type CreateItemsKeyInput struct { MasterKey string } -func CreateItemsKey(input CreateItemsKeyInput) error { - ik := gosn.NewItemsKey() - fmt.Printf("%+v\n", ik.ItemsKey) - - return nil -} +// func CreateItemsKey(input CreateItemsKeyInput) error { +// ik := items.NewItemsKey() +// fmt.Printf("%+v\n", ik.ItemsKey) +// +// return nil +// } func splitContent(in string) (version, nonce, cipherText, authenticatedData string) { components := strings.Split(in, ":") diff --git a/debug_test.go b/debug_test.go index 460256d..7e95517 100644 --- a/debug_test.go +++ b/debug_test.go @@ -1,14 +1,15 @@ package sncli import ( - "github.com/jonhadfield/gosn-v2" - "github.com/stretchr/testify/require" "testing" + + "github.com/jonhadfield/gosn-v2/session" + "github.com/stretchr/testify/require" ) func TestDebugStringItemsKeyEncItemKey(t *testing.T) { plaintext, err := DecryptString(DecryptStringInput{ - Session: gosn.Session{}, + Session: session.Session{}, In: "004:966fb3ab4422f3b2a0ea20159d769cbee1d7f763d5aba425:xRmX5+LlNYk4bXI4OaeKNMI2LZE3QeLO5xFVwy+v3PY8hBUBOuDRa+n7m01gfA57fPL4JBrWhGJ9b8gaiOPFGC8ntlBL7+qhj/sQ/cbA4Po=:eyJrcCI6eyJjcmVhdGVkIjoiMTYwODQ3MzM4Nzc5OSIsImlkZW50aWZpZXIiOiJsZW1vbjIiLCJvcmlnaW5hdGlvbiI6InJlZ2lzdHJhdGlvbiIsInB3X25vbmNlIjoiNGZXc2RUOHJaY2NOTlR1aWVZcTF2bGJ6YkIzRmVkeE0iLCJ2ZXJzaW9uIjoiMDA0In0sInUiOiJhMWIxZDYwYy1mNjA1LTQ2MDQtOGE5ZS03NjE1NDkyODI4M2IiLCJ2IjoiMDA0In0=", UseStdOut: false, Key: "9dbd97421d3981c433979fc8d86559734331f711372c4ad7a0a6830fff75af68", @@ -19,7 +20,7 @@ func TestDebugStringItemsKeyEncItemKey(t *testing.T) { func TestDebugStringItemsKeyEncItemKeySession(t *testing.T) { plaintext, err := DecryptString(DecryptStringInput{ - Session: gosn.Session{ + Session: session.Session{ MasterKey: "9dbd97421d3981c433979fc8d86559734331f711372c4ad7a0a6830fff75af68", }, In: "004:966fb3ab4422f3b2a0ea20159d769cbee1d7f763d5aba425:xRmX5+LlNYk4bXI4OaeKNMI2LZE3QeLO5xFVwy+v3PY8hBUBOuDRa+n7m01gfA57fPL4JBrWhGJ9b8gaiOPFGC8ntlBL7+qhj/sQ/cbA4Po=:eyJrcCI6eyJjcmVhdGVkIjoiMTYwODQ3MzM4Nzc5OSIsImlkZW50aWZpZXIiOiJsZW1vbjIiLCJvcmlnaW5hdGlvbiI6InJlZ2lzdHJhdGlvbiIsInB3X25vbmNlIjoiNGZXc2RUOHJaY2NOTlR1aWVZcTF2bGJ6YkIzRmVkeE0iLCJ2ZXJzaW9uIjoiMDA0In0sInUiOiJhMWIxZDYwYy1mNjA1LTQ2MDQtOGE5ZS03NjE1NDkyODI4M2IiLCJ2IjoiMDA0In0=", diff --git a/export.go b/export.go index a046804..cdfc3c8 100644 --- a/export.go +++ b/export.go @@ -1,12 +1,7 @@ package sncli import ( - "fmt" - "github.com/briandowns/spinner" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" - "os" - "time" ) type ExportConfig struct { @@ -24,73 +19,74 @@ type ImportConfig struct { Debug bool } -// Run will retrieve all items from SN directly, re-encrypt them with a new ItemsKey and write them to a file. -func (i ExportConfig) Run() error { - if !i.Session.Debug { - prefix := HiWhite("exporting ") - - s := spinner.New(spinner.CharSets[14], 100*time.Millisecond, spinner.WithWriter(os.Stdout)) - if i.UseStdOut { - s = spinner.New(spinner.CharSets[14], 100*time.Millisecond, spinner.WithWriter(os.Stderr)) - } - - s.Prefix = prefix - s.Start() - - err := i.Session.Export(i.File) - - s.Stop() - - return err - } - - return i.Session.Export(i.File) -} - -func (i *ImportConfig) Run() (imported int, err error) { - // populate DB - gii := cache.SyncInput{ - Session: i.Session, - } - - gio, err := Sync(gii, true) - if err != nil { - return imported, err - } - - var syncTokens []cache.SyncToken - if err = gio.DB.All(&syncTokens); err != nil { - return imported, err - } - syncToken := "" - if len(syncTokens) > 0 { - syncToken = syncTokens[0].SyncToken - } - if err = gio.DB.Close(); err != nil { - return imported, err - } - - // request all items from SN - var iItemsKey gosn.ItemsKey - var iItems gosn.EncryptedItems - - iItems, iItemsKey, err = i.Session.Session.Import(i.File, syncToken, "") - if err != nil { - return 0, err - } - - if iItemsKey.ItemsKey == "" { - panic(fmt.Sprintf("iItemsKey.ItemsKey is empty for: '%s'", iItemsKey.UUID)) - } - - // push item and close db - pii := cache.SyncInput{ - Session: i.Session, - Close: true, - } - - _, err = Sync(pii, true) - imported = len(iItems) - - return imported, err -} +// +// // Run will retrieve all items from SN directly, re-encrypt them with a new ItemsKey and write them to a file. +// func (i ExportConfig) Run() error { +// if !i.Session.Debug { +// prefix := HiWhite("exporting ") +// +// s := spinner.New(spinner.CharSets[14], 100*time.Millisecond, spinner.WithWriter(os.Stdout)) +// if i.UseStdOut { +// s = spinner.New(spinner.CharSets[14], 100*time.Millisecond, spinner.WithWriter(os.Stderr)) +// } +// +// s.Prefix = prefix +// s.Start() +// +// err := i.Session.Export(i.File) +// +// s.Stop() +// +// return err +// } +// +// return i.Session.Export(i.File) +// } + +// func (i *ImportConfig) Run() (imported int, err error) { +// // populate DB +// gii := cache.SyncInput{ +// Session: i.Session, +// } +// +// gio, err := Sync(gii, true) +// if err != nil { +// return imported, err +// } +// +// var syncTokens []cache.SyncToken +// if err = gio.DB.All(&syncTokens); err != nil { +// return imported, err +// } +// syncToken := "" +// if len(syncTokens) > 0 { +// syncToken = syncTokens[0].SyncToken +// } +// if err = gio.DB.Close(); err != nil { +// return imported, err +// } +// +// // request all items from SN +// var iItemsKey items.ItemsKey +// var iItems items.EncryptedItems +// +// iItems, iItemsKey, err = i.Session.Session.Import(i.File, syncToken, "") +// if err != nil { +// return 0, err +// } +// +// if iItemsKey.ItemsKey == "" { +// panic(fmt.Sprintf("iItemsKey.ItemsKey is empty for: '%s'", iItemsKey.UUID)) +// } +// +// // push item and close db +// pii := cache.SyncInput{ +// Session: i.Session, +// Close: true, +// } +// +// _, err = Sync(pii, true) +// imported = len(iItems) +// +// return imported, err +// } diff --git a/export_test.go b/export_test.go index f051078..7f68f81 100644 --- a/export_test.go +++ b/export_test.go @@ -12,8 +12,8 @@ package sncli // require.NotEmpty(t, ik.CreatedAtTimestamp) // require.Empty(t, ik.UpdatedAtTimestamp) // require.Empty(t, ik.UpdatedAt) -// n, _ := gosn.NewNote("test title", "test content", nil) -// eis := gosn.Items{&n} +// n, _ := items.NewNote("test title", "test content", nil) +// eis := items.Items{&n} // encItems, err := eis.Encrypt(testSession.Session, ik) // require.NoError(t, err) // require.NotEmpty(t, encItems[0].UUID) @@ -25,8 +25,8 @@ package sncli // require.Empty(t, encItems[0].DuplicateOf) // // testSession.ItemsKeys = append(testSession.Session.ItemsKeys, ik) -// di, err := gosn.DecryptItems(testSession.Session, encItems, gosn.ItemsKeys{}) -// // di, err := encItems.Decrypt(testSession.Session, gosn.ItemsKeys{}) +// di, err := gosn.DecryptItems(testSession.Session, encItems, items.ItemsKeys{}) +// // di, err := encItems.Decrypt(testSession.Session, items.ItemsKeys{}) // // require.NoError(t, err) // require.NotEmpty(t, di) @@ -36,11 +36,11 @@ package sncli // require.NoError(t, err) // require.Greater(t, len(pi), 0) // -// var dn gosn.Note +// var dn items.Note // // for x := range pi { // if pi[x].GetContentType() == "Note" { -// dn = *pi[x].(*gosn.Note) +// dn = *pi[x].(*items.Note) // // } // } @@ -99,9 +99,9 @@ package sncli // allCacheItemsPreExport := len(existingItems) // allItemsKeysPreExport := len(testSession.ItemsKeys) // -// note, _ := gosn.NewNote("Example Title", "Some example text", nil) +// note, _ := items.NewNote("Example Title", "Some example text", nil) // -// itemsToPut := gosn.Items{ +// itemsToPut := items.Items{ // ¬e, // } // encItemsToPut, err := itemsToPut.Encrypt(testSession.Session, testSession.DefaultItemsKey) @@ -201,9 +201,9 @@ package sncli // var existingItems []cache.Item // err = gio.DB.All(&existingItems) // require.NoError(t, err) -// note, _ := gosn.NewNote("Example Title", "Some example text", nil) +// note, _ := items.NewNote("Example Title", "Some example text", nil) // -// itemsToPut := gosn.Items{ +// itemsToPut := items.Items{ // ¬e, // } // encItemsToPut, err := itemsToPut.Encrypt(testSession.Session, testSession.DefaultItemsKey) @@ -299,7 +299,7 @@ package sncli // itd, err := citd.ToItems(testSession) // require.NoError(t, err) // require.Len(t, itd, 1) -// dn := itd[0].(*gosn.Note) +// dn := itd[0].(*items.Note) // require.Equal(t, dn.Content.Title, note.Content.Title) // require.Equal(t, dn.Content.Text, note.Content.Text) // } @@ -311,8 +311,8 @@ package sncli // defer cleanUp(*testSession) // // // create and put initial originalNote -// originalNote, _ := gosn.NewNote("Example Title", "Some example text", nil) -// itemsToPut := gosn.Items{ +// originalNote, _ := items.NewNote("Example Title", "Some example text", nil) +// itemsToPut := items.Items{ // &originalNote, // } // @@ -358,7 +358,7 @@ package sncli // updatedNote.Content.SetTitle("Example Title UPDATED") // updatedNote.Content.SetText("Some example text UPDATED") // -// itemsToPut = gosn.Items{ +// itemsToPut = items.Items{ // &updatedNote, // } // @@ -403,9 +403,9 @@ package sncli // defer cleanUp(*testSession) // // // create and put initial originalTag -// originalTag, err := gosn.NewTag("Example Title", nil) +// originalTag, err := items.NewTag("Example Title", nil) // -// itemsToPut := gosn.Items{ +// itemsToPut := items.Items{ // &originalTag, // } // encItemsToPut, err := itemsToPut.Encrypt(testSession.Session, testSession.DefaultItemsKey) @@ -458,7 +458,7 @@ package sncli // // change initial originalTag and re-put // updatedTag := originalTag.Copy() // updatedTag.Content.SetTitle("Example Title UPDATED") -// itemsToPut = gosn.Items{ +// itemsToPut = items.Items{ // &updatedTag, // } // encItemsToPut, err = itemsToPut.Encrypt(testSession.Session, testSession.DefaultItemsKey) @@ -506,7 +506,7 @@ package sncli // require.NoError(t, gio.DB.All(&cItems)) // require.NoError(t, gio.DB.Close()) // -// var gItems gosn.Items +// var gItems items.Items // gItems, err = cItems.ToItems(testSession) // // require.NoError(t, err) @@ -515,7 +515,7 @@ package sncli // // for _, i := range gItems { // if i.GetContentType() == "Tag" { -// if i.(*gosn.Tag).Equals(originalTag) { +// if i.(*items.Tag).Equals(originalTag) { // found = true // } // } @@ -538,8 +538,8 @@ package sncli // require.NoError(t, err) // // // create and put originalTag -// originalTag, _ := gosn.NewTag("Example Title", nil) -// itemsToPut := gosn.Items{ +// originalTag, _ := items.NewTag("Example Title", nil) +// itemsToPut := items.Items{ // &originalTag, // } // @@ -602,7 +602,7 @@ package sncli // itd := dItems[0] // itd.SetDeleted(true) // -// itemsToPut = gosn.Items{ +// itemsToPut = items.Items{ // itd, // } // @@ -646,7 +646,7 @@ package sncli // // require.NoError(t, gio.DB.Close()) // -// var gItems gosn.Items +// var gItems items.Items // gItems, err = cItems.ToItems(testSession) // // require.NoError(t, err) diff --git a/go.mod b/go.mod index 576413b..747d528 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/fatih/color v1.16.0 github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/jonhadfield/gosn-v2 v0.0.0-20231207170939-dd07972e746d + github.com/jonhadfield/gosn-v2 v0.0.0-20231211221432-ebc6ca6dee6e github.com/ryanuber/columnize v2.1.2+incompatible github.com/spf13/viper v1.18.0 github.com/stretchr/testify v1.8.4 @@ -48,6 +48,8 @@ require ( require ( github.com/alessio/shellescape v1.4.2 // indirect github.com/google/uuid v1.4.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect diff --git a/go.sum b/go.sum index edc4db8..cdfcb3c 100644 --- a/go.sum +++ b/go.sum @@ -42,10 +42,18 @@ github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/jonhadfield/gosn-v2 v0.0.0-20231207170939-dd07972e746d h1:MTnvyVtov+FQrKRzWoD2vPDPZFdAy8cclf2yKm6xAh4= github.com/jonhadfield/gosn-v2 v0.0.0-20231207170939-dd07972e746d/go.mod h1:O3mpWoyBDVZFZdFXrUcydYseBJ4I6eDl1svCTbqxyXI= +github.com/jonhadfield/gosn-v2 v0.0.0-20231211221432-ebc6ca6dee6e h1:wxlOA9BRqoON8+z9Sg2uKVcybtkYxMupPJ7b52bL29o= +github.com/jonhadfield/gosn-v2 v0.0.0-20231211221432-ebc6ca6dee6e/go.mod h1:4/EdV1iRAKpaa4ZcF1TuniwRaajeWIMyMEWkrVnq/k8= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= diff --git a/healthcheck.go b/healthcheck.go index 57119f5..d1f86b3 100644 --- a/healthcheck.go +++ b/healthcheck.go @@ -2,21 +2,23 @@ package sncli import ( "fmt" - "github.com/briandowns/spinner" - "github.com/jonhadfield/gosn-v2" "os" "strings" "time" + + "github.com/briandowns/spinner" + "github.com/jonhadfield/gosn-v2/items" + "github.com/jonhadfield/gosn-v2/session" ) type ItemsKeysHealthcheckInput struct { - Session gosn.Session + Session session.Session UseStdOut bool DeleteInvalid bool } func ItemKeysHealthcheck(input ItemsKeysHealthcheckInput) error { - var so gosn.SyncOutput + var so items.SyncOutput var err error var syncToken string @@ -33,13 +35,13 @@ func ItemKeysHealthcheck(input ItemsKeysHealthcheckInput) error { s.Prefix = prefix s.Start() - so, err = gosn.Sync(gosn.SyncInput{ + so, err = items.Sync(items.SyncInput{ Session: &input.Session, }) s.Stop() } else { - so, err = gosn.Sync(gosn.SyncInput{ + so, err = items.Sync(items.SyncInput{ Session: &input.Session, }) } @@ -96,7 +98,7 @@ func ItemKeysHealthcheck(input ItemsKeysHealthcheckInput) error { fmt.Println() var itemsWithMissingKeys []string - var encitemsNotSpecifyingItemsKeyID gosn.EncryptedItems + var encitemsNotSpecifyingItemsKeyID items.EncryptedItems var itemsKeysNotEncryptedWithCurrentMasterKey []string var itemsKeysInUse []string var version003Items int64 @@ -116,7 +118,7 @@ func ItemKeysHealthcheck(input ItemsKeysHealthcheckInput) error { switch { case so.Items[x].ContentType == "SN|ItemsKey": - var ik gosn.ItemsKey + var ik items.ItemsKey ik, err = so.Items[x].Decrypt(input.Session.MasterKey) if err != nil || ik.ItemsKey == "" { itemsKeysNotEncryptedWithCurrentMasterKey = append(itemsKeysNotEncryptedWithCurrentMasterKey, @@ -129,7 +131,6 @@ func ItemKeysHealthcheck(input ItemsKeysHealthcheckInput) error { encitemsNotSpecifyingItemsKeyID = append(encitemsNotSpecifyingItemsKeyID, so.Items[x]) continue - } itemsKeysInUse = append(itemsKeysInUse, so.Items[x].ItemsKeyID) if !itemsKeyExists(so.Items[x].ItemsKeyID, seenItemsKeys) { @@ -184,14 +185,14 @@ func ItemKeysHealthcheck(input ItemsKeysHealthcheckInput) error { var c string _, err = fmt.Scanln(&c) if err == nil && StringInSlice(c, []string{"y", "yes"}, false) { - var itemsToDelete gosn.EncryptedItems + var itemsToDelete items.EncryptedItems for x := range encitemsNotSpecifyingItemsKeyID { itemToDelete := encitemsNotSpecifyingItemsKeyID[x] itemToDelete.Deleted = true itemsToDelete = append(itemsToDelete, itemToDelete) } - so, err = gosn.Sync(gosn.SyncInput{ + so, err = items.Sync(items.SyncInput{ SyncToken: syncToken, Session: &input.Session, Items: itemsToDelete, diff --git a/helpers.go b/helpers.go index ee1f485..13e67f9 100644 --- a/helpers.go +++ b/helpers.go @@ -8,7 +8,7 @@ import ( "os" "strings" - "github.com/jonhadfield/gosn-v2" + "github.com/jonhadfield/gosn-v2/items" ) func StringInSlice(inStr string, inSlice []string, matchCase bool) bool { @@ -63,7 +63,7 @@ type EncryptedItemExport struct { DuplicateOf *string `json:"duplicate_of"` } -func writeJSON(i ExportConfig, items gosn.EncryptedItems) error { +func writeJSON(i ExportConfig, items items.EncryptedItems) error { // prepare for export var itemsExport []EncryptedItemExport for x := range items { @@ -80,7 +80,6 @@ func writeJSON(i ExportConfig, items gosn.EncryptedItems) error { UpdatedAtTimestamp: items[x].UpdatedAtTimestamp, DuplicateOf: items[x].DuplicateOf, }) - } file, err := os.Create(i.File) @@ -98,7 +97,7 @@ func writeJSON(i ExportConfig, items gosn.EncryptedItems) error { content := strings.Builder{} content.WriteString("{\n \"version\": \"004\",") content.WriteString("\n \"items\": ") - content.WriteString(string(jsonExport)) + content.Write(jsonExport) content.WriteString(",") // add keyParams @@ -129,10 +128,10 @@ func readGob(filePath string, object interface{}) error { } type EncryptedItemsFile struct { - Items gosn.EncryptedItems `json:"items"` + Items items.EncryptedItems `json:"items"` } -func readJSON(filePath string) (items gosn.EncryptedItems, err error) { +func readJSON(filePath string) (items items.EncryptedItems, err error) { file, err := ioutil.ReadFile(filePath) if err != nil { err = fmt.Errorf("%w failed to open: %s", err, filePath) @@ -150,7 +149,7 @@ func readJSON(filePath string) (items gosn.EncryptedItems, err error) { return eif.Items, err } -func ItemRefsToYaml(irs []gosn.ItemReference) []ItemReferenceYAML { +func ItemRefsToYaml(irs []items.ItemReference) []ItemReferenceYAML { var iRefs []ItemReferenceYAML for _, ref := range irs { @@ -164,7 +163,7 @@ func ItemRefsToYaml(irs []gosn.ItemReference) []ItemReferenceYAML { return iRefs } -func ItemRefsToJSON(irs []gosn.ItemReference) []ItemReferenceJSON { +func ItemRefsToJSON(irs []items.ItemReference) []ItemReferenceJSON { var iRefs []ItemReferenceJSON for _, ref := range irs { @@ -198,7 +197,7 @@ func CommaSplit(i string) []string { return s } -func RemoveDeleted(in gosn.Items) (out gosn.Items) { +func RemoveDeleted(in items.Items) (out items.Items) { for _, i := range in { if !i.IsDeleted() { out = append(out, i) diff --git a/main.go b/main.go index 4eb097c..8770e9c 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,12 @@ package sncli import ( - "github.com/briandowns/spinner" - "github.com/jonhadfield/gosn-v2" - "github.com/jonhadfield/gosn-v2/cache" "os" "time" + + "github.com/briandowns/spinner" + "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" ) const ( @@ -39,13 +40,13 @@ type OrgStandardNotesSNDetailYAML struct { } type AppDataContentYAML struct { - OrgStandardNotesSN OrgStandardNotesSNDetailYAML `yaml:"org.standardnotes.sn"` - OrgStandardNotesSNComponents gosn.OrgStandardNotesSNComponentsDetail `yaml:"org.standardnotes.sn.components,omitempty"` + OrgStandardNotesSN OrgStandardNotesSNDetailYAML `yaml:"org.standardnotes.sn"` + OrgStandardNotesSNComponents items.OrgStandardNotesSNComponentsDetail `yaml:"org.standardnotes.sn.components,omitempty"` } type AppDataContentJSON struct { - OrgStandardNotesSN OrgStandardNotesSNDetailJSON `json:"org.standardnotes.sn"` - OrgStandardNotesSNComponents gosn.OrgStandardNotesSNComponentsDetail `json:"org.standardnotes.sn.components,omitempty"` + OrgStandardNotesSN OrgStandardNotesSNDetailJSON `json:"org.standardnotes.sn"` + OrgStandardNotesSNComponents items.OrgStandardNotesSNComponentsDetail `json:"org.standardnotes.sn.components,omitempty"` } type TagContentYAML struct { @@ -162,21 +163,21 @@ type AddTagsOutput struct { type GetTagConfig struct { Session *cache.Session - Filters gosn.ItemFilters + Filters items.ItemFilters Output string Debug bool } type GetSettingsConfig struct { Session *cache.Session - Filters gosn.ItemFilters + Filters items.ItemFilters Output string Debug bool } type GetNoteConfig struct { Session *cache.Session - Filters gosn.ItemFilters + Filters items.ItemFilters NoteTitles []string TagTitles []string TagUUIDs []string @@ -204,6 +205,15 @@ type AddNoteInput struct { Debug bool } +type DeleteItemConfig struct { + Session *cache.Session + NoteTitles []string + NoteText string + ItemsUUIDs []string + Regex bool + Debug bool +} + type DeleteNoteConfig struct { Session *cache.Session NoteTitles []string @@ -224,7 +234,7 @@ type StatsConfig struct { Session cache.Session } -func referenceExists(tag gosn.Tag, refID string) bool { +func referenceExists(tag items.Tag, refID string) bool { for _, ref := range tag.Content.References() { if ref.UUID == refID { return true @@ -234,7 +244,7 @@ func referenceExists(tag gosn.Tag, refID string) bool { return false } -func filterEncryptedItemsByTypes(ei gosn.EncryptedItems, types []string) (o gosn.EncryptedItems) { +func filterEncryptedItemsByTypes(ei items.EncryptedItems, types []string) (o items.EncryptedItems) { for _, i := range ei { if StringInSlice(i.ContentType, types, true) { o = append(o, i) @@ -244,7 +254,7 @@ func filterEncryptedItemsByTypes(ei gosn.EncryptedItems, types []string) (o gosn return o } -func filterItemsByTypes(ei gosn.Items, types []string) (o gosn.Items) { +func filterItemsByTypes(ei items.Items, types []string) (o items.Items) { for _, i := range ei { if StringInSlice(i.GetContentType(), types, true) { o = append(o, i) @@ -279,12 +289,12 @@ func (i *WipeConfig) Run() (int, error) { s.Prefix = prefix s.Start() - deleted, err := gosn.DeleteContent(i.Session.Session, i.Everything) + deleted, err := items.DeleteContent(i.Session.Session, i.Everything) s.Stop() return deleted, err } - return gosn.DeleteContent(i.Session.Session, i.Everything) + return items.DeleteContent(i.Session.Session, i.Everything) } diff --git a/note.go b/note.go index b6e2cb8..e747595 100644 --- a/note.go +++ b/note.go @@ -2,12 +2,13 @@ package sncli import ( "fmt" - "github.com/asdine/storm/v3/q" - "github.com/jonhadfield/gosn-v2" - "github.com/jonhadfield/gosn-v2/cache" "io/ioutil" "os" "path/filepath" + + "github.com/asdine/storm/v3/q" + "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" ) func (i *AddNoteInput) Run() (err error) { @@ -77,7 +78,7 @@ func addNote(i addNoteInput) (noteUUID string, err error) { } } - var noteToAdd gosn.Note + var noteToAdd items.Note si := cache.SyncInput{ Session: i.session, @@ -95,22 +96,22 @@ func addNote(i addNoteInput) (noteUUID string, err error) { if i.replace { gnc := GetNoteConfig{ Session: i.session, - // Filters: gosn.ItemFilters{}, - Filters: gosn.ItemFilters{ + // Filters: items.ItemFilters{}, + Filters: items.ItemFilters{ MatchAny: false, - Filters: []gosn.Filter{{ - Type: "Note", - Key: "Title", - Comparison: "==", - Value: i.noteTitle, - }, + Filters: []items.Filter{ + { + Type: "Note", + Key: "Title", + Comparison: "==", + Value: i.noteTitle, + }, }, }, } - var gi gosn.Items + var gi items.Items gi, err = gnc.Run() if err != nil { - return } switch len(gi) { @@ -127,7 +128,7 @@ func addNote(i addNoteInput) (noteUUID string, err error) { return } } else { - noteToAdd, err = gosn.NewNote(i.noteTitle, i.noteText, nil) + noteToAdd, err = items.NewNote(i.noteTitle, i.noteText, nil) if err != nil { return } @@ -141,7 +142,6 @@ func addNote(i addNoteInput) (noteUUID string, err error) { so, err = Sync(si, true) if err != nil { - return } @@ -152,11 +152,10 @@ func addNote(i addNoteInput) (noteUUID string, err error) { err = query.Find(&allEncTags) // it's ok if there are no tags, so only error if something else went wrong if err != nil && err.Error() != "not found" { - return } - if err = cache.SaveNotes(i.session, so.DB, gosn.Notes{noteToAdd}, false); err != nil { + if err = cache.SaveNotes(i.session, so.DB, items.Notes{noteToAdd}, false); err != nil { return } @@ -192,13 +191,19 @@ func addNote(i addNoteInput) (noteUUID string, err error) { return noteUUID, err } +func (i *DeleteItemConfig) Run() (noDeleted int, err error) { + noDeleted, err = deleteItems(i.Session, []string{}, "", i.ItemsUUIDs, i.Regex) + + return noDeleted, err +} + func (i *DeleteNoteConfig) Run() (noDeleted int, err error) { noDeleted, err = deleteNotes(i.Session, i.NoteTitles, i.NoteText, i.NoteUUIDs, i.Regex) return noDeleted, err } -func (i *GetNoteConfig) Run() (items gosn.Items, err error) { +func (i *GetNoteConfig) Run() (items items.Items, err error) { var so cache.SyncOutput so, err = Sync(cache.SyncInput{ Session: i.Session, @@ -231,7 +236,7 @@ func (i *GetNoteConfig) Run() (items gosn.Items, err error) { } func deleteNotes(session *cache.Session, noteTitles []string, noteText string, noteUUIDs []string, regex bool) (noDeleted int, err error) { - var getNotesFilters []gosn.Filter + var getNotesFilters []items.Filter switch { case len(noteTitles) > 0: @@ -241,7 +246,7 @@ func deleteNotes(session *cache.Session, noteTitles []string, noteText string, n comparison = "~" } - getNotesFilters = append(getNotesFilters, gosn.Filter{ + getNotesFilters = append(getNotesFilters, items.Filter{ Key: "Title", Value: title, Comparison: comparison, @@ -254,7 +259,7 @@ func deleteNotes(session *cache.Session, noteTitles []string, noteText string, n comparison = "~" } - getNotesFilters = append(getNotesFilters, gosn.Filter{ + getNotesFilters = append(getNotesFilters, items.Filter{ Key: "Text", Value: noteText, Comparison: comparison, @@ -262,7 +267,7 @@ func deleteNotes(session *cache.Session, noteTitles []string, noteText string, n }) case len(noteUUIDs) > 0: for _, uuid := range noteUUIDs { - getNotesFilters = append(getNotesFilters, gosn.Filter{ + getNotesFilters = append(getNotesFilters, items.Filter{ Key: "UUID", Value: uuid, Comparison: "==", @@ -271,7 +276,7 @@ func deleteNotes(session *cache.Session, noteTitles []string, noteText string, n } } - itemFilter := gosn.ItemFilters{ + itemFilter := items.ItemFilters{ Filters: getNotesFilters, MatchAny: true, } @@ -295,7 +300,7 @@ func deleteNotes(session *cache.Session, noteTitles []string, noteText string, n return } - var notes gosn.Items + var notes items.Items notes, err = allPersistedItems.ToItems(session) if err != nil { @@ -303,13 +308,13 @@ func deleteNotes(session *cache.Session, noteTitles []string, noteText string, n } notes.Filter(itemFilter) - var notesToDelete gosn.Notes + var notesToDelete items.Notes for _, item := range notes { if item.GetContentType() != "Note" { panic(fmt.Sprintf("Got a non-note item in the notes list: %s", item.GetContentType())) } - note := item.(*gosn.Note) + note := item.(*items.Note) if note.GetContent() != nil { note.Content.SetText("") note.SetDeleted(true) @@ -330,10 +335,111 @@ func deleteNotes(session *cache.Session, noteTitles []string, noteText string, n } pii.Close = true - gio, err = Sync(pii, true) + _, err = Sync(pii, true) if err != nil { return } return len(notesToDelete), err } + +func deleteItems(session *cache.Session, noteTitles []string, noteText string, itemUUIDs []string, regex bool) (noDeleted int, err error) { + var getItemsFilters []items.Filter + + switch { + case len(noteTitles) > 0: + for _, title := range noteTitles { + comparison := "==" + if regex { + comparison = "~" + } + + getItemsFilters = append(getItemsFilters, items.Filter{ + Key: "Title", + Value: title, + Comparison: comparison, + Type: "Note", + }) + } + case noteText != "": + comparison := "==" + if regex { + comparison = "~" + } + + getItemsFilters = append(getItemsFilters, items.Filter{ + Key: "Text", + Value: noteText, + Comparison: comparison, + Type: "Note", + }) + case len(itemUUIDs) > 0: + for _, uuid := range itemUUIDs { + getItemsFilters = append(getItemsFilters, items.Filter{ + Key: "UUID", + Value: uuid, + Comparison: "==", + Type: "Anything", + }) + } + } + + itemFilter := items.ItemFilters{ + Filters: getItemsFilters, + MatchAny: true, + } + + getItemsInput := cache.SyncInput{ + Session: session, + } + + var gio cache.SyncOutput + + gio, err = Sync(getItemsInput, true) + if err != nil { + return + } + + var allPersistedItems cache.Items + + err = gio.DB.All(&allPersistedItems) + if err != nil { + err = fmt.Errorf("getting items from db: %w", err) + return + } + + var pItems items.Items + + pItems, err = allPersistedItems.ToItems(session) + if err != nil { + return + } + + pItems.Filter(itemFilter) + var itemsToDelete items.Items + + for _, pItem := range pItems { + pItem.SetDeleted(true) + itemsToDelete = append(itemsToDelete, pItem) + } + + if itemsToDelete == nil { + return + } + + if err = cache.SaveItems(session, gio.DB, itemsToDelete, true); err != nil { + return 0, err + } + + pii := cache.SyncInput{ + Session: session, + } + + pii.Close = true + _, err = Sync(pii, true) + if err != nil { + return + } + + return len(itemsToDelete), err +} diff --git a/note_test.go b/note_test.go index 9e50ade..9d81fd1 100644 --- a/note_test.go +++ b/note_test.go @@ -2,7 +2,6 @@ package sncli import ( "fmt" - "github.com/stretchr/testify/require" "log" "os" "strconv" @@ -10,13 +9,17 @@ import ( "testing" "time" - "github.com/jonhadfield/gosn-v2" + "github.com/jonhadfield/gosn-v2/auth" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/common" + "github.com/jonhadfield/gosn-v2/items" + "github.com/jonhadfield/gosn-v2/session" + "github.com/stretchr/testify/require" ) var ( testSession *cache.Session - gTtestSession *gosn.Session + gTtestSession *session.Session testUserEmail string testUserPassword string ) @@ -26,7 +29,7 @@ func localTestMain() { testUserEmail = fmt.Sprintf("ramea-%s", strconv.FormatInt(time.Now().UnixNano(), 16)) testUserPassword = "secretsanta" - rInput := gosn.RegisterInput{ + rInput := auth.RegisterInput{ Password: testUserPassword, Email: testUserEmail, APIServer: localServer, @@ -43,12 +46,40 @@ func localTestMain() { } func signIn(server, email, password string) { - ts, err := gosn.CliSignIn(email, password, server, true) + ts, err := auth.CliSignIn(email, password, server, true) if err != nil { log.Fatal(err) } - gTtestSession = &ts + if server == "" { + server = SNServerURL + } + + gTtestSession = &session.Session{ + Debug: true, + HTTPClient: common.NewHTTPClient(), + SchemaValidation: false, + Server: server, + FilesServerUrl: ts.FilesServerUrl, + Token: "", + MasterKey: ts.MasterKey, + ItemsKeys: nil, + DefaultItemsKey: session.SessionItemsKey{}, + KeyParams: auth.KeyParams{}, + AccessToken: ts.AccessToken, + RefreshToken: ts.RefreshToken, + AccessExpiration: ts.AccessExpiration, + RefreshExpiration: ts.RefreshExpiration, + ReadOnlyAccess: ts.ReadOnlyAccess, + PasswordNonce: ts.PasswordNonce, + Schemas: nil, + } + + testSession = &cache.Session{ + Session: gTtestSession, + CacheDB: nil, + CacheDBPath: "", + } } func TestMain(m *testing.M) { @@ -56,24 +87,42 @@ func TestMain(m *testing.M) { if strings.Contains(os.Getenv("SN_SERVER"), "ramea") { localTestMain() } else { - signIn(os.Getenv("SN_SERVER"), os.Getenv("SN_EMAIL"), os.Getenv("SN_PASSWORD")) + signIn(SNServerURL, os.Getenv("SN_EMAIL"), os.Getenv("SN_PASSWORD")) } - if _, err := gosn.Sync(gosn.SyncInput{Session: gTtestSession}); err != nil { + if _, err := items.Sync(items.SyncInput{Session: gTtestSession}); err != nil { log.Fatal(err) } if gTtestSession.DefaultItemsKey.ItemsKey == "" { panic("failed in TestMain due to empty default items key") } + if strings.TrimSpace(gTtestSession.Server) == "" { + panic("failed in TestMain due to empty server") + } var err error - testSession, err = cache.ImportSession(gTtestSession, "") + testSession, err = cache.ImportSession(&auth.SignInResponseDataSession{ + Debug: gTtestSession.Debug, + HTTPClient: gTtestSession.HTTPClient, + SchemaValidation: false, + Server: gTtestSession.Server, + FilesServerUrl: gTtestSession.FilesServerUrl, + Token: "", + MasterKey: gTtestSession.MasterKey, + KeyParams: gTtestSession.KeyParams, + AccessToken: gTtestSession.AccessToken, + RefreshToken: gTtestSession.RefreshToken, + AccessExpiration: gTtestSession.AccessExpiration, + RefreshExpiration: gTtestSession.RefreshExpiration, + ReadOnlyAccess: gTtestSession.ReadOnlyAccess, + PasswordNonce: gTtestSession.PasswordNonce, + }, "") if err != nil { return } - testSession.CacheDBPath, err = cache.GenCacheDBPath(*testSession, "", gosn.LibName) + testSession.CacheDBPath, err = cache.GenCacheDBPath(*testSession, "", common.LibName) if err != nil { panic(err) } @@ -97,22 +146,22 @@ func TestAddDeleteNoteByUUID(t *testing.T) { require.NoError(t, err) // get new note - filter := gosn.Filter{ + filter := items.Filter{ Type: "Note", Key: "Title", Comparison: "==", Value: "TestNoteOne", } - iFilter := gosn.ItemFilters{ - Filters: []gosn.Filter{filter}, + iFilter := items.ItemFilters{ + Filters: []items.Filter{filter}, } gnc := GetNoteConfig{ Session: testSession, Filters: iFilter, } - var preRes, postRes gosn.Items + var preRes, postRes items.Items preRes, err = gnc.Run() @@ -151,9 +200,9 @@ func TestReplaceNote(t *testing.T) { // get new note gnc := GetNoteConfig{ Session: testSession, - Filters: gosn.ItemFilters{ + Filters: items.ItemFilters{ MatchAny: false, - Filters: []gosn.Filter{{ + Filters: []items.Filter{{ Type: "Note", Key: "Title", Comparison: "==", @@ -167,7 +216,7 @@ func TestReplaceNote(t *testing.T) { }, } - var preReplace, postReplace gosn.Items + var preReplace, postReplace items.Items preReplace, err := gnc.Run() require.NoError(t, err, err) @@ -186,9 +235,9 @@ func TestReplaceNote(t *testing.T) { // get updated note gnc = GetNoteConfig{ Session: testSession, - Filters: gosn.ItemFilters{ + Filters: items.ItemFilters{ MatchAny: false, - Filters: []gosn.Filter{{ + Filters: []items.Filter{{ Type: "Note", Key: "Title", Comparison: "==", @@ -209,9 +258,9 @@ func TestReplaceNote(t *testing.T) { // check only one note with that title exists gnc = GetNoteConfig{ Session: testSession, - Filters: gosn.ItemFilters{ + Filters: items.ItemFilters{ MatchAny: false, - Filters: []gosn.Filter{{ + Filters: []items.Filter{{ Type: "Note", Key: "Title", Comparison: "==", @@ -221,7 +270,7 @@ func TestReplaceNote(t *testing.T) { } highlander, err := gnc.Run() - require.NoError(t, err, err) + require.NoError(t, err) require.Len(t, highlander, 1) } @@ -239,11 +288,11 @@ func TestWipeWith50(t *testing.T) { require.NoError(t, err) // check notes created - noteFilter := gosn.Filter{ + noteFilter := items.Filter{ Type: "Note", } - filters := gosn.ItemFilters{ - Filters: []gosn.Filter{noteFilter}, + filters := items.ItemFilters{ + Filters: []items.Filter{noteFilter}, } gni := cache.SyncInput{ Session: testSession, @@ -256,21 +305,21 @@ func TestWipeWith50(t *testing.T) { require.NotNil(t, gno.DB) // get items from db - var items cache.Items + var cItems cache.Items - require.NoError(t, gno.DB.All(&items)) + require.NoError(t, gno.DB.All(&cItems)) require.NoError(t, gno.DB.Close()) var nonotes int - for _, i := range items { + for _, i := range cItems { if i.ContentType == "Note" { nonotes++ } } - var gItems gosn.Items - gItems, err = items.ToItems(testSession) + var gItems items.Items + gItems, err = cItems.ToItems(testSession) require.NoError(t, err) @@ -314,22 +363,22 @@ func TestAddDeleteNoteByTitle(t *testing.T) { require.Equal(t, 1, noDeleted) require.NoError(t, err) - filter := gosn.Filter{ + filter := items.Filter{ Type: "Note", Key: "Title", Comparison: "==", Value: "TestNoteOne", } - iFilter := gosn.ItemFilters{ - Filters: []gosn.Filter{filter}, + iFilter := items.ItemFilters{ + Filters: []items.Filter{filter}, } gnc := GetNoteConfig{ Session: testSession, Filters: iFilter, } - var postRes gosn.Items + var postRes items.Items postRes, err = gnc.Run() require.NoError(t, err) require.EqualValues(t, len(postRes), 0, "note was not deleted") @@ -360,21 +409,21 @@ func TestAddDeleteNoteByTitleRegex(t *testing.T) { require.NoError(t, err) // get same note again - filter := gosn.Filter{ + filter := items.Filter{ Type: "Note", Key: "Title", Comparison: "==", Value: "TestNoteOne", } - iFilter := gosn.ItemFilters{ - Filters: []gosn.Filter{filter}, + iFilter := items.ItemFilters{ + Filters: []items.Filter{filter}, } gnc := GetNoteConfig{ Session: testSession, Filters: iFilter, } - var postRes gosn.Items + var postRes items.Items postRes, err = gnc.Run() require.NoError(t, err) @@ -394,23 +443,23 @@ func TestGetNote(t *testing.T) { err := addNoteConfig.Run() require.NoError(t, err) - noteFilter := gosn.Filter{ + noteFilter := items.Filter{ Type: "Note", Key: "Title", Comparison: "==", Value: "TestNoteOne", } // retrieve one note - itemFilters := gosn.ItemFilters{ + itemFilters := items.ItemFilters{ MatchAny: false, - Filters: []gosn.Filter{noteFilter}, + Filters: []items.Filter{noteFilter}, } getNoteConfig := GetNoteConfig{ Session: testSession, Filters: itemFilters, } - var output gosn.Items + var output items.Items output, err = getNoteConfig.Run() require.NoError(t, err) require.EqualValues(t, 1, len(output)) @@ -427,11 +476,11 @@ func TestCreateOneHundredNotes(t *testing.T) { err := createNotes(testSession, numNotes, textParas) require.NoError(t, err) - noteFilter := gosn.Filter{ + noteFilter := items.Filter{ Type: "Note", } - filter := gosn.ItemFilters{ - Filters: []gosn.Filter{noteFilter}, + filter := items.ItemFilters{ + Filters: []items.Filter{noteFilter}, } gnc := GetNoteConfig{ @@ -439,11 +488,11 @@ func TestCreateOneHundredNotes(t *testing.T) { Filters: filter, } - var res gosn.Items + var res items.Items res, err = gnc.Run() require.NoError(t, err) - require.True(t, len(res) >= numNotes) + require.GreaterOrEqual(t, len(res), numNotes) wipeConfig := WipeConfig{ Session: testSession, @@ -452,13 +501,12 @@ func TestCreateOneHundredNotes(t *testing.T) { var deleted int deleted, err = wipeConfig.Run() require.NoError(t, err) - require.True(t, deleted >= numNotes) + require.GreaterOrEqual(t, deleted, numNotes) } func cleanUp(session cache.Session) { session.RemoveDB() - _, err := gosn.DeleteContent(session.Session, true) - + _, err := items.DeleteContent(session.Session, true) if err != nil { panic(err) } diff --git a/register.go b/register.go index 7d7cc0a..4235b37 100644 --- a/register.go +++ b/register.go @@ -1,8 +1,6 @@ package sncli -import ( - "github.com/jonhadfield/gosn-v2" -) +import "github.com/jonhadfield/gosn-v2/auth" type RegisterConfig struct { Email string @@ -12,7 +10,7 @@ type RegisterConfig struct { } func (i *RegisterConfig) Run() error { - registerInput := gosn.RegisterInput{ + registerInput := auth.RegisterInput{ Email: i.Email, Password: i.Password, APIServer: i.APIServer, diff --git a/settings.go b/settings.go index 7a046c2..ed223bd 100644 --- a/settings.go +++ b/settings.go @@ -1,11 +1,11 @@ package sncli import ( - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" ) -func (i *GetSettingsConfig) Run() (settings gosn.Items, err error) { +func (i *GetSettingsConfig) Run() (settings items.Items, err error) { getItemsInput := cache.SyncInput{ Session: i.Session, } @@ -24,7 +24,7 @@ func (i *GetSettingsConfig) Run() (settings gosn.Items, err error) { return } - var items gosn.Items + var items items.Items items, err = allPersistedItems.ToItems(i.Session) if err != nil { diff --git a/stats.go b/stats.go index 0af638a..ddd78d6 100644 --- a/stats.go +++ b/stats.go @@ -6,8 +6,8 @@ import ( "time" "github.com/fatih/color" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" "github.com/ryanuber/columnize" ) @@ -21,7 +21,7 @@ var ( type stats struct { oldestNote, newestNote, lastUpdatedNote time.Time - hasOrphanedRefs []gosn.Item + hasOrphanedRefs []items.Item } func (i *StatsConfig) Run() error { @@ -43,13 +43,13 @@ func (i *StatsConfig) Run() error { return err } - var items gosn.Items - items, err = allPersistedItems.ToItems(&i.Session) + var gitems items.Items + gitems, err = allPersistedItems.ToItems(&i.Session) if err != nil { return err } - var notes gosn.Items + var notes items.Items var missingItemsKey []string @@ -68,11 +68,11 @@ func (i *StatsConfig) Run() error { tCounter.counts = make(map[string]int64) - for _, item := range items { + for _, item := range gitems { // check if item is trashed note var isTrashedNote bool if item.GetContentType() == "Note" { - n := item.(*gosn.Note) + n := item.(*items.Note) if n.Content.Trashed != nil && *n.Content.Trashed { isTrashedNote = true } @@ -174,7 +174,7 @@ func (i *StatsConfig) Run() error { } for x := 0; x < finalItem; x++ { - note := notes[x].(*gosn.Note) + note := notes[x].(*items.Note) fmt.Printf(" - %d bytes: \"%s\"\n", note.GetContentSize(), note.Content.Title) } } else { diff --git a/tag.go b/tag.go index 247d418..5e241cb 100644 --- a/tag.go +++ b/tag.go @@ -3,8 +3,8 @@ package sncli import ( "strings" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" ) type tagNotesInput struct { @@ -35,14 +35,14 @@ func tagNotes(i tagNotesInput) (err error) { } // get notes and tags - getNotesFilter := gosn.Filter{ + getNotesFilter := items.Filter{ Type: "Note", } - getTagsFilter := gosn.Filter{ + getTagsFilter := items.Filter{ Type: "Tag", } - filters := []gosn.Filter{getNotesFilter, getTagsFilter} - itemFilter := gosn.ItemFilters{ + filters := []items.Filter{getNotesFilter, getTagsFilter} + itemFilter := items.ItemFilters{ MatchAny: true, Filters: filters, } @@ -64,31 +64,31 @@ func tagNotes(i tagNotesInput) (err error) { return } - var items gosn.Items + var gItems items.Items - items, err = allPersistedItems.ToItems(i.session) + gItems, err = allPersistedItems.ToItems(i.session) if err != nil { return } - items.Filter(itemFilter) + gItems.Filter(itemFilter) - var allTags []*gosn.Tag + var allTags []*items.Tag - var allNotes []*gosn.Note + var allNotes []*items.Note // create slices of notes and tags - for _, item := range items { + for _, item := range gItems { if item.IsDeleted() { continue } if item.GetContentType() == "Tag" { - allTags = append(allTags, item.(*gosn.Tag)) + allTags = append(allTags, item.(*items.Tag)) } if item.GetContentType() == "Note" { - allNotes = append(allNotes, item.(*gosn.Note)) + allNotes = append(allNotes, item.(*items.Note)) } } @@ -108,7 +108,7 @@ func tagNotes(i tagNotesInput) (err error) { // update existing (and just created) tags to reference matching uuids // determine which TAGS need updating and create list to sync back to server - var tagsToPush gosn.Tags + var tagsToPush items.Tags for _, t := range allTags { // if tag title is in ones to add then update tag with new references @@ -189,7 +189,7 @@ func (i *AddTagsInput) Run() (output AddTagsOutput, err error) { var ato addTagsOutput ato, err = addTags(ati) if err != nil { - return + return AddTagsOutput{}, err } output.Added = ato.added @@ -211,7 +211,7 @@ func (i *AddTagsInput) Run() (output AddTagsOutput, err error) { return output, err } -func (i *GetTagConfig) Run() (items gosn.Items, err error) { +func (i *GetTagConfig) Run() (items items.Items, err error) { var so cache.SyncOutput si := cache.SyncInput{ @@ -220,7 +220,7 @@ func (i *GetTagConfig) Run() (items gosn.Items, err error) { so, err = Sync(si, true) if err != nil { - return + return items, err } var allPersistedItems cache.Items @@ -251,11 +251,11 @@ func (i *DeleteTagConfig) Run() (noDeleted int, err error) { } func deleteTags(session *cache.Session, tagTitles []string, tagUUIDs []string) (noDeleted int, err error) { - deleteTagsFilter := gosn.Filter{ + deleteTagsFilter := items.Filter{ Type: "Tag", } - filters := []gosn.Filter{deleteTagsFilter} - deleteFilter := gosn.ItemFilters{ + filters := []items.Filter{deleteTagsFilter} + deleteFilter := items.ItemFilters{ MatchAny: true, Filters: filters, } @@ -276,7 +276,7 @@ func deleteTags(session *cache.Session, tagTitles []string, tagUUIDs []string) ( _ = so.DB.Close() }() - var tags gosn.Items + var tags items.Items // get items from db var allPersistedItems cache.Items @@ -286,26 +286,26 @@ func deleteTags(session *cache.Session, tagTitles []string, tagUUIDs []string) ( return } - var items gosn.Items + var gItems items.Items - items, err = allPersistedItems.ToItems(session) + gItems, err = allPersistedItems.ToItems(session) if err != nil { return } - tags = items + tags = gItems tags.Filter(deleteFilter) - var tagsToDelete gosn.Items + var tagsToDelete items.Items for _, tag := range tags { if tag.IsDeleted() { continue } - var gTag *gosn.Tag + var gTag *items.Tag if tag.GetContentType() == "Tag" { - gTag = tag.(*gosn.Tag) + gTag = tag.(*items.Tag) } else { continue } @@ -317,7 +317,7 @@ func deleteTags(session *cache.Session, tagTitles []string, tagUUIDs []string) ( } } - var eTagsToDelete gosn.EncryptedItems + var eTagsToDelete items.EncryptedItems eTagsToDelete, err = tagsToDelete.Encrypt(session.Session, session.DefaultItemsKey) if err != nil { @@ -358,13 +358,13 @@ type addTagsOutput struct { func addTags(ati addTagsInput) (ato addTagsOutput, err error) { // get all tags - addTagsFilter := gosn.Filter{ + addTagsFilter := items.Filter{ Type: "Tag", } - filters := []gosn.Filter{addTagsFilter} + filters := []items.Filter{addTagsFilter} - addFilter := gosn.ItemFilters{ + addFilter := items.ItemFilters{ MatchAny: true, Filters: filters, } @@ -386,8 +386,8 @@ func addTags(ati addTagsInput) (ato addTagsOutput, err error) { return } - var items gosn.Items - items, err = allPersistedItems.ToItems(ati.session) + var gItems items.Items + gItems, err = allPersistedItems.ToItems(ati.session) if err != nil { return } @@ -396,22 +396,22 @@ func addTags(ati addTagsInput) (ato addTagsOutput, err error) { return } - items.Filter(addFilter) + gItems.Filter(addFilter) - var allTags gosn.Tags + var allTags items.Tags - for _, item := range items { + for _, item := range gItems { if item.IsDeleted() { continue } if item.GetContentType() == "Tag" { - tag := item.(*gosn.Tag) + tag := item.(*items.Tag) allTags = append(allTags, *tag) } } - var tagsToAdd gosn.Tags + var tagsToAdd items.Tags for _, tag := range ati.tagTitles { if tagExists(allTags, tag) { @@ -419,7 +419,7 @@ func addTags(ati addTagsInput) (ato addTagsOutput, err error) { continue } - newTag, _ := gosn.NewTag(tag, nil) + newTag, _ := items.NewTag(tag, nil) tagsToAdd = append(tagsToAdd, newTag) ato.added = append(ato.added, tag) @@ -431,7 +431,7 @@ func addTags(ati addTagsInput) (ato addTagsOutput, err error) { return } - var eTagsToAdd gosn.EncryptedItems + var eTagsToAdd items.EncryptedItems eTagsToAdd, err = tagsToAdd.Encrypt(ati.session.Gosn()) if err != nil { @@ -457,16 +457,16 @@ func addTags(ati addTagsInput) (ato addTagsOutput, err error) { return ato, err } -func upsertTagReferences(tag gosn.Tag, typeUUIDs map[string][]string) (gosn.Tag, bool) { +func upsertTagReferences(tag items.Tag, typeUUIDs map[string][]string) (items.Tag, bool) { // create item reference - var newReferences []gosn.ItemReference + var newReferences []items.ItemReference var changed bool for k, v := range typeUUIDs { for _, ref := range v { if !referenceExists(tag, ref) { - newReferences = append(newReferences, gosn.ItemReference{ + newReferences = append(newReferences, items.ItemReference{ ContentType: k, UUID: ref, }) @@ -484,7 +484,7 @@ func upsertTagReferences(tag gosn.Tag, typeUUIDs map[string][]string) (gosn.Tag, return tag, changed } -func tagExists(existing []gosn.Tag, find string) bool { +func tagExists(existing []items.Tag, find string) bool { for _, tag := range existing { if tag.Content.GetTitle() == find { return true diff --git a/tag_test.go b/tag_test.go index abc701d..a2ffc37 100644 --- a/tag_test.go +++ b/tag_test.go @@ -1,11 +1,11 @@ package sncli import ( - "github.com/stretchr/testify/require" "testing" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" + "github.com/stretchr/testify/require" ) func TestAddDeleteTagByTitle(t *testing.T) { @@ -52,12 +52,12 @@ func TestGetTag(t *testing.T) { require.Empty(t, ato.Existing) // create filters - getTagFilters := gosn.ItemFilters{ + getTagFilters := items.ItemFilters{ MatchAny: true, } for _, testTagTitle := range testTagTitles { - getTagFilters.Filters = append(getTagFilters.Filters, gosn.Filter{ + getTagFilters.Filters = append(getTagFilters.Filters, items.Filter{ Key: "Title", Value: testTagTitle, Type: "Tag", @@ -70,7 +70,7 @@ func TestGetTag(t *testing.T) { Filters: getTagFilters, } - var output gosn.Items + var output items.Items output, err = getTagConfig.Run() require.NoError(t, err) require.EqualValues(t, len(output), 2, "expected two items but got: %+v", output) @@ -144,14 +144,14 @@ func TestTaggingOfNotes(t *testing.T) { err = tni.Run() require.NoError(t, err) - filterNotesByTagName := gosn.Filter{ + filterNotesByTagName := items.Filter{ Type: "Note", Key: "TagTitle", Comparison: "==", Value: "testTag", } - itemFilters := gosn.ItemFilters{ - Filters: []gosn.Filter{filterNotesByTagName}, + itemFilters := items.ItemFilters{ + Filters: []items.Filter{filterNotesByTagName}, MatchAny: true, } gnc := GetNoteConfig{ @@ -159,7 +159,7 @@ func TestTaggingOfNotes(t *testing.T) { Filters: itemFilters, } - var retNotes gosn.Items + var retNotes items.Items retNotes, err = gnc.Run() require.NoError(t, err) diff --git a/test_data.go b/test_data.go index 0bccf4e..d5964dc 100644 --- a/test_data.go +++ b/test_data.go @@ -6,8 +6,9 @@ import ( "strings" "time" - "github.com/jonhadfield/gosn-v2" "github.com/jonhadfield/gosn-v2/cache" + "github.com/jonhadfield/gosn-v2/items" + "github.com/jonhadfield/gosn-v2/session" ) var testParas = []string{ @@ -76,18 +77,18 @@ func genRandomText(paragraphs int) string { return strBuilder.String() } -func genNotes(num, textParas int) (notes gosn.Items) { +func genNotes(num, textParas int) (notes items.Items) { for i := 1; i <= num; i++ { - note, _ := gosn.NewNote(fmt.Sprintf("%d.%s", i, genRandomText(1)), genRandomText(textParas), nil) + note, _ := items.NewNote(fmt.Sprintf("%d.%s", i, genRandomText(1)), genRandomText(textParas), nil) notes = append(notes, ¬e) } return notes } -func genTags(num int64) (tags gosn.Items) { +func genTags(num int64) (tags items.Items) { for i := int64(1); i <= num; i++ { - tag, _ := gosn.NewTag(genRandomText(1), nil) + tag, _ := items.NewTag(genRandomText(1), nil) tags = append(tags, &tag) } @@ -99,7 +100,7 @@ func createNotes(session *cache.Session, num int, paras int) error { pii.Session = session gendNotes := genNotes(num, paras) - var eGendNotes gosn.EncryptedItems + var eGendNotes items.EncryptedItems var err error @@ -138,19 +139,19 @@ func createNotes(session *cache.Session, num int, paras int) error { return err } -func createTags(session gosn.Session, num int64) error { - var pii gosn.SyncInput +func createTags(session session.Session, num int64) error { + var pii items.SyncInput pii.Session = &session gendTags := genTags(num) - var eGendTags gosn.EncryptedItems + var eGendTags items.EncryptedItems eGendTags, err := gendTags.Encrypt(&session, session.DefaultItemsKey) if err != nil { return err } pii.Items = eGendTags - _, err = gosn.Sync(pii) + _, err = items.Sync(pii) return err } @@ -163,7 +164,7 @@ type TestDataCreateNotesConfig struct { } type TestDataCreateTagsConfig struct { - Session gosn.Session + Session session.Session NumTags int64 Debug bool }