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  }