add backup/restore REST API

This commit is contained in:
Nicola Murino
2019-12-27 23:12:44 +01:00
parent f49c280a7f
commit ae094d3479
26 changed files with 673 additions and 29 deletions

View File

@@ -2,8 +2,10 @@ package httpd_test
import (
"bytes"
"crypto/rand"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
@@ -40,6 +42,8 @@ const (
quotaScanPath = "/api/v1/quota_scan"
versionPath = "/api/v1/version"
providerStatusPath = "/api/v1/providerstatus"
dumpDataPath = "/api/v1/dumpdata"
loadDataPath = "/api/v1/loaddata"
metricsPath = "/metrics"
webBasePath = "/web"
webUsersPath = "/web/users"
@@ -51,16 +55,13 @@ const (
var (
defaultPerms = []string{dataprovider.PermAny}
homeBasePath string
backupsPath string
testServer *httptest.Server
providerDriverName string
)
func TestMain(m *testing.M) {
if runtime.GOOS == "windows" {
homeBasePath = "C:\\"
} else {
homeBasePath = "/tmp"
}
homeBasePath = os.TempDir()
logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
logger.InitLogger(logfilePath, 5, 1, 28, false, zerolog.DebugLevel)
config.LoadConfig(configDir, "")
@@ -77,6 +78,11 @@ func TestMain(m *testing.M) {
httpdConf.BindPort = 8081
httpd.SetBaseURL("http://127.0.0.1:8081")
httpdConf.BackupsPath = "test_backups"
currentPath, _ := os.Getwd()
backupsPath = filepath.Join(currentPath, "..", httpdConf.BackupsPath)
logger.DebugToConsole("aaa: %v", backupsPath)
os.MkdirAll(backupsPath, 0777)
sftpd.SetDataProvider(dataProvider)
httpd.SetDataProvider(dataProvider)
@@ -96,6 +102,7 @@ func TestMain(m *testing.M) {
exitCode := m.Run()
os.Remove(logfilePath)
os.RemoveAll(backupsPath)
os.Exit(exitCode)
}
@@ -541,6 +548,22 @@ func TestProviderErrors(t *testing.T) {
if err != nil {
t.Errorf("get provider status with provider closed must fail: %v", err)
}
_, _, err = httpd.Dumpdata("backup.json", http.StatusInternalServerError)
if err != nil {
t.Errorf("get provider status with provider closed must fail: %v", err)
}
user := getTestUser()
user.ID = 1
backupData := httpd.BackupData{}
backupData.Users = append(backupData.Users, user)
backupContent, _ := json.Marshal(backupData)
backupFilePath := filepath.Join(backupsPath, "backup.json")
ioutil.WriteFile(backupFilePath, backupContent, 0666)
_, _, err = httpd.Loaddata(backupFilePath, "", http.StatusInternalServerError)
if err != nil {
t.Errorf("get provider status with provider closed must fail: %v", err)
}
os.Remove(backupFilePath)
config.LoadConfig(configDir, "")
providerConf := config.GetProviderConf()
err = dataprovider.Initialize(providerConf, configDir)
@@ -551,6 +574,100 @@ func TestProviderErrors(t *testing.T) {
sftpd.SetDataProvider(dataprovider.GetProvider())
}
func TestDumpdata(t *testing.T) {
_, _, err := httpd.Dumpdata("", http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
_, _, err = httpd.Dumpdata(filepath.Join(backupsPath, "backup.json"), http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
_, _, err = httpd.Dumpdata("../backup.json", http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
_, _, err = httpd.Dumpdata("backup.json", http.StatusOK)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
os.Remove(filepath.Join(backupsPath, "backup.json"))
if runtime.GOOS != "windows" {
os.Chmod(backupsPath, 0001)
_, _, err = httpd.Dumpdata("bck.json", http.StatusInternalServerError)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
os.Chmod(backupsPath, 0755)
}
}
func TestLoaddata(t *testing.T) {
user := getTestUser()
user.ID = 1
user.Username = "test_user_restore"
backupData := httpd.BackupData{}
backupData.Users = append(backupData.Users, user)
backupContent, _ := json.Marshal(backupData)
backupFilePath := filepath.Join(backupsPath, "backup.json")
ioutil.WriteFile(backupFilePath, backupContent, 0666)
_, _, err := httpd.Loaddata(backupFilePath, "a", http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
_, _, err = httpd.Loaddata("backup.json", "1", http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
_, _, err = httpd.Loaddata(backupFilePath+"a", "1", http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if runtime.GOOS != "windows" {
os.Chmod(backupFilePath, 0111)
_, _, err = httpd.Loaddata(backupFilePath, "1", http.StatusInternalServerError)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
os.Chmod(backupFilePath, 0644)
}
// add user from backup
_, _, err = httpd.Loaddata(backupFilePath, "1", http.StatusOK)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
// update user from backup
_, _, err = httpd.Loaddata(backupFilePath, "2", http.StatusOK)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
users, _, err := httpd.GetUsers(1, 0, user.Username, http.StatusOK)
if err != nil {
t.Errorf("unable to get users: %v", err)
}
if len(users) != 1 {
t.Error("Unable to get restored user")
}
user = users[0]
_, err = httpd.RemoveUser(user, http.StatusOK)
if err != nil {
t.Errorf("unable to remove user: %v", err)
}
os.Remove(backupFilePath)
createTestFile(backupFilePath, 10485761)
_, _, err = httpd.Loaddata(backupFilePath, "1", http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
os.Remove(backupFilePath)
createTestFile(backupFilePath, 65535)
_, _, err = httpd.Loaddata(backupFilePath, "1", http.StatusBadRequest)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
os.Remove(backupFilePath)
}
// test using mock http server
func TestBasicUserHandlingMock(t *testing.T) {
@@ -1293,3 +1410,16 @@ func checkResponseCode(t *testing.T, expected, actual int) {
t.Errorf("Expected response code %d. Got %d", expected, actual)
}
}
func createTestFile(path string, size int64) error {
baseDir := filepath.Dir(path)
if _, err := os.Stat(baseDir); os.IsNotExist(err) {
os.MkdirAll(baseDir, 0777)
}
content := make([]byte, size)
_, err := rand.Read(content)
if err != nil {
return err
}
return ioutil.WriteFile(path, content, 0666)
}