Skip to content

Commit 13577c2

Browse files
committed
Added GCS Read permission error
1 parent cb36601 commit 13577c2

File tree

4 files changed

+79
-9
lines changed

4 files changed

+79
-9
lines changed

server/e2e/proto_project_export_test.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package e2e
22

33
import (
4+
"archive/zip"
5+
"bytes"
46
"context"
7+
"encoding/json"
58
"testing"
69

710
pb "github.com/reearth/reearth/server/internal/adapter/internalapi/schemas/internalapi/v1"
@@ -88,7 +91,8 @@ func TestInternalAPI_export(t *testing.T) {
8891

8992
resp.Header("Content-Type").Contains("application/zip")
9093
body := resp.Body().Raw()
91-
assert.Greater(t, len(body), 0)
94+
assert.Greater(t, len(body), 4)
95+
assert.Equal(t, "PK\x03\x04", string(body[:4])) // check zip file hedder
9296

9397
// private => Error!
9498
exp, err = client.ExportProject(ctx, &pb.ExportProjectRequest{
@@ -131,7 +135,40 @@ func TestInternalAPI_export(t *testing.T) {
131135

132136
resp.Header("Content-Type").Contains("application/zip")
133137
body := resp.Body().Raw()
134-
assert.Greater(t, len(body), 0)
138+
assert.Greater(t, len(body), 4)
139+
assert.Equal(t, "PK\x03\x04", string(body[:4])) // zip header
140+
141+
data := []byte(body)
142+
143+
r, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
144+
require.NoError(t, err)
145+
146+
var pjBytes []byte
147+
for _, f := range r.File {
148+
if f.Name == "project.json" {
149+
rc, err := f.Open()
150+
require.NoError(t, err)
151+
152+
var buf bytes.Buffer
153+
_, err = buf.ReadFrom(rc)
154+
rc.Close()
155+
require.NoError(t, err)
156+
157+
pjBytes = buf.Bytes()
158+
break
159+
}
160+
}
161+
require.NotNil(t, pjBytes, "project.json should exist in the zip")
162+
assert.True(t, json.Valid(pjBytes), "project.json must be valid JSON")
163+
164+
var doc map[string]any
165+
require.NoError(t, json.Unmarshal(pjBytes, &doc))
166+
167+
_, ok := doc["project"].(map[string]any)
168+
assert.True(t, ok, "`project` must exist and be an object")
169+
170+
_, ok = doc["scene"].(map[string]any)
171+
assert.True(t, ok, "`scene` must exist and be an object")
135172

136173
})
137174
}

server/internal/app/repo.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func initReposAndGateways(ctx context.Context, conf *config.Config, debug bool)
130130
func initFile(ctx context.Context, conf *config.Config) (fileRepo gateway.File) {
131131
var err error
132132
if conf.GCS.IsConfigured() {
133-
log.Infofc(ctx, "file: GCS storage is used: %s\n", conf.GCS.BucketName)
133+
log.Infofc(ctx, "[Storage] GCS storage is used: %s", conf.GCS.BucketName)
134134
fileRepo, err = gcs.NewFile(false, conf.GCS.BucketName, conf.AssetBaseURL, conf.GCS.PublicationCacheControl)
135135
if err != nil {
136136
log.Warnf("file: failed to init GCS storage: %s\n", err.Error())
@@ -140,15 +140,15 @@ func initFile(ctx context.Context, conf *config.Config) (fileRepo gateway.File)
140140
}
141141

142142
if conf.S3.IsConfigured() {
143-
log.Infofc(ctx, "file: S3 storage is used: %s\n", conf.S3.BucketName)
143+
log.Infofc(ctx, "[Storage] S3 storage is used: %s", conf.S3.BucketName)
144144
fileRepo, err = s3.NewS3(ctx, conf.S3.BucketName, conf.AssetBaseURL, conf.S3.PublicationCacheControl)
145145
if err != nil {
146146
log.Warnf("file: failed to init S3 storage: %s\n", err.Error())
147147
}
148148
return
149149
}
150150

151-
log.Infof("file: local storage is used")
151+
log.Infof("[Storage] local afero storage is used")
152152
afs := afero.NewBasePathFs(afero.NewOsFs(), "data")
153153
fileRepo, err = fs.NewFile(afs, conf.AssetBaseURL)
154154
if err != nil {

server/internal/infrastructure/gcs/file.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,18 +335,51 @@ func (f *fileRepo) read(ctx context.Context, filename string) (io.ReadCloser, er
335335
return nil, rerror.ErrInternalByWithContext(ctx, err)
336336
}
337337

338-
reader, err := bucket.Object(filename).NewReader(ctx)
338+
obj := bucket.Object(filename)
339+
340+
attrs, err := obj.Attrs(ctx)
339341
if err != nil {
340342
if errors.Is(err, storage.ErrObjectNotExist) {
341343
return nil, rerror.ErrNotFound
342344
}
343-
log.Errorfc(ctx, "gcs: read err: %+v\n", err)
345+
log.Errorfc(ctx, "gcs: attrs err: %+v\n", err)
346+
return nil, rerror.ErrInternalByWithContext(ctx, err)
347+
}
348+
349+
reader, err := obj.Generation(attrs.Generation).NewReader(ctx)
350+
if err != nil {
351+
if errors.Is(err, storage.ErrObjectNotExist) {
352+
if OK := f.exists(ctx, bucket, filename); OK {
353+
return nil, errors.New("no read permission")
354+
}
355+
return nil, rerror.ErrNotFound
356+
}
357+
log.Errorfc(ctx, "gcs: generation read err: %+v\n", err)
344358
return nil, rerror.ErrInternalByWithContext(ctx, err)
345359
}
346360

347361
return reader, nil
348362
}
349363

364+
func (f *fileRepo) exists(ctx context.Context, bucket *storage.BucketHandle, filename string) bool {
365+
fmt.Printf("Checking existence: %s\n", filename)
366+
367+
obj := bucket.Object(filename)
368+
attrs, err := obj.Attrs(ctx)
369+
if err != nil {
370+
if errors.Is(err, storage.ErrObjectNotExist) {
371+
fmt.Printf("File does NOT exist: %s\n", filename)
372+
return false
373+
}
374+
fmt.Printf("Error checking existence: %+v\n", err)
375+
return false
376+
}
377+
378+
fmt.Printf("OK! File exist: %s , Updated: %v (Size: %d bytes, Generation: %d)\n",
379+
filename, attrs.Updated, attrs.Size, attrs.Generation)
380+
return true
381+
}
382+
350383
func (f *fileRepo) upload(ctx context.Context, filename string, content io.Reader) (int64, error) {
351384
if filename == "" {
352385
return 0, gateway.ErrInvalidFile

server/internal/usecase/interactor/common.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,10 @@ func (d ProjectDeleter) Delete(ctx context.Context, prj *project.Project, force
269269
}
270270

271271
func IsCurrentHostAssets(ctx context.Context, u string) bool {
272-
if strings.HasPrefix(u, "assets/") || strings.HasPrefix(u, "/assets") {
272+
if strings.HasPrefix(u, "assets/") && strings.HasPrefix(u, adapter.CurrentHost(ctx)) {
273273
return true
274274
}
275-
return strings.HasPrefix(u, adapter.CurrentHost(ctx))
275+
return false
276276
}
277277

278278
func ReplaceToCurrentHost(ctx context.Context, urlString string) string {

0 commit comments

Comments
 (0)