diff --git a/e2e/tests/permission_test.go b/e2e/tests/permission_test.go index b4cd6c34a..df5ccf718 100644 --- a/e2e/tests/permission_test.go +++ b/e2e/tests/permission_test.go @@ -1429,3 +1429,77 @@ func (s *StorageTestSuite) TestUpdateGroupExtraWithPermission() { s.Require().Error(err) } + +func (s *StorageTestSuite) TestPutPolicy_ObjectWithSlash() { + var err error + user := s.GenAndChargeAccounts(2, 1000000) + + sp := s.BaseSuite.PickStorageProvider() + gvg, found := sp.GetFirstGlobalVirtualGroup() + s.Require().True(found) + // CreateBucket + bucketName := storageutil.GenRandomBucketName() + msgCreateBucket := storagetypes.NewMsgCreateBucket( + user[0].GetAddr(), bucketName, storagetypes.VISIBILITY_TYPE_PUBLIC_READ, sp.OperatorKey.GetAddr(), + nil, math.MaxUint, nil, 0) + msgCreateBucket.PrimarySpApproval.GlobalVirtualGroupFamilyId = gvg.FamilyId + msgCreateBucket.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateBucket.GetApprovalBytes()) + s.Require().NoError(err) + s.SendTxBlock(user[0], msgCreateBucket) + + // HeadBucket + ctx := context.Background() + queryHeadBucketRequest := storagetypes.QueryHeadBucketRequest{ + BucketName: bucketName, + } + queryHeadBucketResponse, err := s.Client.HeadBucket(ctx, &queryHeadBucketRequest) + s.Require().NoError(err) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.BucketName, bucketName) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.Owner, user[0].GetAddr().String()) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.GlobalVirtualGroupFamilyId, gvg.FamilyId) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.PaymentAddress, user[0].GetAddr().String()) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.Visibility, storagetypes.VISIBILITY_TYPE_PUBLIC_READ) + s.Require().Equal(queryHeadBucketResponse.BucketInfo.SourceType, storagetypes.SOURCE_TYPE_ORIGIN) + + // CreateObject + objectName := "test/" + storageutil.GenRandomObjectName() + // create test buffer + var buffer bytes.Buffer + line := `1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890, + 1234567890,1234567890,1234567890,123` + // Create 1MiB content where each line contains 1024 characters. + for i := 0; i < 1024; i++ { + buffer.WriteString(fmt.Sprintf("[%05d] %s\n", i, line)) + } + payloadSize := buffer.Len() + checksum := sdk.Keccak256(buffer.Bytes()) + expectChecksum := [][]byte{checksum, checksum, checksum, checksum, checksum, checksum, checksum} + contextType := "text/event-stream" + msgCreateObject := storagetypes.NewMsgCreateObject(user[0].GetAddr(), bucketName, objectName, uint64(payloadSize), storagetypes.VISIBILITY_TYPE_PUBLIC_READ, expectChecksum, contextType, storagetypes.REDUNDANCY_EC_TYPE, math.MaxUint, nil) + msgCreateObject.PrimarySpApproval.Sig, err = sp.ApprovalKey.Sign(msgCreateObject.GetApprovalBytes()) + s.Require().NoError(err) + s.T().Logf("Message: %s", msgCreateObject.String()) + + time.Sleep(3 * time.Second) + s.SendTxBlock(user[0], msgCreateObject) + + time.Sleep(3 * time.Second) + // Put object policy + statement := &types.Statement{ + Actions: []types.ActionType{types.ACTION_GET_OBJECT}, + Effect: types.EFFECT_ALLOW, + } + principal := types.NewPrincipalWithAccount(user[1].GetAddr()) + msgPutPolicy := storagetypes.NewMsgPutPolicy(user[0].GetAddr(), types2.NewObjectGRN(bucketName, objectName).String(), + principal, []*types.Statement{statement}, nil) + s.SendTxBlock(user[0], msgPutPolicy) + +} diff --git a/types/grn.go b/types/grn.go index 73d43c380..dec35ad7c 100644 --- a/types/grn.go +++ b/types/grn.go @@ -192,16 +192,21 @@ func (r *GRN) ParseFromString(res string, wildcards bool) error { func (r *GRN) parseBucketAndObjectName(name string) (string, string, error) { nameArr := strings.Split(name, "/") - if len(nameArr) != 2 { + if len(nameArr) < 2 { return "", "", gnfderrors.ErrInvalidGRN.Wrapf("expect bucketName/object, actual %s", r.name) } - err := s3util.CheckValidBucketName(nameArr[0]) + bucketName := nameArr[0] + objectName, found := strings.CutPrefix(name, bucketName+"/") + if !found { + return "", "", gnfderrors.ErrInvalidGRN.Wrapf("object name not found, grn: %s", name) + } + err := s3util.CheckValidBucketName(bucketName) if err != nil { return "", "", gnfderrors.ErrInvalidGRN.Wrapf("invalid bucketName, err: %s", err) } - err = s3util.CheckValidObjectName(nameArr[1]) + err = s3util.CheckValidObjectName(objectName) if err != nil { return "", "", gnfderrors.ErrInvalidGRN.Wrapf("invalid objectName, err: %s", err) } - return nameArr[0], nameArr[1], nil + return bucketName, objectName, nil } diff --git a/types/grn_test.go b/types/grn_test.go index 9ff5a319d..f85fd1e9d 100644 --- a/types/grn_test.go +++ b/types/grn_test.go @@ -91,3 +91,14 @@ func TestGRNBasicNew(t *testing.T) { groupGRNString := "grn:g:" + ownerAcc.String() + ":testgroup" require.Equal(t, groupGRNString, types3.NewGroupGRN(ownerAcc, "testgroup").String()) } + +func TestGRNWithSlash(t *testing.T) { + var grn types3.GRN + + err := grn.ParseFromString("grn:o::"+"testbucket"+"/"+"test/object", false) + require.NoError(t, err) + require.Equal(t, grn.ResourceType(), resource.RESOURCE_TYPE_OBJECT) + bucketName, objectName := grn.MustGetBucketAndObjectName() + require.Equal(t, bucketName, "testbucket") + require.Equal(t, objectName, "test/object") +}