Skip to content

Commit

Permalink
add delete secret to sync
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Ostrovskiy committed Nov 8, 2023
1 parent b0dee60 commit bef07ce
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 40 deletions.
30 changes: 30 additions & 0 deletions internal/client/infrastrucrure/filemanager/filemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type FileStorage interface {
ReadEncryptedByName(name string) (chan []byte, error)
UpdateDataByName(name string, data Data) error
UpdateInfoByName(name string, info models.DataInfo) error
DeleteByIDs(ids []string) error
DeleteByName(name string) error
}

Expand Down Expand Up @@ -213,6 +214,35 @@ func (fm *FileManager) DeleteByName(name string) error {
return fm.saveMetaData()
}

func (fm *FileManager) DeleteByIDs(ids []string) error {
var delErr error
for _, id := range ids {
if _, err := os.Stat(filepath.Join(fm.storageDir, id)); !os.IsNotExist(err) {
err := os.Remove(filepath.Join(fm.storageDir, id))
if err != nil {
delErr = fmt.Errorf("%w, %s: %w", delErr, id, err)
}
}

finder:
for name, info := range fm.Meta.Data {
if info.DataID == id {
delete(fm.Meta.Data, name)

break finder
}
}
}
if err := fm.saveMetaData(); err != nil {
delErr = fmt.Errorf("%w, save meta err: %w", delErr, err)
}
if delErr != nil {
return fmt.Errorf("%w", delErr)
}

return nil
}

