github.com/cozy/cozy-stack@v0.0.0-20240327093429-939e4a21320e/web/remote/remote.go (about)

     1  package remote
     2  
     3  import (
     4  	"net/http"
     5  	"strings"
     6  
     7  	"github.com/cozy/cozy-stack/model/permission"
     8  	"github.com/cozy/cozy-stack/model/remote"
     9  	"github.com/cozy/cozy-stack/pkg/consts"
    10  	"github.com/cozy/cozy-stack/pkg/jsonapi"
    11  	"github.com/cozy/cozy-stack/web/middlewares"
    12  	"github.com/labstack/echo/v4"
    13  )
    14  
    15  func allDoctypes(c echo.Context) error {
    16  	if err := middlewares.AllowWholeType(c, permission.GET, consts.Doctypes); err != nil {
    17  		return wrapRemoteErr(err)
    18  	}
    19  
    20  	inst := middlewares.GetInstance(c)
    21  	doctypes, err := remote.ListDoctypes(inst)
    22  	if err != nil {
    23  		return wrapRemoteErr(err)
    24  	}
    25  	return c.JSON(http.StatusOK, doctypes)
    26  }
    27  
    28  func remoteGet(c echo.Context) error {
    29  	doctype := c.Param("doctype")
    30  	slug, err := allowWholeType(c, permission.GET, doctype)
    31  	if err != nil {
    32  		return wrapRemoteErr(err)
    33  	}
    34  	instance := middlewares.GetInstance(c)
    35  	remote, err := remote.Find(instance, doctype)
    36  	if err != nil {
    37  		return wrapRemoteErr(err)
    38  	}
    39  	if remote.Verb != "GET" {
    40  		return jsonapi.MethodNotAllowed("GET")
    41  	}
    42  	err = remote.ProxyTo(instance, c.Response(), c.Request(), slug)
    43  	if err != nil {
    44  		return wrapRemoteErr(err)
    45  	}
    46  	return nil
    47  }
    48  
    49  func remotePost(c echo.Context) error {
    50  	doctype := c.Param("doctype")
    51  	slug, err := allowWholeType(c, permission.POST, doctype)
    52  	if err != nil {
    53  		return wrapRemoteErr(err)
    54  	}
    55  	instance := middlewares.GetInstance(c)
    56  	remote, err := remote.Find(instance, doctype)
    57  	if err != nil {
    58  		return wrapRemoteErr(err)
    59  	}
    60  	if remote.Verb != "POST" {
    61  		return jsonapi.MethodNotAllowed("POST")
    62  	}
    63  	err = remote.ProxyTo(instance, c.Response(), c.Request(), slug)
    64  	if err != nil {
    65  		return wrapRemoteErr(err)
    66  	}
    67  	return nil
    68  }
    69  
    70  func remoteAsset(c echo.Context) error {
    71  	_, err := middlewares.GetPermission(c)
    72  	if err != nil {
    73  		return err
    74  	}
    75  	return wrapRemoteErr(remote.
    76  		ProxyRemoteAsset(c.Param("asset-name"), c.Response()))
    77  }
    78  
    79  // Routes set the routing for the remote service
    80  func Routes(router *echo.Group) {
    81  	router.GET("/_all_doctypes", allDoctypes)
    82  	router.GET("/:doctype", remoteGet)
    83  	router.POST("/:doctype", remotePost)
    84  	router.GET("/assets/:asset-name", remoteAsset)
    85  }
    86  
    87  func wrapRemoteErr(err error) error {
    88  	switch err {
    89  	case remote.ErrNotFoundRemote:
    90  		return jsonapi.NotFound(err)
    91  	case remote.ErrInvalidRequest:
    92  		return jsonapi.BadRequest(err)
    93  	case remote.ErrRequestFailed:
    94  		return jsonapi.BadGateway(err)
    95  	case remote.ErrInvalidVariables:
    96  		return jsonapi.BadRequest(err)
    97  	case remote.ErrMissingVar:
    98  		return jsonapi.BadRequest(err)
    99  	case remote.ErrInvalidContentType:
   100  		return jsonapi.BadGateway(err)
   101  	case remote.ErrRemoteAssetNotFound:
   102  		return jsonapi.NotFound(err)
   103  	}
   104  	return err
   105  }
   106  
   107  func allowWholeType(c echo.Context, v permission.Verb, doctype string) (string, error) {
   108  	pdoc, err := middlewares.GetPermission(c)
   109  	if err != nil {
   110  		return "", err
   111  	}
   112  	if !pdoc.Permissions.AllowWholeType(v, doctype) {
   113  		return "", middlewares.ErrForbidden
   114  	}
   115  	slug := ""
   116  	if parts := strings.SplitN(pdoc.SourceID, "/", 2); len(parts) > 1 {
   117  		slug = parts[1]
   118  	}
   119  	return slug, nil
   120  }