diff --git a/server/internal/app/file.go b/server/internal/app/file.go index 076d09d8a1..943f531f1a 100644 --- a/server/internal/app/file.go +++ b/server/internal/app/file.go @@ -1,12 +1,10 @@ package app import ( - "fmt" "io" "mime" "net/http" "path" - "time" "github.com/labstack/echo/v4" "github.com/reearth/reearth/server/internal/usecase/gateway" @@ -26,7 +24,6 @@ func serveFiles( return func(ctx echo.Context) error { reader, filename, err := handler(ctx) if err != nil { - fmt.Printf("file handler err: %s\n", err.Error()) return err } ct := "application/octet-stream" @@ -53,25 +50,13 @@ func serveFiles( "/export/:filename", fileHandler(func(ctx echo.Context) (io.Reader, string, error) { filename := ctx.Param("filename") - r, err := repo.ReadExportProjectZip(ctx.Request().Context(), filename) if err != nil { - return nil, "", err + return nil, "", rerror.ErrNotFound } - fmt.Printf("download: %s \n", filename) - - go func() { - // download and then delete - time.Sleep(3 * time.Second) - err := repo.RemoveExportProjectZip(ctx.Request().Context(), filename) - if err != nil { - fmt.Printf("delete err: %s \n", err.Error()) - } else { - fmt.Printf("file deleted: %s \n", filename) - } - }() - - return r, filename, nil + // download and then delete + err = repo.RemoveExportProjectZip(ctx.Request().Context(), filename) + return r, filename, err }), ) diff --git a/server/internal/infrastructure/gcs/file.go b/server/internal/infrastructure/gcs/file.go index a8a94d852c..9109421fd5 100644 --- a/server/internal/infrastructure/gcs/file.go +++ b/server/internal/infrastructure/gcs/file.go @@ -109,7 +109,7 @@ func (f *fileRepo) RemoveAsset(ctx context.Context, u *url.URL) error { func (f *fileRepo) ReadPluginFile(ctx context.Context, pid id.PluginID, filename string) (io.ReadCloser, error) { sn := sanitize.Path(filename) if sn == "" { - return nil, gateway.ErrInvalidFile + return nil, rerror.ErrNotFound } return f.read(ctx, path.Join(gcsPluginBasePath, pid.String(), sn)) } @@ -133,7 +133,7 @@ func (f *fileRepo) RemovePlugin(ctx context.Context, pid id.PluginID) error { func (f *fileRepo) ReadBuiltSceneFile(ctx context.Context, name string) (io.ReadCloser, error) { if name == "" { - return nil, gateway.ErrInvalidFile + return nil, rerror.ErrNotFound } return f.read(ctx, path.Join(gcsMapBasePath, sanitize.Path(name)+".json")) } @@ -170,7 +170,7 @@ func (f *fileRepo) RemoveBuiltScene(ctx context.Context, name string) error { func (f *fileRepo) ReadStoryFile(ctx context.Context, name string) (io.ReadCloser, error) { if name == "" { - return nil, gateway.ErrInvalidFile + return nil, rerror.ErrNotFound } return f.read(ctx, path.Join(gcsStoryBasePath, sanitize.Path(name)+".json")) } @@ -208,15 +208,20 @@ func (f *fileRepo) RemoveStory(ctx context.Context, name string) error { func (f *fileRepo) ReadExportProjectZip(ctx context.Context, name string) (io.ReadCloser, error) { sn := sanitize.Path(name) if sn == "" { - return nil, gateway.ErrInvalidFile + return nil, rerror.ErrNotFound } - r, err := f.read(ctx, path.Join(gcsExportBasePath, sn)) + bucket, err := f.bucket(ctx) if err != nil { - if errors.Is(err, rerror.ErrNotFound) { - r, err = f.read(ctx, path.Join(gcsExportBasePath, name)) - } + log.Errorfc(ctx, "gcs: read bucket err: %+v\n", err) + return nil, rerror.ErrInternalByWithContext(ctx, err) } - return r, err + if ok := checkPrefix(ctx, bucket, gcsExportBasePath); !ok { + return nil, errors.New("Prefix not exist") + } + if ok := checkObject(ctx, bucket, gcsExportBasePath, path.Join(gcsExportBasePath, sn)); !ok { + return nil, errors.New("Object not exist") + } + return f.read(ctx, path.Join(gcsExportBasePath, sn)) } func (f *fileRepo) UploadExportProjectZip(ctx context.Context, zipFile afero.File) error { @@ -410,3 +415,38 @@ func newAssetID() string { // TODO: replace return id.NewAssetID().String() } + +func checkPrefix(ctx context.Context, bucket *storage.BucketHandle, prefix string) bool { + it := bucket.Objects(ctx, &storage.Query{ + Delimiter: "/", + }) + for { + attrs, err := it.Next() + if err == iterator.Done { + break + } + fmt.Printf("attrs.Prefix %s \n", attrs.Prefix) + if attrs.Prefix == prefix+"/" { + return true + } + } + return false +} + +func checkObject(ctx context.Context, bucket *storage.BucketHandle, prefix string, objectName string) bool { + it := bucket.Objects(ctx, &storage.Query{ + Prefix: prefix + "/", + Delimiter: "/", + }) + for { + attrs, err := it.Next() + if err == iterator.Done { + break + } + fmt.Printf("attrs.Name %s \n", attrs.Name) + if attrs.Name == objectName { + return true + } + } + return false +}