From dc7d699e614a44eed795fba07b56fa422237dab3 Mon Sep 17 00:00:00 2001 From: Marc Ole Bulling Date: Fri, 6 Jun 2025 15:17:35 +0200 Subject: [PATCH] Added tests --- internal/storage/FileServing.go | 1 + internal/storage/FileServing_test.go | 88 +++++++++++ .../testconfiguration/TestConfiguration.go | 23 +-- internal/webserver/api/Api_test.go | 140 ++++++++++++++++++ 4 files changed, 242 insertions(+), 10 deletions(-) diff --git a/internal/storage/FileServing.go b/internal/storage/FileServing.go index d0805a1..47cb101 100644 --- a/internal/storage/FileServing.go +++ b/internal/storage/FileServing.go @@ -364,6 +364,7 @@ const ( ) // ReplaceFile replaces the file content of fileId with the content of newFileContentId +// If delete is true, the NEW file will be deleted. // Replacing e2e encrypted files is NOT possible func ReplaceFile(fileId, newFileContentId string, delete bool) (models.File, error) { file, ok := GetFile(fileId) diff --git a/internal/storage/FileServing_test.go b/internal/storage/FileServing_test.go index 9eb3d2e..9f659d8 100644 --- a/internal/storage/FileServing_test.go +++ b/internal/storage/FileServing_test.go @@ -788,3 +788,91 @@ func TestDeleteAllEncrypted(t *testing.T) { test.IsEqualBool(t, ok, true) test.IsEqualBool(t, data.UnlimitedTime, true) } + +func TestReplaceFile(t *testing.T) { + originalFile := models.File{ + Id: "originalfiletest", + Name: "old.txt", + Size: "1KB", + SHA1: "replacetest1", + ContentType: "text/plain", + UnlimitedDownloads: true, + UnlimitedTime: true, + AwsBucket: "", + SizeBytes: 1024, + Encryption: models.EncryptionInfo{ + IsEncrypted: false, + IsEndToEndEncrypted: false, + DecryptionKey: nil, + Nonce: nil, + }, + } + + newFile := models.File{ + Id: "newfiletest", + Name: "new.txt", + Size: "2KB", + SHA1: "replacetest2", + ContentType: "text/plain2", + UnlimitedDownloads: true, + UnlimitedTime: true, + AwsBucket: "", + SizeBytes: 2048, + Encryption: models.EncryptionInfo{ + IsEncrypted: true, + IsEndToEndEncrypted: false, + DecryptionKey: []byte("key"), + Nonce: []byte("nonce"), + }, + } + + e2eFile := models.File{ + Id: "e2eFile", + Name: "e2eFile", + Size: "1KB", + UnlimitedDownloads: true, + UnlimitedTime: true, + SHA1: "replacetest3", + Encryption: models.EncryptionInfo{ + IsEncrypted: true, + IsEndToEndEncrypted: true, + }, + } + database.SaveMetaData(originalFile) + _, ok := database.GetMetaDataById(originalFile.Id) + test.IsEqualBool(t, ok, true) + _, ok = GetFile(originalFile.Id) + test.IsEqualBool(t, ok, true) + database.SaveMetaData(newFile) + _, ok = database.GetMetaDataById(newFile.Id) + test.IsEqualBool(t, ok, true) + database.SaveMetaData(e2eFile) + _, ok = database.GetMetaDataById(e2eFile.Id) + test.IsEqualBool(t, ok, true) + _, err := ReplaceFile("invalidfile", originalFile.Id, false) + test.IsNotNil(t, err) + _, err = ReplaceFile(originalFile.Id, "invalidfile", false) + test.IsNotNil(t, err) + _, err = ReplaceFile(originalFile.Id, e2eFile.Id, false) + test.IsNotNil(t, err) + + _, err = ReplaceFile(originalFile.Id, newFile.Id, false) + test.IsNil(t, err) + file, ok := GetFile(originalFile.Id) + test.IsEqualBool(t, ok, true) + test.IsEqualString(t, file.Name, newFile.Name) + test.IsEqualString(t, file.SHA1, newFile.SHA1) + test.IsEqualString(t, file.ContentType, newFile.ContentType) + test.IsEqualString(t, file.AwsBucket, newFile.AwsBucket) + test.IsEqualString(t, file.Size, newFile.Size) + test.IsEqualInt64(t, file.SizeBytes, newFile.SizeBytes) + test.IsEqual(t, file.Encryption, newFile.Encryption) + _, ok = GetFile(newFile.Id) + test.IsEqualBool(t, ok, true) + + _, err = ReplaceFile(originalFile.Id, newFile.Id, true) + _, ok = GetFile(originalFile.Id) + test.IsEqualBool(t, ok, true) + _, ok = GetFile(newFile.Id) + test.IsEqualBool(t, ok, false) +} diff --git a/internal/test/testconfiguration/TestConfiguration.go b/internal/test/testconfiguration/TestConfiguration.go index 31c8380..09d1550 100644 --- a/internal/test/testconfiguration/TestConfiguration.go +++ b/internal/test/testconfiguration/TestConfiguration.go @@ -64,16 +64,19 @@ func Create(initFiles bool) { database.Close() if initFiles { - os.MkdirAll(dataDir, 0777) - os.WriteFile(dataDir+"/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0", []byte("123"), 0777) - os.WriteFile(dataDir+"/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd1", []byte("123"), 0777) - os.WriteFile(dataDir+"/c4f9375f9834b4e7f0a528cc65c055702bf5f24a", []byte("456"), 0777) - os.WriteFile(dataDir+"/e017693e4a04a59d0b0f400fe98177fe7ee13cf7", []byte("789"), 0777) - os.WriteFile(dataDir+"/2341354656543213246465465465432456898794", []byte("abc"), 0777) - os.WriteFile(dataDir+"/03cfd743661f07975fa2f1220c5194cbaff48451", []byte("def"), 0777) - os.WriteFile(dataDir+"/pendingdeletion", []byte("ghi"), 0777) - os.WriteFile(dataDir+"/unlimitedtest", []byte("def"), 0777) - os.WriteFile(baseDir+"/fileupload.jpg", []byte("abc"), 0777) + _ = os.MkdirAll(dataDir, 0777) + _ = os.WriteFile(dataDir+"/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0", []byte("123"), 0777) + _ = os.WriteFile(dataDir+"/a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd1", []byte("123"), 0777) + _ = os.WriteFile(dataDir+"/c4f9375f9834b4e7f0a528cc65c055702bf5f24a", []byte("456"), 0777) + _ = os.WriteFile(dataDir+"/e017693e4a04a59d0b0f400fe98177fe7ee13cf7", []byte("789"), 0777) + _ = os.WriteFile(dataDir+"/2341354656543213246465465465432456898794", []byte("abc"), 0777) + _ = os.WriteFile(dataDir+"/03cfd743661f07975fa2f1220c5194cbaff48451", []byte("def"), 0777) + _ = os.WriteFile(dataDir+"/replacetest1", []byte("abc"), 0777) + _ = os.WriteFile(dataDir+"/replacetest2", []byte("abc"), 0777) + _ = os.WriteFile(dataDir+"/replacetest3", []byte("abc"), 0777) + _ = os.WriteFile(dataDir+"/pendingdeletion", []byte("ghi"), 0777) + _ = os.WriteFile(dataDir+"/unlimitedtest", []byte("def"), 0777) + _ = os.WriteFile(baseDir+"/fileupload.jpg", []byte("abc"), 0777) } } diff --git a/internal/webserver/api/Api_test.go b/internal/webserver/api/Api_test.go index 2754c20..dd96c53 100644 --- a/internal/webserver/api/Api_test.go +++ b/internal/webserver/api/Api_test.go @@ -1613,3 +1613,143 @@ func TestMinorFunctions(t *testing.T) { outputFileJson(nil, models.File{}) sendError(nil, 0, "none") } + +func testReplaceFileCall(t *testing.T, apiKey string, fileTarget, fileOrigin string, deleteFile bool, resultCode int, expectedResponse string) { + t.Helper() + const apiUrl = "/files/replace" + const headerFileIdTarget = "id" + const headerFileIdOrigin = "idNewContent" + const headerDeleteFile = "deleteNewFile" + headers := []test.Header{{}} + if fileTarget != "" { + headers = append(headers, test.Header{Name: headerFileIdTarget, Value: fileTarget}) + } + if fileOrigin != "" { + headers = append(headers, test.Header{Name: headerFileIdOrigin, Value: fileOrigin}) + } + if deleteFile { + headers = append(headers, test.Header{Name: headerDeleteFile, Value: "true"}) + } + w, r := getRecorder(apiUrl, apiKey, headers) + Process(w, r) + test.IsEqualInt(t, w.Code, resultCode) + if expectedResponse != "" { + test.ResponseBodyContains(t, w, expectedResponse) + } + + defer test.ExpectPanic(t) + apiRestoreFile(w, ¶mAuthCreate{}, models.User{Id: 7}) +} + +func TestFileReplace(t *testing.T) { + originalFile := models.File{ + Id: "originalfiletest", + Name: "old.txt", + Size: "1KB", + SHA1: "replacetest1", + ContentType: "text/plain", + UnlimitedDownloads: true, + UnlimitedTime: true, + AwsBucket: "", + SizeBytes: 1024, + UserId: idUser, + Encryption: models.EncryptionInfo{ + IsEncrypted: false, + IsEndToEndEncrypted: false, + DecryptionKey: nil, + Nonce: nil, + }, + } + + newFile := models.File{ + Id: "newfiletest", + Name: "new.txt", + Size: "2KB", + SHA1: "replacetest2", + ContentType: "text/plain2", + UnlimitedDownloads: true, + UnlimitedTime: true, + UserId: idUser, + AwsBucket: "", + SizeBytes: 2048, + Encryption: models.EncryptionInfo{ + IsEncrypted: true, + IsEndToEndEncrypted: false, + DecryptionKey: []byte("key"), + Nonce: []byte("nonce"), + }, + } + + e2eFile := models.File{ + Id: "e2eFile", + Name: "e2eFile", + Size: "1KB", + UnlimitedDownloads: true, + UserId: idUser, + UnlimitedTime: true, + SHA1: "replacetest3", + Encryption: models.EncryptionInfo{ + IsEncrypted: true, + IsEndToEndEncrypted: true, + }, + } + adminFile := models.File{ + Id: "adminfile", + Name: "old.txt", + Size: "1KB", + SHA1: "replacetest1", + ContentType: "text/plain", + UnlimitedDownloads: true, + UnlimitedTime: true, + AwsBucket: "", + SizeBytes: 1024, + UserId: idAdmin, + Encryption: models.EncryptionInfo{ + IsEncrypted: false, + IsEndToEndEncrypted: false, + DecryptionKey: nil, + Nonce: nil, + }, + } + + database.SaveMetaData(originalFile) + _, ok := database.GetMetaDataById(originalFile.Id) + test.IsEqualBool(t, ok, true) + database.SaveMetaData(newFile) + _, ok = database.GetMetaDataById(newFile.Id) + test.IsEqualBool(t, ok, true) + database.SaveMetaData(e2eFile) + _, ok = database.GetMetaDataById(e2eFile.Id) + test.IsEqualBool(t, ok, true) + database.SaveMetaData(adminFile) + _, ok = database.GetMetaDataById(adminFile.Id) + test.IsEqualBool(t, ok, true) + + apiKey := testAuthorisation(t, "/files/replace", models.ApiPermReplace) + testReplaceFileCall(t, apiKey.Id, "", "invalid", false, 400, `{"Result":"error","ErrorMessage":"header id is required"}`) + testReplaceFileCall(t, apiKey.Id, "invalid", "", false, 400, `{"Result":"error","ErrorMessage":"header idNewContent is required"}`) + testReplaceFileCall(t, apiKey.Id, "invalid", originalFile.Id, false, 404, `{"Result":"error","ErrorMessage":"Invalid id provided."}`) + testReplaceFileCall(t, apiKey.Id, originalFile.Id, "invalid", false, 404, `{"Result":"error","ErrorMessage":"Invalid id provided."}`) + testReplaceFileCall(t, apiKey.Id, originalFile.Id, adminFile.Id, false, 401, `{"Result":"error","ErrorMessage":"No permission to duplicate this file"}`) + testReplaceFileCall(t, apiKey.Id, adminFile.Id, originalFile.Id, false, 401, `{"Result":"error","ErrorMessage":"No permission to replace this file"}`) + testReplaceFileCall(t, apiKey.Id, e2eFile.Id, originalFile.Id, false, 400, `{"Result":"error","ErrorMessage":"End-to-End encrypted files cannot be replaced"}`) + testReplaceFileCall(t, apiKey.Id, originalFile.Id, newFile.Id, false, 200, "") + + file, ok := database.GetMetaDataById(originalFile.Id) + test.IsEqualBool(t, ok, true) + test.IsEqualString(t, file.Name, newFile.Name) + test.IsEqualString(t, file.SHA1, newFile.SHA1) + test.IsEqualString(t, file.ContentType, newFile.ContentType) + test.IsEqualString(t, file.AwsBucket, newFile.AwsBucket) + test.IsEqualString(t, file.Size, newFile.Size) + test.IsEqualInt64(t, file.SizeBytes, newFile.SizeBytes) + test.IsEqual(t, file.Encryption, newFile.Encryption) + _, ok = storage.GetFile(newFile.Id) + test.IsEqualBool(t, ok, true) + testReplaceFileCall(t, apiKey.Id, originalFile.Id, newFile.Id, true, 200, "") + + _, ok = storage.GetFile(originalFile.Id) + test.IsEqualBool(t, ok, true) + _, ok = storage.GetFile(newFile.Id) + test.IsEqualBool(t, ok, false) +}