Skip to content

Commit cdfe187

Browse files
authored
Merge pull request #36 from pythonhacker/issue-30-tag
Issue 30 tag
2 parents e806ecb + f5bc4a8 commit cdfe187

File tree

5 files changed

+186
-26
lines changed

5 files changed

+186
-26
lines changed

actions.go

+97-17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/csv"
77
"errors"
88
"fmt"
9+
"gorm.io/gorm"
910
"os"
1011
"os/exec"
1112
"os/signal"
@@ -175,14 +176,19 @@ func setActiveDatabasePath(dbPath string) error {
175176
}
176177

177178
if newEncrypted {
178-
// Decrypt new database if it is encrypted
179-
fmt.Printf("Database %s is encrypted, decrypting it\n", fullPath)
180-
err, _ = decryptDatabase(fullPath)
181-
if err != nil {
182-
fmt.Printf("Decryption Error - \"%s\", not switching databases\n", err.Error())
183-
return err
179+
if !settings.AutoEncrypt {
180+
// Decrypt new database if it is encrypted
181+
fmt.Printf("Database %s is encrypted, decrypting it\n", fullPath)
182+
err, _ = decryptDatabase(fullPath)
183+
if err != nil {
184+
fmt.Printf("Decryption Error - \"%s\", not switching databases\n", err.Error())
185+
return err
186+
} else {
187+
newEncrypted = false
188+
}
184189
} else {
185-
newEncrypted = false
190+
// New database is encrypted and autoencrypt is set - so keep it like that
191+
// fmt.Printf("Database %s is already encrypted, nothing to do\n", fullPath)
186192
}
187193
}
188194
}
@@ -193,7 +199,7 @@ func setActiveDatabasePath(dbPath string) error {
193199
return nil
194200
}
195201

