Skip to content

Commit

Permalink
Merge pull request #338 from nemunaire/integration-improvements
Browse files Browse the repository at this point in the history
Improve integrations with metadata and debug routes
  • Loading branch information
ddvk authored Nov 17, 2024
2 parents 743916c + f190b66 commit 1a3f0ce
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 20 deletions.
27 changes: 22 additions & 5 deletions internal/app/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,9 +903,25 @@ func (app *App) blobStorageWrite(c *gin.Context) {
}

func (app *App) integrationsGetMetadata(c *gin.Context) {
var metadata messages.IntegrationMetadata
metadata.Thumbnail = ""
c.JSON(http.StatusOK, &metadata)
uid := c.GetString(userIDKey)
integrationID := common.ParamS(integrationKey, c)
fileID := common.ParamS(fileKey, c)

integrationProvider, err := integrations.GetIntegrationProvider(app.userStorer, uid, integrationID)
if err != nil {
log.Error(fmt.Errorf("can't get integration, %v", err))
c.AbortWithStatus(http.StatusInternalServerError)
return
}

metadata, err := integrationProvider.GetMetadata(fileID)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

c.JSON(http.StatusOK, metadata)
}

func (app *App) integrationsUpload(c *gin.Context) {
Expand Down Expand Up @@ -947,7 +963,7 @@ func (app *App) integrationsGetFile(c *gin.Context) {
return
}

reader, err := integrationProvider.Download(fileID)
reader, size, err := integrationProvider.Download(fileID)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
Expand All @@ -956,8 +972,9 @@ func (app *App) integrationsGetFile(c *gin.Context) {

defer reader.Close()

c.DataFromReader(http.StatusOK, -1, "application/octet-stream", reader, nil)
c.DataFromReader(http.StatusOK, size, "application/octet-stream", reader, nil)
}

func (app *App) integrationsList(c *gin.Context) {
uid := c.GetString(userIDKey)
integrationID := common.ParamS(integrationKey, c)
Expand Down
9 changes: 7 additions & 2 deletions internal/integrations/dropbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ func newDropbox(i model.IntegrationConfig) *DropBox {
}
}

func (d *DropBox) GetMetadata(fileID string) (*messages.IntegrationMetadata, error) {
// TODO
return nil, nil
}

func (d *DropBox) List(folderID string, depth int) (*messages.IntegrationFolder, error) {

args := files.ListFolderArg{
Expand Down Expand Up @@ -65,8 +70,8 @@ func (d *DropBox) List(folderID string, depth int) (*messages.IntegrationFolder,
return response, nil
}

func (d *DropBox) Download(fileID string) (io.ReadCloser, error) {
return nil, nil
func (d *DropBox) Download(fileID string) (io.ReadCloser, int64, error) {
return nil, 0, nil

}
func (d *DropBox) Upload(folderID, name, fileType string, reader io.ReadCloser) (string, error) {
Expand Down
6 changes: 3 additions & 3 deletions internal/integrations/integrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ const (

// IntegrationProvider abstracts 3rd party integrations
type IntegrationProvider interface {
GetMetadata(fileID string) (result *messages.IntegrationMetadata, err error)
List(folderID string, depth int) (result *messages.IntegrationFolder, err error)
Download(fileID string) (io.ReadCloser, error)
Download(fileID string) (io.ReadCloser, int64, error)
Upload(folderID, name, fileType string, reader io.ReadCloser) (string, error)
}

Expand Down Expand Up @@ -125,7 +126,6 @@ func visitDir(root, currentPath string, depth int, parentFolder *messages.Integr
docName := strings.TrimSuffix(entryName, ext)
extension := strings.TrimPrefix(ext, ".")


file := &messages.IntegrationFile{
ProvidedFileType: contentType,
DateChanged: d.ModTime(),
Expand All @@ -134,7 +134,7 @@ func visitDir(root, currentPath string, depth int, parentFolder *messages.Integr
ID: encodedPath,
FileID: encodedPath,
Name: docName,
Size: int(d.Size()),
Size: d.Size(),
SourceFileType: contentType,
}

Expand Down
32 changes: 29 additions & 3 deletions internal/integrations/localfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,25 @@ func newLocalFS(i model.IntegrationConfig) *localFS {
}
}

func (d *localFS) GetMetadata(fileID string) (*messages.IntegrationMetadata, error) {
decoded, err := decodeName(fileID)
if err != nil {
return nil, err
}

ext := path.Ext(decoded)
contentType := contentTypeFromExt(ext)

return &messages.IntegrationMetadata{
ID: fileID,
Name: path.Base(decoded),
Thumbnail: []byte{},
SourceFileType: contentType,
ProvidedFileType: contentType,
FileType: ext,
}, nil
}

// List populates the response
func (d *localFS) List(folder string, depth int) (*messages.IntegrationFolder, error) {
response := messages.NewIntegrationFolder(folder, "")
Expand Down Expand Up @@ -69,16 +88,23 @@ func (d *localFS) List(folder string, depth int) (*messages.IntegrationFolder, e
return response, nil
}

func (d *localFS) Download(fileID string) (io.ReadCloser, error) {
func (d *localFS) Download(fileID string) (io.ReadCloser, int64, error) {
decoded, err := decodeName(fileID)
if err != nil {
return nil, err
return nil, 0, err
}

localPath := path.Join(d.rootPath, path.Clean(decoded))
return os.Open(localPath)

st, err := os.Stat(localPath)
if err != nil {
return nil, 0, err
}

res, err := os.Open(localPath)
return res, st.Size(), err
}

func (d *localFS) Upload(folderID, name, fileType string, reader io.ReadCloser) (id string, err error) {
folder := "/"
if folderID != rootFolder {
Expand Down
31 changes: 29 additions & 2 deletions internal/integrations/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,39 @@ func (w *WebDavIntegration) Upload(folderID, name, fileType string, reader io.Re
}

// Download downloads
func (w *WebDavIntegration) Download(fileID string) (io.ReadCloser, error) {
func (w *WebDavIntegration) Download(fileID string) (io.ReadCloser, int64, error) {
decoded, err := decodeName(fileID)
if err != nil {
return nil, 0, err
}

st, err := w.c.Stat(decoded)
if err != nil {
return nil, 0, err
}

res, err := w.c.ReadStream(decoded)

return res, st.Size(), err
}

func (w *WebDavIntegration) GetMetadata(fileID string) (*messages.IntegrationMetadata, error) {
decoded, err := decodeName(fileID)
if err != nil {
return nil, err
}
return w.c.ReadStream(decoded)

ext := path.Ext(decoded)
contentType := contentTypeFromExt(ext)

return &messages.IntegrationMetadata{
ID: fileID,
Name: path.Base(decoded),
Thumbnail: []byte{},
SourceFileType: contentType,
ProvidedFileType: contentType,
FileType: ext,
}, nil
}

// List populates the response
Expand Down
13 changes: 8 additions & 5 deletions internal/messages/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ type IntegrationFile struct {
ID string `json:"id"`
Name string `json:"name"`
ProvidedFileType string `json:"providedFileType"`
Size int `json:"size"`
Size int64 `json:"size"`
SourceFileType string `json:"sourceFileType"`
}

Expand All @@ -225,8 +225,11 @@ type IntegrationFolder struct {
}

type IntegrationMetadata struct {
FileType string `json:"fileType"`
ID string `json:"id"`
Name string `json:"name"`
Thumbnail string `json:"thumbnail"`
ID string `json:"id"`
Name string `json:"name"`
// Thumbnail is base64 encoded string of an image/png
Thumbnail []byte `json:"thumbnail"`
SourceFileType string `json:"sourceFileType"`
ProvidedFileType string `json:"providedFileType"`
FileType string `json:"fileType"`
}
78 changes: 78 additions & 0 deletions internal/ui/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/ddvk/rmfakecloud/internal/common"
"github.com/ddvk/rmfakecloud/internal/integrations"
"github.com/ddvk/rmfakecloud/internal/model"
"github.com/ddvk/rmfakecloud/internal/storage"
"github.com/ddvk/rmfakecloud/internal/ui/viewmodel"
Expand Down Expand Up @@ -649,3 +650,80 @@ func (app *ReactAppWrapper) deleteIntegration(c *gin.Context) {

c.AbortWithStatus(http.StatusNotFound)
}

func (app *ReactAppWrapper) exploreIntegration(c *gin.Context) {
uid := c.GetString(userIDContextKey)

integrationID := common.ParamS(intIDParam, c)

integrationProvider, err := integrations.GetIntegrationProvider(app.userStorer, uid, integrationID)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

folder := common.ParamS("path", c)
if folder == "" {
folder = "root"
}

response, err := integrationProvider.List(folder, 2)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

c.JSON(http.StatusOK, response)
}

func (app *ReactAppWrapper) getMetadataIntegration(c *gin.Context) {
uid := c.GetString(userIDContextKey)

integrationID := common.ParamS(intIDParam, c)

integrationProvider, err := integrations.GetIntegrationProvider(app.userStorer, uid, integrationID)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

fileid := common.ParamS("path", c)

response, err := integrationProvider.GetMetadata(fileid)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

c.JSON(http.StatusOK, response)
}

func (app *ReactAppWrapper) downloadThroughIntegration(c *gin.Context) {
uid := c.GetString(userIDContextKey)

integrationID := common.ParamS(intIDParam, c)

integrationProvider, err := integrations.GetIntegrationProvider(app.userStorer, uid, integrationID)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

fileid := common.ParamS("path", c)

response, size, err := integrationProvider.Download(fileid)
if err != nil {
log.Error(err)
c.AbortWithStatus(http.StatusInternalServerError)
return
}

defer response.Close()

c.DataFromReader(http.StatusOK, size, "", response, nil)
}
4 changes: 4 additions & 0 deletions internal/ui/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) {
auth.PUT("integrations/:intid", app.updateIntegration)
auth.DELETE("integrations/:intid", app.deleteIntegration)

auth.GET("integrations/:intid/explore/*path", app.exploreIntegration)
auth.GET("integrations/:intid/metadata/*path", app.getMetadataIntegration)
auth.GET("integrations/:intid/download/*path", app.downloadThroughIntegration)

//admin
admin := auth.Group("")
admin.Use(app.adminMiddleware())
Expand Down

0 comments on commit 1a3f0ce

Please sign in to comment.