package collabora import ( "crypto/sha256" "encoding/hex" "fmt" "io" "io/ioutil" "net/http" "os" "regexp" "time" "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/backend/view" tpl "gitnet.fr/deblan/budget/backend/view/template/collabora" "gitnet.fr/deblan/budget/config" "gitnet.fr/deblan/budget/database/model" f "gitnet.fr/deblan/budget/file" ) func getToken() string { now := time.Now() dateString := fmt.Sprintf( "%04d-%02d-%02d-%s", now.Year(), now.Month(), now.Day(), config.Get().Security.Secret, ) hash := sha256.New() hash.Write([]byte(dateString)) hashedBytes := hash.Sum(nil) hashedString := hex.EncodeToString(hashedBytes) return hashedString[:32] } type Controller struct { Token string } func New(e *echo.Echo) *Controller { c := Controller{ Token: getToken(), } e.GET("/collabora/:id", c.Iframe) e.GET("/wopi/:id", c.Info) e.GET("/wopi/:id/contents", c.WopiContentGet) e.POST("/wopi/:id/contents", c.WopiContentPost) return &c } func (ctrl *Controller) Iframe(c echo.Context) error { if nil == model.LoadSessionUser(c) { return c.Redirect(302, "/login") } resp, err := http.Get(config.Get().Collabora.HostingDiscoveryUrl()) if err != nil { return err } defer resp.Body.Close() regex, _ := regexp.Compile(fmt.Sprintf( ``, c.Param("extension"), )) body, _ := io.ReadAll(resp.Body) items := regex.FindStringSubmatch(string(body)) if len(items) == 0 { return nil } wopiSrc := fmt.Sprintf( "%s%s", config.Get().Server.BaseUrl, "/wopi/"+c.Param("id"), ) url := items[1] + "WOPISrc=" + wopiSrc return view.Render(c, 200, tpl.Iframe(url, ctrl.Token)) } func (ctrl *Controller) Info(c echo.Context) error { if c.QueryParam("access_token") != ctrl.Token { return c.JSON(403, nil) } var file string files := []f.File{} f.GetFiles(&files, config.Get().File.Path) for _, f := range files { if f.Id == c.Param("id") { file = f.Path } } if file == "" { return c.JSON(404, message.FileNotFound) } fi, _ := os.Stat(file) type res struct { BaseFileName string Size int64 UserId uint UserCanWrite bool } return c.JSON(200, res{ BaseFileName: fi.Name(), Size: fi.Size(), UserId: 1, // User.ID, UserCanWrite: true, }) } func (ctrl *Controller) WopiContentGet(c echo.Context) error { if c.QueryParam("access_token") != ctrl.Token { return c.JSON(403, nil) } var file string files := []f.File{} f.GetFiles(&files, config.Get().File.Path) for _, f := range files { if f.Id == c.Param("id") { file = f.Path } } if file == "" { return c.JSON(404, message.FileNotFound) } content, _ := os.ReadFile(file) return c.Blob(200, "application/vnd.oasis.opendocument.spreadsheet", content) } func (ctrl *Controller) WopiContentPost(c echo.Context) error { if c.QueryParam("access_token") != ctrl.Token { return c.JSON(403, nil) } var file string files := []f.File{} f.GetFiles(&files, config.Get().File.Path) for _, f := range files { if f.Id == c.Param("id") { file = f.Path } } if file == "" { return c.JSON(404, message.FileNotFound) } data, _ := ioutil.ReadAll(c.Request().Body) err := os.WriteFile(file, data, 0600) if err != nil { return err } return c.JSON(200, nil) }