196-
if newEncrypted {
202+
if newEncrypted && !settings.AutoEncrypt {
197203
// Use should manually decrypt before switching
198204
fmt.Println("Auto-encrypt disabled, decrypt new database manually before switching.")
199205
return nil
@@ -223,6 +229,7 @@ func addNewEntry() error {
223229
var url string
224230
var notes string
225231
var passwd string
232+
var tags string
226233
var err error
227234
var customEntries []CustomEntry
228235

@@ -250,7 +257,8 @@ func addNewEntry() error {
250257
}
251258
// fmt.Printf("Password => %s\n", passwd)
252259

253-
notes = readInput(reader, "\nNotes")
260+
tags = readInput(reader, "\nTags (separated by space): ")
261+
notes = readInput(reader, "Notes")
254262

255263
// Title and username/password are mandatory
256264
if len(title) == 0 {
@@ -269,7 +277,7 @@ func addNewEntry() error {
269277
customEntries = addCustomFields(reader)
270278

271279
// Trim spaces
272-
err = addNewDatabaseEntry(title, userName, url, passwd, notes, customEntries)
280+
err = addNewDatabaseEntry(title, userName, url, passwd, tags, notes, customEntries)
273281

274282
if err != nil {
275283
fmt.Printf("Error adding entry - \"%s\"\n", err.Error())
@@ -299,7 +307,7 @@ func addOrUpdateCustomFields(reader *bufio.Reader, entry *Entry) ([]CustomEntry,
299307
fmt.Println("Field Name: " + customEntry.FieldName)
300308
fieldName = readInput(reader, "\tNew Field Name (Enter to keep, \"x\" to delete)")
301309
if strings.ToLower(strings.TrimSpace(fieldName)) == "x" {
302-
fmt.Println("Deleting field " + fieldName)
310+
fmt.Println("Deleting field: " + customEntry.FieldName)
303311
} else {
304312
if strings.TrimSpace(fieldName) == "" {
305313
fieldName = customEntry.FieldName
@@ -365,6 +373,7 @@ func editCurrentEntry(idString string) error {
365373
var title string
366374
var url string
367375
var notes string
376+
var tags string
368377
var passwd string
369378
var err error
370379
var entry *Entry
@@ -407,13 +416,16 @@ func editCurrentEntry(idString string) error {
407416
}
408417
// fmt.Printf("Password => %s\n", passwd)
409418

419+
fmt.Printf("\nCurrent Tags: %s\n", entry.Tags)
420+
tags = readInput(reader, "New Tags")
421+
410422
fmt.Printf("\nCurrent Notes: %s\n", entry.Notes)
411423
notes = readInput(reader, "New Notes")
412424

413425
customEntries, flag := addOrUpdateCustomFields(reader, entry)
414426

415427
// Update
416-
err = updateDatabaseEntry(entry, title, userName, url, passwd, notes, customEntries, flag)
428+
err = updateDatabaseEntry(entry, title, userName, url, passwd, tags, notes, customEntries, flag)
417429
if err != nil {
418430
fmt.Printf("Error updating entry - \"%s\"\n", err.Error())
419431
}
@@ -629,6 +641,9 @@ func copyCurrentEntry(idString string) error {
629641

630642
var err error
631643
var entry *Entry
644+
var entryNew *Entry
645+
var exEntries []ExtendedEntry
646+
632647
var id int
633648

634649
if err = checkActiveDatabase(); err != nil {
@@ -643,12 +658,24 @@ func copyCurrentEntry(idString string) error {
643658
return err
644659
}
645660

646-
err, _ = cloneEntry(entry)
661+
err, entryNew = cloneEntry(entry)
647662
if err != nil {
648663
fmt.Printf("Error cloning entry: \"%s\"\n", err.Error())
649664
return err
650665
}
651666

667+
exEntries = getExtendedEntries(entry)
668+
669+
if len(exEntries) > 0 {
670+
fmt.Printf("%d extended entries found\n", len(exEntries))
671+
672+
err = cloneExtendedEntries(entryNew, exEntries)
673+
if err != nil {
674+
fmt.Printf("Error cloning extended entries: \"%s\"\n", err.Error())
675+
return err
676+
}
677+
}
678+
652679
return err
653680
}
654681

@@ -684,11 +711,11 @@ func encryptDatabase(dbPath string, givenPasswd *string) error {
684711
}
685712

686713
if len(passwd) == 0 {
687-
fmt.Printf("Password: ")
714+
fmt.Printf("Encryption Password: ")
688715
err, passwd = readPassword()
689716

690717
if err == nil {
691-
fmt.Printf("\nPassword again: ")
718+
fmt.Printf("\nEncryption Password again: ")
692719
err, passwd2 = readPassword()
693720
if err == nil {
694721
if passwd != passwd2 {
@@ -736,7 +763,7 @@ func decryptDatabase(dbPath string) (error, string) {
736763
return err, ""
737764
}
738765

739-
fmt.Printf("Password: ")
766+
fmt.Printf("Decryption Password: ")
740767
err, passwd = readPassword()
741768

742769
if err != nil {
@@ -757,12 +784,65 @@ func decryptDatabase(dbPath string) (error, string) {
757784
}
758785

759786
if err == nil {
760-
fmt.Println("\nDecryption complete.")
787+
fmt.Println("...decryption complete.")
761788
}
762789

763790
return err, passwd
764791
}
765792

793+
// Migrate an existing database to the new schema
794+
func migrateDatabase(dbPath string) error {
795+
796+
var err error
797+
var flag bool
798+
var passwd string
799+
var db *gorm.DB
800+
801+
if _, err = os.Stat(dbPath); os.IsNotExist(err) {
802+
fmt.Printf("Error - path %s does not exist\n", dbPath)
803+
return err
804+
}
805+
806+
if err, flag = isFileEncrypted(dbPath); flag {
807+
err, passwd = decryptDatabase(dbPath)
808+
}
809+
810+
if err != nil {
811+
return err
812+
}
813+
814+
err, db = openDatabase(dbPath)
815+
816+
if err != nil {
817+
fmt.Printf("Error opening database path - %s: %s\n", dbPath, err.Error())
818+
return err
819+
}
820+
821+
fmt.Println("Migrating tables ...")
822+
err = db.AutoMigrate(&Entry{})
823+
824+
if err != nil {
825+
fmt.Printf("Error migrating table \"entries\" - %s: %s\n", dbPath, err.Error())
826+
return err
827+
}
828+
829+
err = db.AutoMigrate(&ExtendedEntry{})
830+
831+
if err != nil {
832+
fmt.Printf("Error migrating table \"exentries\" - %s: %s\n", dbPath, err.Error())
833+
return err
834+
}
835+
836+
if flag {
837+
// File was encrypted - encrypt it again
838+
encryptDatabase(dbPath, &passwd)
839+
}
840+
841+
fmt.Println("Migration successful.")
842+
843+
return nil
844+
}
845+
766846
// Export data to a varity of file types
767847
func exportToFile(fileName string) error {
768848

crypto.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ func decryptFileAES(encDbPath string, password string) error {
278278
return err
279279
}
280280

281-
err, origFile = rewriteBaseFile(encDbPath, plainText, 0600)
281+
err, origFile = rewriteFile(encDbPath, plainText, 0600)
282282

283283
if err != nil {
284284
fmt.Printf("Error writing decrypted data to %s - \"%s\"\n", origFile, err.Error())
@@ -425,8 +425,8 @@ func decryptFileXChachaPoly(encDbPath string, password string) error {
425425
return err
426426
}
427427

428-
// err = os.WriteFile("test.sqlite3", plainText, 0600)
429-
err, origFile = rewriteBaseFile(encDbPath, plainText, 0600)
428+
// err = os.WriteFile("test.sqlite3", oplainText, 0600)
429+
err, origFile = rewriteFile(encDbPath, plainText, 0600)
430430

431431
if err != nil {
432432
fmt.Printf("Error writing decrypted data to %s - \"%s\"\n", origFile, err.Error())

db.go

+60-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type Entry struct {
2222
Url string `gorm:"column:url"`
2323
Password string `gorm:"column:password"`
2424
Notes string `gorm:"column:notes"`
25+
Tags string `gorm:"column:tags"`
2526
Timestamp time.Time `gorm:"type:timestamp;default:(datetime('now','localtime'))"` // sqlite3
2627
}
2728

@@ -56,6 +57,16 @@ func (e1 *Entry) Copy(e2 *Entry) {
5657
}
5758
}
5859

60+
// Clone an entry
61+
func (e1 *ExtendedEntry) Copy(e2 *ExtendedEntry) {
62+
63+
if e2 != nil {
64+
e1.FieldName = e2.FieldName
65+
e1.FieldValue = e2.FieldValue
66+
e1.EntryID = e2.EntryID
67+
}
68+
}
69+
5970
// Create a new database
6071
func openDatabase(filePath string) (error, *gorm.DB) {
6172

@@ -219,13 +230,15 @@ func replaceCustomEntries(db *gorm.DB, entry *Entry, updatedEntries []CustomEntr
219230
}
220231

221232
// Add a new entry to current database
222-
func addNewDatabaseEntry(title, userName, url, passwd, notes string, customEntries []CustomEntry) error {
233+
func addNewDatabaseEntry(title, userName, url, passwd, tags string,
234+
notes string, customEntries []CustomEntry) error {
223235

224236
var entry Entry
225237
var err error
226238
var db *gorm.DB
227239

228-
entry = Entry{Title: title, User: userName, Url: url, Password: passwd, Notes: notes}
240+
entry = Entry{Title: title, User: userName, Url: url, Password: passwd, Tags: strings.TrimSpace(tags),
241+
Notes: notes}
229242

230243
err, db = openActiveDatabase()
231244
if err == nil && db != nil {
@@ -247,13 +260,20 @@ func addNewDatabaseEntry(title, userName, url, passwd, notes string, customEntri
247260
}
248261

249262
// Update current database entry with new values
250-
func updateDatabaseEntry(entry *Entry, title, userName, url, passwd, notes string, customEntries []CustomEntry, flag bool) error {
263+
func updateDatabaseEntry(entry *Entry, title, userName, url, passwd, tags string,
264+
notes string, customEntries []CustomEntry, flag bool) error {
251265

252266
var updateMap map[string]interface{}
253267

254268
updateMap = make(map[string]interface{})
255269

256-
keyValMap := map[string]string{"title": title, "user": userName, "url": url, "password": passwd, "notes": notes}
270+
keyValMap := map[string]string{
271+
"title": title,
272+
"user": userName,
273+
"url": url,
274+
"password": passwd,
275+
"notes": notes,
276+
"tags": tags}
257277

258278
for key, val := range keyValMap {
259279
if len(val) > 0 {
@@ -416,11 +436,22 @@ func removeDatabaseEntry(entry *Entry) error {
416436

417437
err, db = openActiveDatabase()
418438
if err == nil && db != nil {
439+
var exEntries []ExtendedEntry
440+
419441
res := db.Delete(entry)
420442
if res.Error != nil {
421443
return res.Error
422444
}
423445

446+
// Delete extended entries if any
447+
exEntries = getExtendedEntries(entry)
448+
if len(exEntries) > 0 {
449+
res = db.Delete(exEntries)
450+
if res.Error != nil {
451+
return res.Error
452+
}
453+
}
454+
424455
return nil
425456
}
426457

@@ -450,6 +481,31 @@ func cloneEntry(entry *Entry) (error, *Entry) {
450481
return err, nil
451482
}
452483

484+
// Clone extended entries for an entry and return error code
485+
func cloneExtendedEntries(entry *Entry, exEntries []ExtendedEntry) error {
486+
487+
var err error
488+
var db *gorm.DB
489+
490+
err, db = openActiveDatabase()
491+
if err == nil && db != nil {
492+
for _, exEntry := range exEntries {
493+
var exEntryNew ExtendedEntry
494+
495+
exEntryNew.Copy(&exEntry)
496+
// Update the ID!
497+
exEntryNew.EntryID = entry.ID
498+
499+
result := db.Create(&exEntryNew)
500+
if result.Error != nil {
501+
return result.Error
502+
}
503+
}
504+
}
505+
506+
return err
507+
}
508+
453509
// Return an iterator over all entries using the given order query keys
454510
func iterateEntries(orderKey string, order string) (error, []Entry) {
455511

main.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"strings"
1010
)
1111

12-
const VERSION = 0.3
12+
const VERSION = 0.4
1313
const APP = "varuh"
1414

1515
const AUTHOR_INFO = `
@@ -91,6 +91,7 @@ func performAction(optMap map[string]interface{}) {
9191
"clone": WrapperMaxKryptStringFunc(copyCurrentEntry),
9292
"use-db": setActiveDatabasePath,
9393
"export": exportToFile,
94+
"migrate": migrateDatabase,
9495
}
9596

9697
stringListActionsMap := map[string]actionFunc{
@@ -190,6 +191,7 @@ func initializeCmdLine(parser *argparse.Parser) map[string]interface{} {
190191
{"E", "edit", "Edit entry by <id>", "<id>", ""},
191192
{"l", "list-entry", "List entry by <id>", "<id>", ""},
192193
{"x", "export", "Export all entries to <filename>", "<filename>", ""},
194+
{"m", "migrate", "Migrate a database to latest schema", "<path>", ""},
193195
}
194196

195197
for _, opt := range stringOptions {

0 commit comments

Comments
 (0)