diff --git a/kernel/api/router.go b/kernel/api/router.go index 8c73771f6..67113f88c 100644 --- a/kernel/api/router.go +++ b/kernel/api/router.go @@ -218,6 +218,10 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/sync/performBootSync", model.CheckAuth, model.CheckReadonly, performBootSync) ginServer.Handle("POST", "/api/sync/getBootSync", model.CheckAuth, getBootSync) ginServer.Handle("POST", "/api/sync/getSyncInfo", model.CheckAuth, getSyncInfo) + ginServer.Handle("POST", "/api/sync/exportSyncProviderS3", model.CheckAuth, exportSyncProviderS3) + ginServer.Handle("POST", "/api/sync/importSyncProviderS3", model.CheckAuth, importSyncProviderS3) + ginServer.Handle("POST", "/api/sync/exportSyncProviderWebDAV", model.CheckAuth, exportSyncProviderWebDAV) + ginServer.Handle("POST", "/api/sync/importSyncProviderWebDAV", model.CheckAuth, importSyncProviderWebDAV) ginServer.Handle("POST", "/api/inbox/getShorthands", model.CheckAuth, getShorthands) ginServer.Handle("POST", "/api/inbox/getShorthand", model.CheckAuth, getShorthand) diff --git a/kernel/api/sync.go b/kernel/api/sync.go index f006d5e16..46b70acf8 100644 --- a/kernel/api/sync.go +++ b/kernel/api/sync.go @@ -17,7 +17,13 @@ package api import ( + "encoding/hex" + "github.com/siyuan-note/logging" + "io" "net/http" + "os" + "path/filepath" + "time" "github.com/88250/gulu" "github.com/gin-gonic/gin" @@ -26,6 +32,202 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) +func importSyncProviderWebDAV(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(200, ret) + + form, err := c.MultipartForm() + if nil != err { + logging.LogErrorf("read upload file failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + files := form.File["file[]"] + if 1 != len(files) { + ret.Code = -1 + ret.Msg = "invalid upload file" + return + } + + f := files[0] + fh, err := f.Open() + if nil != err { + logging.LogErrorf("read upload file failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + data, err := io.ReadAll(fh) + fh.Close() + if nil != err { + logging.LogErrorf("read upload file failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + data = util.AESDecrypt(string(data)) + data, _ = hex.DecodeString(string(data)) + webdav := &conf.WebDAV{} + if err = gulu.JSON.UnmarshalJSON(data, webdav); nil != err { + logging.LogErrorf("import S3 provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + err = model.SetSyncProviderWebDAV(webdav) + if nil != err { + logging.LogErrorf("import S3 provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } +} + +func exportSyncProviderWebDAV(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(http.StatusOK, ret) + + name := "siyuan-webdav-" + time.Now().Format("20060102150405") + ".json" + tmpDir := filepath.Join(util.TempDir, "export") + if err := os.MkdirAll(tmpDir, 0755); nil != err { + logging.LogErrorf("export WebDAV provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + webdav := model.Conf.Sync.WebDAV + if nil == webdav { + webdav = &conf.WebDAV{} + } + + data, err := gulu.JSON.MarshalJSON(model.Conf.Sync.WebDAV) + if nil != err { + logging.LogErrorf("export WebDAV provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + dataStr := util.AESEncrypt(string(data)) + tmp := filepath.Join(tmpDir, name) + if err = os.WriteFile(tmp, []byte(dataStr), 0644); nil != err { + logging.LogErrorf("export WebDAV provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + zipPath := "/export/" + name + ret.Data = map[string]interface{}{ + "name": name, + "zip": zipPath, + } +} + +func importSyncProviderS3(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(200, ret) + + form, err := c.MultipartForm() + if nil != err { + logging.LogErrorf("read upload file failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + files := form.File["file[]"] + if 1 != len(files) { + ret.Code = -1 + ret.Msg = "invalid upload file" + return + } + + f := files[0] + fh, err := f.Open() + if nil != err { + logging.LogErrorf("read upload file failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + data, err := io.ReadAll(fh) + fh.Close() + if nil != err { + logging.LogErrorf("read upload file failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + data = util.AESDecrypt(string(data)) + data, _ = hex.DecodeString(string(data)) + s3 := &conf.S3{} + if err = gulu.JSON.UnmarshalJSON(data, s3); nil != err { + logging.LogErrorf("import S3 provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + err = model.SetSyncProviderS3(s3) + if nil != err { + logging.LogErrorf("import S3 provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } +} + +func exportSyncProviderS3(c *gin.Context) { + ret := gulu.Ret.NewResult() + defer c.JSON(http.StatusOK, ret) + + name := "siyuan-s3-" + time.Now().Format("20060102150405") + ".json" + tmpDir := filepath.Join(util.TempDir, "export") + if err := os.MkdirAll(tmpDir, 0755); nil != err { + logging.LogErrorf("export S3 provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + s3 := model.Conf.Sync.S3 + if nil == s3 { + s3 = &conf.S3{} + } + + data, err := gulu.JSON.MarshalJSON(model.Conf.Sync.S3) + if nil != err { + logging.LogErrorf("export S3 provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + dataStr := util.AESEncrypt(string(data)) + tmp := filepath.Join(tmpDir, name) + if err = os.WriteFile(tmp, []byte(dataStr), 0644); nil != err { + logging.LogErrorf("export S3 provider failed: %s", err) + ret.Code = -1 + ret.Msg = err.Error() + return + } + + zipPath := "/export/" + name + ret.Data = map[string]interface{}{ + "name": name, + "zip": zipPath, + } +} + func getSyncInfo(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret)