github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/instances/move.go (about) 1 package instances 2 3 import ( 4 "fmt" 5 "net/http" 6 "strconv" 7 8 "github.com/cozy/cozy-stack/model/instance/lifecycle" 9 "github.com/cozy/cozy-stack/model/job" 10 "github.com/cozy/cozy-stack/model/move" 11 "github.com/cozy/cozy-stack/pkg/consts" 12 "github.com/cozy/cozy-stack/pkg/couchdb" 13 "github.com/cozy/cozy-stack/pkg/prefixer" 14 "github.com/labstack/echo/v4" 15 ) 16 17 func exporter(c echo.Context) error { 18 domain := c.Param("domain") 19 adminReq, err := strconv.ParseBool(c.QueryParam("admin-req")) 20 if err != nil { 21 return wrapError(err) 22 } 23 24 inst, err := lifecycle.GetInstance(domain) 25 if err != nil { 26 return wrapError(err) 27 } 28 29 options := move.ExportOptions{ 30 ContextualDomain: domain, 31 AdminReq: adminReq, 32 } 33 msg, err := job.NewMessage(options) 34 if err != nil { 35 return wrapError(err) 36 } 37 38 j, err := job.System().PushJob(inst, &job.JobRequest{ 39 WorkerType: "export", 40 Message: msg, 41 }) 42 if err != nil { 43 return wrapError(err) 44 } 45 46 return c.JSON(http.StatusAccepted, j) 47 } 48 49 func dataExporter(c echo.Context) error { 50 domain := c.Param("domain") 51 exportID := c.Param("export-id") 52 53 inst, err := lifecycle.GetInstance(domain) 54 if err != nil { 55 return wrapError(err) 56 } 57 58 var exportDoc move.ExportDoc 59 if err := couchdb.GetDoc(prefixer.GlobalPrefixer, consts.Exports, exportID, &exportDoc); err != nil { 60 if couchdb.IsNotFoundError(err) || couchdb.IsNoDatabaseError(err) { 61 return wrapError(move.ErrExportNotFound) 62 } 63 return wrapError(err) 64 } 65 if exportDoc.HasExpired() { 66 return wrapError(move.ErrExportExpired) 67 } 68 69 cursor, err := move.ParseCursor(&exportDoc, c.QueryParam("cursor")) 70 if err != nil { 71 return wrapError(err) 72 } 73 74 w := c.Response() 75 w.Header().Set(echo.HeaderContentType, "application/zip") 76 filename := domain + ".zip" 77 if len(exportDoc.PartsCursors) > 0 { 78 filename = fmt.Sprintf("%s - part%03d.zip", domain, cursor.Number) 79 } 80 w.Header().Set(echo.HeaderContentDisposition, fmt.Sprintf(`attachment; filename="%s"`, filename)) 81 w.WriteHeader(http.StatusOK) 82 83 archiver := move.SystemArchiver() 84 return move.ExportCopyData(w, inst, &exportDoc, archiver, cursor) 85 } 86 87 func importer(c echo.Context) error { 88 domain := c.Param("domain") 89 inst, err := lifecycle.GetInstance(domain) 90 if err != nil { 91 return wrapError(err) 92 } 93 94 options := move.ImportOptions{ 95 ManifestURL: c.QueryParam("manifest_url"), 96 } 97 msg, err := job.NewMessage(options) 98 if err != nil { 99 return wrapError(err) 100 } 101 102 _, err = job.System().PushJob(inst, &job.JobRequest{ 103 WorkerType: "import", 104 Message: msg, 105 }) 106 if err != nil { 107 return wrapError(err) 108 } 109 110 return c.NoContent(http.StatusNoContent) 111 }