func (fm *FileManager) saveMetaData() error {
data, err := json.Marshal(fm.Meta)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ func TestFileManager_DeleteByName(t *testing.T) {
{
name: "ok",
storage: func() filemanager.FileStorage {
meta := models.UserMeta{Data: make(models.MetaData)}
meta := models.UserMeta{Data: make(models.MetaData), DeletedData: make(models.Deleted)}
testInfo := info
testInfo.DataID = filename
meta.Data["testData"] = testInfo
Expand All @@ -509,7 +509,7 @@ func TestFileManager_DeleteByName(t *testing.T) {
{
name: "failed if secret not exist",
storage: func() filemanager.FileStorage {
meta := models.UserMeta{Data: make(models.MetaData)}
meta := models.UserMeta{Data: make(models.MetaData), DeletedData: make(models.Deleted)}
fs, err := filemanager.NewFileManager(storageDir, userDir, userDir, meta, testKey)
if err != nil {
t.Fatalf("Failed to create FileManager: %v", err)
Expand Down
16 changes: 15 additions & 1 deletion internal/client/infrastrucrure/filemanager/mocks/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions internal/client/infrastrucrure/filemanager/userauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ func Test_userAuth_GetUser(t *testing.T) {
t.Fatalf("Failed prepare user: %v", err)
}
},
user: &models.User{Username: Login, Password: Password},
want: models.UserMeta{Username: Login, IsSyncStorage: true, Data: make(models.MetaData)},
user: &models.User{Username: Login, Password: Password},
want: models.UserMeta{Username: Login, IsSyncStorage: true,
Data: make(models.MetaData), DeletedData: make(models.Deleted)},
wantErr: false,
},
{
Expand All @@ -64,7 +65,6 @@ func Test_userAuth_GetUser(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.prepareFunc()

got, err := tt.auth.GetUser(tt.user)
if (err != nil) != tt.wantErr {
t.Errorf("GetUser() error = %v, wantErr %v", err, tt.wantErr)
Expand Down Expand Up @@ -93,10 +93,11 @@ func Test_userAuth_CreateUser(t *testing.T) {
wantErr bool
}{
{
name: "ok",
auth: auth,
user: &models.User{Username: Login, Password: Password},
want: models.UserMeta{Username: Login, IsSyncStorage: true, Data: make(models.MetaData)},
name: "ok",
auth: auth,
user: &models.User{Username: Login, Password: Password},
want: models.UserMeta{Username: Login, IsSyncStorage: true,
Data: make(models.MetaData), DeletedData: make(models.Deleted)},
IsSyncStorage: true,
wantErr: false,
},
Expand Down
10 changes: 5 additions & 5 deletions internal/client/infrastrucrure/ui/mocks/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/client/usecase/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import (
"os"
"testing"

"github.com/golang/mock/gomock"
"github.com/kripsy/GophKeeper/internal/client/infrastrucrure/filemanager"
mock_filemanager "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/filemanager/mocks"
"github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui"
mock_ui "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui/mocks"
"github.com/kripsy/GophKeeper/internal/client/permissions"
"github.com/kripsy/GophKeeper/internal/models"
"github.com/rs/zerolog"
"go.uber.org/mock/gomock"
)

func TestClientUsecase_createSecret(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion internal/client/usecase/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
"os"
"testing"

"github.com/golang/mock/gomock"
mock_filemanager "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/filemanager/mocks"
"github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui"
mock_ui "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui/mocks"
"github.com/kripsy/GophKeeper/internal/models"
"github.com/rs/zerolog"
"go.uber.org/mock/gomock"
)

func TestClientUsecase_deleteSecret(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion internal/client/usecase/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"os"
"testing"

"github.com/golang/mock/gomock"
"github.com/kripsy/GophKeeper/internal/client/infrastrucrure/filemanager"
mock_filemanager "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/filemanager/mocks"
"github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui"
mock_ui "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui/mocks"
"github.com/kripsy/GophKeeper/internal/models"
"github.com/rs/zerolog"
"go.uber.org/mock/gomock"
)

func TestClientUsecase_getSecrets(t *testing.T) {
Expand Down
34 changes: 24 additions & 10 deletions internal/client/usecase/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ func (c *ClientUsecase) synchronizeWithServer(ctx context.Context, syncKey strin
return nil
}

defer c.syncDeletedSecret(serverMeta.DeletedData)

toDownload, toUpload := findDifferences(c.userData.Meta, *serverMeta)
if len(toUpload) == 0 && len(toDownload) == 0 {
return nil
Expand Down Expand Up @@ -101,14 +103,21 @@ func (c *ClientUsecase) uploadMeta(ctx context.Context, syncKey string) error {
}

func (c *ClientUsecase) syncDeletedSecret(deleted models.Deleted) {
// var needDeleted []string
var needDeleted []string
for dataID := range deleted {
if _, ok := c.userData.Meta.DeletedData[dataID]; !ok {
c.userData.Meta.DeletedData[dataID] = struct{}{}
// needDeleted = append(needDeleted, dataID)
needDeleted = append(needDeleted, dataID)
}
}

if len(needDeleted) == 0 {
return
}

if err := c.fileManager.DeleteByIDs(needDeleted); err != nil {
c.log.Err(err).Msg("failed sync deleted secret")
}
}

func (c *ClientUsecase) uploadSecrets(ctx context.Context, syncKey string, toUpload models.MetaData) error {
Expand Down Expand Up @@ -255,23 +264,28 @@ func findDifferences(local, server models.UserMeta) (needDownload, needUpload mo
serverData[data.DataID] = data
}

// проверяем данные сервера, если данные не обнаружены или устарели добавляем в список на скачивание
// проверяем данные сервера, пропускаем удаленные локально.
// если данные не обнаружены или устарели добавляем в список на скачивание
for dataID, sData := range serverData {
if local.DeletedData.IsDeleted(dataID) {
continue
}
lData, found := localData[dataID]
if !found || lData.UpdatedAt.Before(sData.UpdatedAt) {
if _, deleted := local.DeletedData[dataID]; !deleted {
needDownload[dataID] = sData
}
needDownload[dataID] = sData
}
}

// проверяем локальные данные, если данные не обнаружены или устарели добавляем в список на выгрузку
// проверяем локальные данные, пропускаем удаленные на сервере.
// если данные не обнаружены или устарели добавляем в список на выгрузку
for dataID, lData := range localData {
if server.DeletedData.IsDeleted(dataID) {
continue
}

sData, found := serverData[dataID]
if !found || sData.UpdatedAt.Before(lData.UpdatedAt) {
if _, deleted := server.DeletedData[dataID]; !deleted {
needUpload[dataID] = lData
}
needUpload[dataID] = lData
}
}

Expand Down
100 changes: 100 additions & 0 deletions internal/client/usecase/sync_test.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,102 @@
//nolint:testpackage
package usecase

import (
"reflect"
"testing"
"time"

"github.com/kripsy/GophKeeper/internal/models"
)

func Test_findDifferences(t *testing.T) {
testTime := time.Now()
tests := []struct {
name string
local models.UserMeta
server models.UserMeta
wantNeedDownload models.MetaData
wantNeedUpload models.MetaData
}{
{
name: "download & upload",
local: models.UserMeta{Data: models.MetaData{
"data1": models.DataInfo{DataID: "data1", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime}}},
server: models.UserMeta{Data: models.MetaData{
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data4": models.DataInfo{DataID: "data4", UpdatedAt: testTime}}},
wantNeedDownload: models.MetaData{
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data4": models.DataInfo{DataID: "data4", UpdatedAt: testTime},
},
wantNeedUpload: models.MetaData{
"data1": models.DataInfo{DataID: "data1", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime},
},
},
{
name: "upload",
local: models.UserMeta{Data: models.MetaData{
"data1": models.DataInfo{DataID: "data1", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime}}},
server: models.UserMeta{Data: models.MetaData{}},
wantNeedDownload: models.MetaData{},
wantNeedUpload: models.MetaData{
"data1": models.DataInfo{DataID: "data1", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime}},
},
{
name: "download",
local: models.UserMeta{Data: models.MetaData{}},
server: models.UserMeta{Data: models.MetaData{
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data4": models.DataInfo{DataID: "data4", UpdatedAt: testTime}}},
wantNeedDownload: models.MetaData{
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data4": models.DataInfo{DataID: "data4", UpdatedAt: testTime}},
wantNeedUpload: models.MetaData{},
},
{
name: "upload with deleted data",
local: models.UserMeta{Data: models.MetaData{
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-2 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime}},
},
server: models.UserMeta{DeletedData: models.Deleted{"data2": struct{}{}}},
wantNeedDownload: models.MetaData{},
wantNeedUpload: models.MetaData{
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime}},
},
{
name: "download with deleted",
local: models.UserMeta{Data: models.MetaData{},
DeletedData: models.Deleted{"data2": struct{}{}}},
server: models.UserMeta{Data: models.MetaData{
"data2": models.DataInfo{DataID: "data2", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data4": models.DataInfo{DataID: "data4", UpdatedAt: testTime}}},
wantNeedDownload: models.MetaData{
"data3": models.DataInfo{DataID: "data3", UpdatedAt: testTime.Add(-1 * time.Hour)},
"data4": models.DataInfo{DataID: "data4", UpdatedAt: testTime}},
wantNeedUpload: models.MetaData{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotNeedDownload, gotNeedUpload := findDifferences(tt.local, tt.server)
if !reflect.DeepEqual(gotNeedDownload, tt.wantNeedDownload) {
t.Errorf("findDifferences() gotNeedDownload = %v, want %v", gotNeedDownload, tt.wantNeedDownload)
}
if !reflect.DeepEqual(gotNeedUpload, tt.wantNeedUpload) {
t.Errorf("findDifferences() gotNeedUpload = %v, want %v", gotNeedUpload, tt.wantNeedUpload)
}
})
}
}
2 changes: 1 addition & 1 deletion internal/client/usecase/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import (
"os"
"testing"

"github.com/golang/mock/gomock"
"github.com/kripsy/GophKeeper/internal/client/infrastrucrure/filemanager"
mock_filemanager "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/filemanager/mocks"
"github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui"
mock_ui "github.com/kripsy/GophKeeper/internal/client/infrastrucrure/ui/mocks"
"github.com/kripsy/GophKeeper/internal/client/permissions"
"github.com/kripsy/GophKeeper/internal/models"
"github.com/rs/zerolog"
"go.uber.org/mock/gomock"
)

func TestClientUsecase_updateSecret(t *testing.T) {
Expand Down
Loading

0 comments on commit bef07ce

Please sign in to comment.