From 31f4004d47bf57eb3e36b6d9ef8ca227acd34c89 Mon Sep 17 00:00:00 2001 From: ymk <81808708+yk-eukarya@users.noreply.github.com> Date: Fri, 18 Oct 2024 08:37:41 +0200 Subject: [PATCH 1/7] imp --- server/internal/adapter/publicapi/api.go | 24 +++++++++------ server/internal/adapter/publicapi/asset.go | 36 ++++++++++++++++++++++ server/internal/adapter/publicapi/types.go | 2 +- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/server/internal/adapter/publicapi/api.go b/server/internal/adapter/publicapi/api.go index 998767889f..fdca47c234 100644 --- a/server/internal/adapter/publicapi/api.go +++ b/server/internal/adapter/publicapi/api.go @@ -64,28 +64,34 @@ func PublicApiItemList() echo.HandlerFunc { ctx := c.Request().Context() ctrl := GetController(ctx) + mKey := c.Param("model") + pKey := c.Param("project") p, err := listParamFromEchoContext(c) if err != nil { return c.JSON(http.StatusBadRequest, "invalid offset or limit") } resType := "" - m := c.Param("model") - if strings.Contains(m, ".") { - m, resType, _ = strings.Cut(m, ".") + if strings.Contains(mKey, ".") { + mKey, resType, _ = strings.Cut(mKey, ".") } if resType != "csv" && resType != "json" && resType != "geojson" { resType = "json" } - items, _, err := ctrl.GetItems(ctx, c.Param("project"), m, p) + var res any + if mKey == "assets" { + res, err = ctrl.GetAssets(ctx, pKey, p) + } else { + res, _, err = ctrl.GetItems(ctx, pKey, mKey, p) + } if err != nil { return err } - vi, s, err1 := ctrl.GetVersionedItems(ctx, c.Param("project"), m, p) - if err1 != nil { - return err1 + vi, s, err := ctrl.GetVersionedItems(ctx, pKey, mKey, p) + if mKey != "assets" && err != nil { + return err } switch resType { @@ -94,9 +100,9 @@ func PublicApiItemList() echo.HandlerFunc { case "geojson": return toGeoJSON(c, vi, s) case "json": - return c.JSON(http.StatusOK, items) + return c.JSON(http.StatusOK, res) default: - return c.JSON(http.StatusOK, items) + return c.JSON(http.StatusOK, res) } } } diff --git a/server/internal/adapter/publicapi/asset.go b/server/internal/adapter/publicapi/asset.go index c7c49985a8..1fc30f8b70 100644 --- a/server/internal/adapter/publicapi/asset.go +++ b/server/internal/adapter/publicapi/asset.go @@ -4,8 +4,11 @@ import ( "context" "errors" + "github.com/reearth/reearth-cms/server/internal/usecase/interfaces" + "github.com/reearth/reearth-cms/server/pkg/asset" "github.com/reearth/reearth-cms/server/pkg/id" "github.com/reearth/reearthx/rerror" + "github.com/reearth/reearthx/util" ) func (c *Controller) GetAsset(ctx context.Context, prj, i string) (Asset, error) { @@ -34,3 +37,36 @@ func (c *Controller) GetAsset(ctx context.Context, prj, i string) (Asset, error) return NewAsset(a, f, c.assetUrlResolver), nil } + +func (c *Controller) GetAssets(ctx context.Context, pKey string, p ListParam) (ListResult[Asset], error) { + prj, err := c.checkProject(ctx, pKey) + if err != nil { + return ListResult[Asset]{}, err + } + + a, pi, err := c.usecases.Asset.FindByProject(ctx, prj.ID(), interfaces.AssetFilter{ + Sort: nil, + Keyword: nil, + Pagination: p.Pagination, + }, nil) + + if err != nil { + if errors.Is(err, rerror.ErrNotFound) { + return ListResult[Asset]{}, rerror.ErrNotFound + } + return ListResult[Asset]{}, err + } + + res, err := util.TryMap(a, func(i *asset.Asset) (Asset, error) { + f, err := c.usecases.Asset.FindFileByID(ctx, i.ID(), nil) + if err != nil { + return Asset{}, err + } + return NewAsset(i, f, c.assetUrlResolver), nil + }) + if err != nil { + return ListResult[Asset]{}, err + } + + return NewListResult(res, pi, p.Pagination), nil +} diff --git a/server/internal/adapter/publicapi/types.go b/server/internal/adapter/publicapi/types.go index 020fcd3c2b..2a6ab115c9 100644 --- a/server/internal/adapter/publicapi/types.go +++ b/server/internal/adapter/publicapi/types.go @@ -177,7 +177,7 @@ func NewAsset(a *asset.Asset, f *asset.File, urlResolver asset.URLResolver) Asse base, _ := url.Parse(u) base.Path = path.Dir(base.Path) - files = lo.Map(f.FlattenChildren(), func(f *asset.File, _ int) string { + files = lo.Map(f.Files(), func(f *asset.File, _ int) string { b := *base b.Path = path.Join(b.Path, f.Path()) return b.String() From 0455ef4ef4c14d0068d47f26357e9a05ef34b9a4 Mon Sep 17 00:00:00 2001 From: ymk <81808708+yk-eukarya@users.noreply.github.com> Date: Fri, 18 Oct 2024 08:43:24 +0200 Subject: [PATCH 2/7] imp --- server/internal/adapter/publicapi/asset.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/internal/adapter/publicapi/asset.go b/server/internal/adapter/publicapi/asset.go index 1fc30f8b70..7a4f1ceaac 100644 --- a/server/internal/adapter/publicapi/asset.go +++ b/server/internal/adapter/publicapi/asset.go @@ -7,6 +7,7 @@ import ( "github.com/reearth/reearth-cms/server/internal/usecase/interfaces" "github.com/reearth/reearth-cms/server/pkg/asset" "github.com/reearth/reearth-cms/server/pkg/id" + "github.com/reearth/reearth-cms/server/pkg/project" "github.com/reearth/reearthx/rerror" "github.com/reearth/reearthx/util" ) @@ -44,6 +45,10 @@ func (c *Controller) GetAssets(ctx context.Context, pKey string, p ListParam) (L return ListResult[Asset]{}, err } + if prj.Publication().Scope() != project.PublicationScopePublic || !prj.Publication().AssetPublic() { + return ListResult[Asset]{}, rerror.ErrNotFound + } + a, pi, err := c.usecases.Asset.FindByProject(ctx, prj.ID(), interfaces.AssetFilter{ Sort: nil, Keyword: nil, From dac428f4a0a5d48b96a9db4cca6474413481fc11 Mon Sep 17 00:00:00 2001 From: nourbalaha Date: Tue, 22 Oct 2024 13:03:17 +0900 Subject: [PATCH 3/7] add e2e tests --- server/e2e/publicapi_test.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/server/e2e/publicapi_test.go b/server/e2e/publicapi_test.go index 93705591f1..fc79f2fed9 100644 --- a/server/e2e/publicapi_test.go +++ b/server/e2e/publicapi_test.go @@ -203,6 +203,25 @@ func TestPublicAPI(t *testing.T) { "error": "not found", }) + e.GET("/api/p/{project}/assets", publicAPIProjectAlias). + Expect(). + Status(http.StatusOK). + JSON(). + IsEqual(map[string]any{ + "hasMore": false, + "limit": 50, + "offset": 0, + "page": 1, + "results": []map[string]any{ + map[string]any{ + "id": publicAPIAsset1ID.String(), + "type": "asset", + "url": fmt.Sprintf("https://example.com/assets/%s/%s/aaa.zip", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + }, + }, + "totalCount": 1, + }) + e.GET("/api/p/{project}/assets/{assetid}", publicAPIProjectAlias, publicAPIAsset1ID). Expect(). Status(http.StatusOK). @@ -211,9 +230,6 @@ func TestPublicAPI(t *testing.T) { "type": "asset", "id": publicAPIAsset1ID.String(), "url": fmt.Sprintf("https://example.com/assets/%s/%s/aaa.zip", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), - "files": []string{ - fmt.Sprintf("https://example.com/assets/%s/%s/aaa/bbb.txt", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), - }, }) // make the project's assets private @@ -418,7 +434,7 @@ func publicAPISeeder(ctx context.Context, r *repo.Container) error { lo.Must0(r.Project.Save(ctx, p1)) lo.Must0(r.Asset.Save(ctx, a)) - lo.Must0(r.AssetFile.Save(ctx, a.ID(), af)) + lo.Must0(r.AssetFile.Save(ctx, a.ID(), af.Clone())) lo.Must0(r.Schema.Save(ctx, s)) lo.Must0(r.Model.Save(ctx, m)) lo.Must0(r.Item.Save(ctx, i1)) From 537954a3494af7775e64c23321a3e852d543db09 Mon Sep 17 00:00:00 2001 From: nourbalaha Date: Tue, 22 Oct 2024 14:26:39 +0900 Subject: [PATCH 4/7] implement find asset files by asset ids --- server/internal/adapter/publicapi/asset.go | 14 ++---- .../infrastructure/memory/asset_file.go | 26 +++++++++++ .../infrastructure/mongo/asset_file.go | 46 +++++++++++++++++++ server/internal/usecase/interactor/asset.go | 14 ++++++ server/internal/usecase/interfaces/asset.go | 1 + server/internal/usecase/repo/asset.go | 1 + 6 files changed, 93 insertions(+), 9 deletions(-) diff --git a/server/internal/adapter/publicapi/asset.go b/server/internal/adapter/publicapi/asset.go index 7a4f1ceaac..8813c89f81 100644 --- a/server/internal/adapter/publicapi/asset.go +++ b/server/internal/adapter/publicapi/asset.go @@ -49,7 +49,7 @@ func (c *Controller) GetAssets(ctx context.Context, pKey string, p ListParam) (L return ListResult[Asset]{}, rerror.ErrNotFound } - a, pi, err := c.usecases.Asset.FindByProject(ctx, prj.ID(), interfaces.AssetFilter{ + al, pi, err := c.usecases.Asset.FindByProject(ctx, prj.ID(), interfaces.AssetFilter{ Sort: nil, Keyword: nil, Pagination: p.Pagination, @@ -62,16 +62,12 @@ func (c *Controller) GetAssets(ctx context.Context, pKey string, p ListParam) (L return ListResult[Asset]{}, err } - res, err := util.TryMap(a, func(i *asset.Asset) (Asset, error) { - f, err := c.usecases.Asset.FindFileByID(ctx, i.ID(), nil) - if err != nil { - return Asset{}, err - } - return NewAsset(i, f, c.assetUrlResolver), nil - }) + fileMap, err := c.usecases.Asset.FindFilesByIDs(ctx, util.Map(al, func(a *asset.Asset) id.AssetID { return a.ID() }), nil) if err != nil { return ListResult[Asset]{}, err } - return NewListResult(res, pi, p.Pagination), nil + return NewListResult(util.Map(al, func(a *asset.Asset) Asset { + return NewAsset(a, fileMap[a.ID()], c.assetUrlResolver) + }), pi, p.Pagination), nil } diff --git a/server/internal/infrastructure/memory/asset_file.go b/server/internal/infrastructure/memory/asset_file.go index 28c2967ecf..762b893483 100644 --- a/server/internal/infrastructure/memory/asset_file.go +++ b/server/internal/infrastructure/memory/asset_file.go @@ -41,6 +41,32 @@ func (r *AssetFile) FindByID(ctx context.Context, id id.AssetID) (*asset.File, e return rerror.ErrIfNil(f, rerror.ErrNotFound) } +func (r *AssetFile) FindByIDs(ctx context.Context, ids id.AssetIDList) (map[id.AssetID]*asset.File, error) { + if r.err != nil { + return nil, r.err + } + + filesMap := make(map[id.AssetID]*asset.File) + for _, id := range ids { + f := r.data.Find(func(key asset.ID, value *asset.File) bool { + return key == id + }).Clone() + fs := r.files.Find(func(key asset.ID, value []*asset.File) bool { + return key == id + }) + if len(fs) > 0 { + f.SetFiles(fs) + } + if f == nil { + return nil, rerror.ErrNotFound + } + filesMap[id] = f + } + + return filesMap, nil +} + + func (r *AssetFile) Save(ctx context.Context, id id.AssetID, file *asset.File) error { if r.err != nil { return r.err diff --git a/server/internal/infrastructure/mongo/asset_file.go b/server/internal/infrastructure/mongo/asset_file.go index ddf5c532db..48eb1992fd 100644 --- a/server/internal/infrastructure/mongo/asset_file.go +++ b/server/internal/infrastructure/mongo/asset_file.go @@ -74,6 +74,52 @@ func (r *AssetFile) FindByID(ctx context.Context, id id.AssetID) (*asset.File, e return f, nil } +func (r *AssetFile) FindByIDs(ctx context.Context, ids id.AssetIDList) (map[id.AssetID]*asset.File, error) { + filesMap := make(map[id.AssetID]*asset.File) + + c := &mongodoc.AssetAndFileConsumer{} + if err := r.client.Find(ctx, bson.M{ + "id": bson.M{"$in": ids.Strings()}, + }, c, options.Find().SetProjection(bson.M{ + "id": 1, + "file": 1, + "flatfiles": 1, + })); err != nil { + return nil, err + } + + for _, result := range c.Result { + assetID := result.ID + f := result.File.Model() + if f == nil { + return nil, rerror.ErrNotFound + } + + if result.FlatFiles { + var afc mongodoc.AssetFilesConsumer + if err := r.assetFilesClient.Find(ctx, bson.M{ + "assetid": assetID, + }, &afc, options.Find().SetSort(bson.D{ + {Key: "page", Value: 1}, + })); err != nil { + return nil, err + } + files := afc.Result().Model() + f.SetFiles(files) + } else if len(f.Children()) > 0 { + f.SetFiles(f.FlattenChildren()) + } + + aId, err := id.AssetIDFrom(assetID) + if err != nil { + return nil, err + } + filesMap[aId] = f + } + + return filesMap, nil +} + func (r *AssetFile) Save(ctx context.Context, id id.AssetID, file *asset.File) error { doc := mongodoc.NewFile(file) _, err := r.client.Client().UpdateOne(ctx, bson.M{ diff --git a/server/internal/usecase/interactor/asset.go b/server/internal/usecase/interactor/asset.go index 0551fe30c2..79815b6085 100644 --- a/server/internal/usecase/interactor/asset.go +++ b/server/internal/usecase/interactor/asset.go @@ -69,6 +69,20 @@ func (i *Asset) FindFileByID(ctx context.Context, aid id.AssetID, _ *usecase.Ope return files, nil } +func (i *Asset) FindFilesByIDs(ctx context.Context, ids id.AssetIDList, _ *usecase.Operator) (map[id.AssetID]*asset.File, error) { + _, err := i.repos.Asset.FindByIDs(ctx, ids) + if err != nil { + return nil, err + } + + files, err := i.repos.AssetFile.FindByIDs(ctx, ids) + if err != nil { + return nil, err + } + + return files, nil +} + func (i *Asset) DownloadByID(ctx context.Context, aid id.AssetID, _ *usecase.Operator) (io.ReadCloser, error) { a, err := i.repos.Asset.FindByID(ctx, aid) if err != nil { diff --git a/server/internal/usecase/interfaces/asset.go b/server/internal/usecase/interfaces/asset.go index 7fafca5e55..958258306e 100644 --- a/server/internal/usecase/interfaces/asset.go +++ b/server/internal/usecase/interfaces/asset.go @@ -61,6 +61,7 @@ type Asset interface { FindByIDs(context.Context, []id.AssetID, *usecase.Operator) (asset.List, error) FindByProject(context.Context, id.ProjectID, AssetFilter, *usecase.Operator) (asset.List, *usecasex.PageInfo, error) FindFileByID(context.Context, id.AssetID, *usecase.Operator) (*asset.File, error) + FindFilesByIDs(context.Context, id.AssetIDList, *usecase.Operator) (map[id.AssetID]*asset.File, error) DownloadByID(context.Context, id.AssetID, *usecase.Operator) (io.ReadCloser, error) GetURL(*asset.Asset) string Create(context.Context, CreateAssetParam, *usecase.Operator) (*asset.Asset, *asset.File, error) diff --git a/server/internal/usecase/repo/asset.go b/server/internal/usecase/repo/asset.go index 67cb1275e0..a7bc23b2dd 100644 --- a/server/internal/usecase/repo/asset.go +++ b/server/internal/usecase/repo/asset.go @@ -25,6 +25,7 @@ type Asset interface { type AssetFile interface { FindByID(context.Context, id.AssetID) (*asset.File, error) + FindByIDs(context.Context, id.AssetIDList) (map[id.AssetID]*asset.File, error) Save(context.Context, id.AssetID, *asset.File) error SaveFlat(context.Context, id.AssetID, *asset.File, []*asset.File) error } From 329cd51dd40a81559dd99c4e3920c61b032b8de4 Mon Sep 17 00:00:00 2001 From: nourbalaha Date: Tue, 22 Oct 2024 15:04:36 +0900 Subject: [PATCH 5/7] test: update the e2e test --- server/e2e/publicapi_test.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/server/e2e/publicapi_test.go b/server/e2e/publicapi_test.go index fc79f2fed9..b501c063a6 100644 --- a/server/e2e/publicapi_test.go +++ b/server/e2e/publicapi_test.go @@ -214,9 +214,13 @@ func TestPublicAPI(t *testing.T) { "page": 1, "results": []map[string]any{ map[string]any{ - "id": publicAPIAsset1ID.String(), - "type": "asset", - "url": fmt.Sprintf("https://example.com/assets/%s/%s/aaa.zip", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + "id": publicAPIAsset1ID.String(), + "type": "asset", + "url": fmt.Sprintf("https://example.com/assets/%s/%s/aaa.zip", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + "contentType": "application/zip", + "files": []string{ + fmt.Sprintf("https://example.com/assets/%s/%s/aaa/bbb.txt", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + }, }, }, "totalCount": 1, @@ -227,9 +231,13 @@ func TestPublicAPI(t *testing.T) { Status(http.StatusOK). JSON(). IsEqual(map[string]any{ - "type": "asset", - "id": publicAPIAsset1ID.String(), - "url": fmt.Sprintf("https://example.com/assets/%s/%s/aaa.zip", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + "type": "asset", + "id": publicAPIAsset1ID.String(), + "url": fmt.Sprintf("https://example.com/assets/%s/%s/aaa.zip", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + "contentType": "application/zip", + "files": []string{ + fmt.Sprintf("https://example.com/assets/%s/%s/aaa/bbb.txt", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + }, }) // make the project's assets private @@ -370,8 +378,7 @@ func publicAPISeeder(ctx context.Context, r *repo.Container) error { a := asset.New().ID(publicAPIAsset1ID).Project(p1.ID()).CreatedByUser(uid).Size(1).Thread(id.NewThreadID()). FileName("aaa.zip").UUID(publicAPIAssetUUID).MustBuild() - af := asset.NewFile().Name("bbb.txt").Path("aaa/bbb.txt").Build() - + af := asset.NewFile().Name("aaa.zip").Path("aaa.zip").ContentType("application/zip").Size(1).Children([]*asset.File{asset.NewFile().Name("bbb.txt").Path("aaa/bbb.txt").Build()}).Build() fid := id.NewFieldID() gst := schema.GeometryObjectSupportedTypeList{schema.GeometryObjectSupportedTypePoint, schema.GeometryObjectSupportedTypeLineString} gest := schema.GeometryEditorSupportedTypeList{schema.GeometryEditorSupportedTypePoint, schema.GeometryEditorSupportedTypeLineString} @@ -434,7 +441,7 @@ func publicAPISeeder(ctx context.Context, r *repo.Container) error { lo.Must0(r.Project.Save(ctx, p1)) lo.Must0(r.Asset.Save(ctx, a)) - lo.Must0(r.AssetFile.Save(ctx, a.ID(), af.Clone())) + lo.Must0(r.AssetFile.Save(ctx, a.ID(), af)) lo.Must0(r.Schema.Save(ctx, s)) lo.Must0(r.Model.Save(ctx, m)) lo.Must0(r.Item.Save(ctx, i1)) From a306552f2f82f0e939b2a5af07d0abda5dec6d12 Mon Sep 17 00:00:00 2001 From: nourbalaha Date: Tue, 22 Oct 2024 17:08:02 +0900 Subject: [PATCH 6/7] refactor --- server/e2e/publicapi_test.go | 6 +++++- server/internal/adapter/publicapi/api.go | 21 ++++++++++++--------- server/internal/adapter/publicapi/types.go | 4 ++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/server/e2e/publicapi_test.go b/server/e2e/publicapi_test.go index b501c063a6..6506b1da19 100644 --- a/server/e2e/publicapi_test.go +++ b/server/e2e/publicapi_test.go @@ -220,6 +220,7 @@ func TestPublicAPI(t *testing.T) { "contentType": "application/zip", "files": []string{ fmt.Sprintf("https://example.com/assets/%s/%s/aaa/bbb.txt", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + fmt.Sprintf("https://example.com/assets/%s/%s/aaa/ccc.txt", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), }, }, }, @@ -237,6 +238,7 @@ func TestPublicAPI(t *testing.T) { "contentType": "application/zip", "files": []string{ fmt.Sprintf("https://example.com/assets/%s/%s/aaa/bbb.txt", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), + fmt.Sprintf("https://example.com/assets/%s/%s/aaa/ccc.txt", publicAPIAssetUUID[:2], publicAPIAssetUUID[2:]), }, }) @@ -378,7 +380,9 @@ func publicAPISeeder(ctx context.Context, r *repo.Container) error { a := asset.New().ID(publicAPIAsset1ID).Project(p1.ID()).CreatedByUser(uid).Size(1).Thread(id.NewThreadID()). FileName("aaa.zip").UUID(publicAPIAssetUUID).MustBuild() - af := asset.NewFile().Name("aaa.zip").Path("aaa.zip").ContentType("application/zip").Size(1).Children([]*asset.File{asset.NewFile().Name("bbb.txt").Path("aaa/bbb.txt").Build()}).Build() + c := []*asset.File{asset.NewFile().Name("bbb.txt").Path("aaa/bbb.txt").Build(), asset.NewFile().Name("ccc.txt").Path("aaa/ccc.txt").Build()} + af := asset.NewFile().Name("aaa.zip").Path("aaa.zip").ContentType("application/zip").Size(10).Children(c).Build() + fid := id.NewFieldID() gst := schema.GeometryObjectSupportedTypeList{schema.GeometryObjectSupportedTypePoint, schema.GeometryObjectSupportedTypeLineString} gest := schema.GeometryEditorSupportedTypeList{schema.GeometryEditorSupportedTypePoint, schema.GeometryEditorSupportedTypeLineString} diff --git a/server/internal/adapter/publicapi/api.go b/server/internal/adapter/publicapi/api.go index fdca47c234..4385fa8242 100644 --- a/server/internal/adapter/publicapi/api.go +++ b/server/internal/adapter/publicapi/api.go @@ -33,7 +33,7 @@ func GetController(ctx context.Context) *Controller { func Echo(e *echo.Group) { e.Use(middleware.CORS()) - e.GET("/:project/:model", PublicApiItemList()) + e.GET("/:project/:model", PublicApiItemOrAssetList()) e.GET("/:project/:model/:item", PublicApiItemOrAsset()) } @@ -59,7 +59,7 @@ func PublicApiItemOrAsset() echo.HandlerFunc { } } -func PublicApiItemList() echo.HandlerFunc { +func PublicApiItemOrAssetList() echo.HandlerFunc { return func(c echo.Context) error { ctx := c.Request().Context() ctrl := GetController(ctx) @@ -71,6 +71,14 @@ func PublicApiItemList() echo.HandlerFunc { return c.JSON(http.StatusBadRequest, "invalid offset or limit") } + if mKey == "assets" { + res, err := ctrl.GetAssets(ctx, pKey, p) + if err != nil { + return err + } + return c.JSON(http.StatusOK, res) + } + resType := "" if strings.Contains(mKey, ".") { mKey, resType, _ = strings.Cut(mKey, ".") @@ -79,18 +87,13 @@ func PublicApiItemList() echo.HandlerFunc { resType = "json" } - var res any - if mKey == "assets" { - res, err = ctrl.GetAssets(ctx, pKey, p) - } else { - res, _, err = ctrl.GetItems(ctx, pKey, mKey, p) - } + res, _, err := ctrl.GetItems(ctx, pKey, mKey, p) if err != nil { return err } vi, s, err := ctrl.GetVersionedItems(ctx, pKey, mKey, p) - if mKey != "assets" && err != nil { + if err != nil { return err } diff --git a/server/internal/adapter/publicapi/types.go b/server/internal/adapter/publicapi/types.go index 2a6ab115c9..4e1d495e91 100644 --- a/server/internal/adapter/publicapi/types.go +++ b/server/internal/adapter/publicapi/types.go @@ -177,9 +177,9 @@ func NewAsset(a *asset.Asset, f *asset.File, urlResolver asset.URLResolver) Asse base, _ := url.Parse(u) base.Path = path.Dir(base.Path) - files = lo.Map(f.Files(), func(f *asset.File, _ int) string { + files = lo.Map(f.FilePaths(), func(p string, _ int) string { b := *base - b.Path = path.Join(b.Path, f.Path()) + b.Path = path.Join(b.Path, p) return b.String() }) } From c4af3594b5179e19abe5d46c80d56a554505fbc0 Mon Sep 17 00:00:00 2001 From: nourbalaha Date: Wed, 23 Oct 2024 13:24:13 +0900 Subject: [PATCH 7/7] implement asset list ids --- server/internal/adapter/publicapi/asset.go | 2 +- server/pkg/asset/list.go | 8 ++++++++ server/pkg/asset/list_test.go | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/server/internal/adapter/publicapi/asset.go b/server/internal/adapter/publicapi/asset.go index 8813c89f81..b2bee3ecd4 100644 --- a/server/internal/adapter/publicapi/asset.go +++ b/server/internal/adapter/publicapi/asset.go @@ -62,7 +62,7 @@ func (c *Controller) GetAssets(ctx context.Context, pKey string, p ListParam) (L return ListResult[Asset]{}, err } - fileMap, err := c.usecases.Asset.FindFilesByIDs(ctx, util.Map(al, func(a *asset.Asset) id.AssetID { return a.ID() }), nil) + fileMap, err := c.usecases.Asset.FindFilesByIDs(ctx, al.IDs(), nil) if err != nil { return ListResult[Asset]{}, err } diff --git a/server/pkg/asset/list.go b/server/pkg/asset/list.go index e9cc7cd886..6c384b9d26 100644 --- a/server/pkg/asset/list.go +++ b/server/pkg/asset/list.go @@ -1,6 +1,7 @@ package asset import ( + "github.com/reearth/reearth-cms/server/pkg/id" "github.com/reearth/reearthx/util" "github.com/samber/lo" "golang.org/x/exp/slices" @@ -27,3 +28,10 @@ func (l List) Map() Map { return a.ID(), a }) } + +func (l List) IDs() (ids id.AssetIDList) { + for _, a := range l { + ids = ids.Add(a.ID()) + } + return +} diff --git a/server/pkg/asset/list_test.go b/server/pkg/asset/list_test.go index 099a8478b0..84809293d6 100644 --- a/server/pkg/asset/list_test.go +++ b/server/pkg/asset/list_test.go @@ -3,6 +3,7 @@ package asset import ( "testing" + "github.com/reearth/reearth-cms/server/pkg/id" "github.com/reearth/reearthx/account/accountdomain" "github.com/stretchr/testify/assert" ) @@ -51,3 +52,12 @@ func TestList_Map(t *testing.T) { }, List{a, nil}.Map()) assert.Equal(t, Map{}, List(nil).Map()) } + +func TestList_IDs(t *testing.T) { + pid := NewProjectID() + uid := accountdomain.NewUserID() + a1 := New().NewID().Project(pid).CreatedByUser(uid).Size(1000).Thread(NewThreadID()).NewUUID().MustBuild() + a2 := New().NewID().Project(pid).CreatedByUser(uid).Size(1000).Thread(NewThreadID()).NewUUID().MustBuild() + al := List{a1, a2} + assert.Equal(t, al.IDs(), id.AssetIDList{a1.ID(), a2.ID()}) +}