github.com/cs3org/reva/v2@v2.27.7/internal/grpc/services/publicshareprovider/publicshareprovider_test.go (about)

     1  package publicshareprovider_test
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
     8  	userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
     9  	permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1"
    10  	rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
    11  	link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
    12  	providerpb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    13  	"github.com/cs3org/reva/v2/internal/grpc/services/publicshareprovider"
    14  	ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
    15  	"github.com/cs3org/reva/v2/pkg/errtypes"
    16  	"github.com/cs3org/reva/v2/pkg/permission"
    17  	"github.com/cs3org/reva/v2/pkg/publicshare"
    18  	"github.com/cs3org/reva/v2/pkg/publicshare/manager/registry"
    19  	"github.com/cs3org/reva/v2/pkg/publicshare/mocks"
    20  	"github.com/cs3org/reva/v2/pkg/rgrpc/status"
    21  	"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
    22  	"github.com/cs3org/reva/v2/pkg/utils"
    23  	cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  	"github.com/pkg/errors"
    27  	"github.com/stretchr/testify/mock"
    28  	"google.golang.org/grpc"
    29  )
    30  
    31  func createPublicShareProvider(revaConfig map[string]interface{}, gs pool.Selectable[gateway.GatewayAPIClient], sm publicshare.Manager) (link.LinkAPIServer, error) {
    32  	config, err := publicshareprovider.ParseConfig(revaConfig)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	passwordPolicy, err := publicshareprovider.ParsePasswordPolicy(config.PasswordPolicy)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	publicshareproviderService, err := publicshareprovider.New(gs, sm, config, passwordPolicy)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	return publicshareproviderService.(link.LinkAPIServer), nil
    45  }
    46  
    47  var _ = Describe("PublicShareProvider", func() {
    48  	// declare in container nodes
    49  	var (
    50  		ctx                     context.Context
    51  		checkPermissionResponse *permissions.CheckPermissionResponse
    52  		statResourceResponse    *providerpb.StatResponse
    53  		provider                link.LinkAPIServer
    54  		manager                 *mocks.Manager
    55  		gatewayClient           *cs3mocks.GatewayAPIClient
    56  		gatewaySelector         pool.Selectable[gateway.GatewayAPIClient]
    57  		resourcePermissions     *providerpb.ResourcePermissions
    58  		linkPermissions         *providerpb.ResourcePermissions
    59  		createdLink             *link.PublicShare
    60  		revaConfig              map[string]interface{}
    61  		user                    *userpb.User
    62  	)
    63  
    64  	BeforeEach(func() {
    65  		// initialize in setup nodes
    66  		manager = mocks.NewManager(GinkgoT())
    67  
    68  		registry.Register("mockManager", func(m map[string]interface{}) (publicshare.Manager, error) {
    69  			return manager, nil
    70  		})
    71  
    72  		pool.RemoveSelector("GatewaySelector" + "any")
    73  		gatewayClient = cs3mocks.NewGatewayAPIClient(GinkgoT())
    74  		gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient](
    75  			"GatewaySelector",
    76  			"any",
    77  			func(cc grpc.ClientConnInterface) gateway.GatewayAPIClient {
    78  				return gatewayClient
    79  			},
    80  		)
    81  
    82  		checkPermissionResponse = &permissions.CheckPermissionResponse{
    83  			Status: status.NewOK(ctx),
    84  		}
    85  
    86  		user = &userpb.User{
    87  			Id: &userpb.UserId{
    88  				OpaqueId: "alice",
    89  			},
    90  			Username: "alice",
    91  		}
    92  		ctx = ctxpkg.ContextSetUser(context.Background(), user)
    93  
    94  		resourcePermissions = &providerpb.ResourcePermissions{
    95  			// all permissions
    96  			AddGrant:             true,
    97  			CreateContainer:      true,
    98  			Delete:               true,
    99  			GetPath:              true,
   100  			GetQuota:             true,
   101  			InitiateFileDownload: true,
   102  			InitiateFileUpload:   true,
   103  			ListContainer:        true,
   104  			ListFileVersions:     true,
   105  			ListGrants:           true,
   106  			ListRecycle:          true,
   107  			Move:                 true,
   108  			PurgeRecycle:         true,
   109  			RemoveGrant:          true,
   110  			RestoreFileVersion:   true,
   111  			RestoreRecycleItem:   true,
   112  			Stat:                 true,
   113  			UpdateGrant:          true,
   114  			DenyGrant:            true,
   115  		}
   116  
   117  		statResourceResponse = &providerpb.StatResponse{
   118  			Status: status.NewOK(ctx),
   119  			Info: &providerpb.ResourceInfo{
   120  				Type:          providerpb.ResourceType_RESOURCE_TYPE_FILE,
   121  				Path:          "./file.txt",
   122  				PermissionSet: resourcePermissions,
   123  			},
   124  		}
   125  
   126  		linkPermissions = &providerpb.ResourcePermissions{
   127  			Stat:                 true,
   128  			CreateContainer:      true,
   129  			Delete:               true,
   130  			GetPath:              true,
   131  			InitiateFileDownload: true,
   132  			InitiateFileUpload:   true,
   133  		}
   134  
   135  		revaConfig = map[string]interface{}{
   136  			"driver": "mockManager",
   137  			"drivers": map[string]map[string]interface{}{
   138  				"jsoncs3": {
   139  					"provider_addr":                 "com.owncloud.api.storage-system",
   140  					"service_user_idp":              "internal",
   141  					"enable_expired_shares_cleanup": true,
   142  					"gateway_addr":                  "https://localhost:9200",
   143  				},
   144  			},
   145  			"gateway_addr":                       "https://localhost:9200",
   146  			"allowed_paths_for_shares":           []string{"/NewFolder"},
   147  			"writeable_share_must_have_password": false,
   148  			"public_share_must_have_password":    true,
   149  			"password_policy": map[string]interface{}{
   150  				"min_digits":               1,
   151  				"min_characters":           8,
   152  				"min_lowercase_characters": 1,
   153  				"min_uppercase_characters": 1,
   154  				"min_special_characters":   1,
   155  				"banned_passwords_list": map[string]struct{}{
   156  					"SecretPassword1!": {},
   157  				},
   158  			},
   159  		}
   160  		var err error
   161  		provider, err = createPublicShareProvider(revaConfig, gatewaySelector, manager)
   162  		Expect(err).ToNot(HaveOccurred())
   163  		Expect(provider).ToNot(BeNil())
   164  	})
   165  	Describe("Creating a PublicShare", func() {
   166  		BeforeEach(func() {
   167  			gatewayClient.
   168  				EXPECT().
   169  				CheckPermission(
   170  					mock.Anything,
   171  					mock.Anything,
   172  				).
   173  				Return(checkPermissionResponse, nil)
   174  
   175  			gatewayClient.
   176  				EXPECT().
   177  				Stat(mock.Anything, mock.Anything).
   178  				Return(statResourceResponse, nil)
   179  
   180  			createdLink = &link.PublicShare{
   181  				PasswordProtected: true,
   182  				Permissions: &link.PublicSharePermissions{
   183  					Permissions: linkPermissions,
   184  				},
   185  				Creator: user.Id,
   186  			}
   187  		})
   188  		It("creates a public share with password", func() {
   189  			manager.
   190  				EXPECT().
   191  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   192  				Return(createdLink, nil)
   193  
   194  			req := &link.CreatePublicShareRequest{
   195  				ResourceInfo: &providerpb.ResourceInfo{
   196  					Owner: &userpb.UserId{
   197  						OpaqueId: "alice",
   198  					},
   199  					Path: "./NewFolder/file.txt",
   200  				},
   201  				Grant: &link.Grant{
   202  					Permissions: &link.PublicSharePermissions{
   203  						Permissions: linkPermissions,
   204  					},
   205  					Password: "SecretPassw0rd!",
   206  				},
   207  				Description: "test",
   208  			}
   209  
   210  			res, err := provider.CreatePublicShare(ctx, req)
   211  			Expect(err).ToNot(HaveOccurred())
   212  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   213  			Expect(res.GetShare()).To(Equal(createdLink))
   214  		})
   215  		It("has no user permission to create public share", func() {
   216  			gatewayClient.
   217  				EXPECT().
   218  				CheckPermission(mock.Anything, mock.Anything).
   219  				Unset()
   220  			checkPermissionResponse = &permissions.CheckPermissionResponse{
   221  				Status: status.NewPermissionDenied(ctx, nil, "permission denied"),
   222  			}
   223  			gatewayClient.
   224  				EXPECT().
   225  				CheckPermission(mock.Anything, mock.Anything).
   226  				Return(checkPermissionResponse, nil)
   227  
   228  			req := &link.CreatePublicShareRequest{}
   229  
   230  			res, err := provider.CreatePublicShare(ctx, req)
   231  			Expect(err).ToNot(HaveOccurred())
   232  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED))
   233  			Expect(res.GetStatus().GetMessage()).To(Equal("no permission to create public links"))
   234  		})
   235  		It("has permission to create internal link", func() {
   236  			// internal links are created with empty permissions
   237  			linkPermissions := &providerpb.ResourcePermissions{}
   238  			manager.
   239  				EXPECT().
   240  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   241  				Return(createdLink, nil)
   242  			// internal link creation should not check user permissions
   243  			gatewayClient.EXPECT().CheckPermission(mock.Anything, mock.Anything).Unset()
   244  
   245  			req := &link.CreatePublicShareRequest{
   246  				ResourceInfo: &providerpb.ResourceInfo{
   247  					Owner: &userpb.UserId{
   248  						OpaqueId: "alice",
   249  					},
   250  					Path: "./NewFolder/file.txt",
   251  				},
   252  				Grant: &link.Grant{
   253  					Permissions: &link.PublicSharePermissions{
   254  						Permissions: linkPermissions,
   255  					},
   256  				},
   257  				Description: "test",
   258  			}
   259  
   260  			res, err := provider.CreatePublicShare(ctx, req)
   261  			Expect(err).ToNot(HaveOccurred())
   262  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   263  			Expect(res.GetShare()).To(Equal(createdLink))
   264  		})
   265  		It("has no share permission on the resource, can create internal link", func() {
   266  			// internal links are created with empty permissions
   267  			linkPermissions := &providerpb.ResourcePermissions{}
   268  			manager.
   269  				EXPECT().
   270  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   271  				Return(createdLink, nil)
   272  
   273  			// internal link creation should not check user permissions
   274  			gatewayClient.EXPECT().CheckPermission(mock.Anything, mock.Anything).Unset()
   275  
   276  			// downgrade user permissions on resource to have no share permission
   277  			resourcePermissions.AddGrant = false
   278  
   279  			req := &link.CreatePublicShareRequest{
   280  				ResourceInfo: &providerpb.ResourceInfo{
   281  					Owner: &userpb.UserId{
   282  						OpaqueId: "alice",
   283  					},
   284  					Path: "./NewFolder/file.txt",
   285  				},
   286  				Grant: &link.Grant{
   287  					Permissions: &link.PublicSharePermissions{
   288  						Permissions: linkPermissions,
   289  					},
   290  				},
   291  				Description: "test",
   292  			}
   293  
   294  			res, err := provider.CreatePublicShare(ctx, req)
   295  			Expect(err).ToNot(HaveOccurred())
   296  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   297  			Expect(res.GetShare()).To(Equal(createdLink))
   298  		})
   299  		It("fails to check create public share user permission", func() {
   300  			gatewayClient.EXPECT().CheckPermission(mock.Anything, mock.Anything).Unset()
   301  			gatewayClient.
   302  				EXPECT().
   303  				CheckPermission(mock.Anything, mock.Anything).
   304  				Return(nil, errors.New("transport error"))
   305  
   306  			req := &link.CreatePublicShareRequest{}
   307  
   308  			res, err := provider.CreatePublicShare(ctx, req)
   309  			Expect(err).To(HaveOccurred())
   310  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
   311  			Expect(res.GetStatus().GetMessage()).To(Equal("failed check user permission to write public link"))
   312  		})
   313  		It("has no share permission on the resource", func() {
   314  			req := &link.CreatePublicShareRequest{}
   315  
   316  			// downgrade user permissions to have no share permission
   317  			resourcePermissions.AddGrant = false
   318  
   319  			res, err := provider.CreatePublicShare(ctx, req)
   320  			Expect(err).ToNot(HaveOccurred())
   321  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
   322  			Expect(res.GetStatus().GetMessage()).To(Equal("no share permission"))
   323  		})
   324  		It("tries to share with higher permissions than granted on the resource", func() {
   325  			// set resource permissions lower than the requested share permissions
   326  			resourcePermissions.Delete = false
   327  
   328  			req := &link.CreatePublicShareRequest{
   329  				Grant: &link.Grant{
   330  					Permissions: &link.PublicSharePermissions{
   331  						Permissions: linkPermissions,
   332  					},
   333  				},
   334  			}
   335  
   336  			res, err := provider.CreatePublicShare(ctx, req)
   337  			Expect(err).ToNot(HaveOccurred())
   338  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
   339  			Expect(res.GetStatus().GetMessage()).To(Equal("insufficient permissions to create that kind of share"))
   340  		})
   341  		It("tries to share inside a path which is not allowed", func() {
   342  			req := &link.CreatePublicShareRequest{
   343  				ResourceInfo: &providerpb.ResourceInfo{
   344  					Owner: &userpb.UserId{
   345  						OpaqueId: "alice",
   346  					},
   347  					Path: "./file.txt",
   348  				},
   349  				Grant: &link.Grant{
   350  					Permissions: &link.PublicSharePermissions{
   351  						Permissions: linkPermissions,
   352  					},
   353  				},
   354  			}
   355  
   356  			res, err := provider.CreatePublicShare(ctx, req)
   357  			Expect(err).ToNot(HaveOccurred())
   358  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_FAILED_PRECONDITION))
   359  			Expect(res.GetStatus().GetMessage()).To(Equal("share creation is not allowed for the specified path"))
   360  		})
   361  		It("tries to share personal space root", func() {
   362  			req := &link.CreatePublicShareRequest{
   363  				ResourceInfo: &providerpb.ResourceInfo{
   364  					Owner: &userpb.UserId{
   365  						OpaqueId: "alice",
   366  					},
   367  					Path: "./NewFolder/file.txt",
   368  					Id: &providerpb.ResourceId{
   369  						StorageId: "storage-id",
   370  						OpaqueId:  "admin-id",
   371  						SpaceId:   "admin-id",
   372  					},
   373  					Space: &providerpb.StorageSpace{SpaceType: "personal"},
   374  				},
   375  				Grant: &link.Grant{
   376  					Permissions: &link.PublicSharePermissions{
   377  						Permissions: linkPermissions,
   378  					},
   379  				},
   380  			}
   381  
   382  			res, err := provider.CreatePublicShare(ctx, req)
   383  			Expect(err).ToNot(HaveOccurred())
   384  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
   385  			Expect(res.GetStatus().GetMessage()).To(Equal("cannot create link on personal space root"))
   386  		})
   387  		It("tries to share a project space root", func() {
   388  			manager.EXPECT().
   389  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   390  				Return(createdLink, nil)
   391  
   392  			req := &link.CreatePublicShareRequest{
   393  				ResourceInfo: &providerpb.ResourceInfo{
   394  					Owner: &userpb.UserId{
   395  						OpaqueId: "alice",
   396  					},
   397  					Path: "./NewFolder/file.txt",
   398  					Id: &providerpb.ResourceId{
   399  						StorageId: "storage-id",
   400  						OpaqueId:  "project-id",
   401  						SpaceId:   "project-id",
   402  					},
   403  					Space: &providerpb.StorageSpace{SpaceType: "project"},
   404  				},
   405  				Grant: &link.Grant{
   406  					Permissions: &link.PublicSharePermissions{
   407  						Permissions: linkPermissions,
   408  					},
   409  					Password: "SecretPassw0rd!",
   410  				},
   411  			}
   412  
   413  			res, err := provider.CreatePublicShare(ctx, req)
   414  			Expect(err).ToNot(HaveOccurred())
   415  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   416  			Expect(res.GetShare()).To(Equal(createdLink))
   417  		})
   418  		It("creates a new quicklink", func() {
   419  			createdLink.Quicklink = true
   420  			manager.EXPECT().
   421  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   422  				Return(createdLink, nil)
   423  
   424  			// no existing quicklinks
   425  			var links = []*link.PublicShare{}
   426  			manager.EXPECT().ListPublicShares(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   427  				Return(links, nil)
   428  
   429  			req := &link.CreatePublicShareRequest{
   430  				ResourceInfo: &providerpb.ResourceInfo{
   431  					Owner: &userpb.UserId{
   432  						OpaqueId: "alice",
   433  					},
   434  					ArbitraryMetadata: &providerpb.ArbitraryMetadata{Metadata: map[string]string{"quicklink": "true"}},
   435  					Path:              "./NewFolder/file.txt",
   436  				},
   437  				Grant: &link.Grant{
   438  					Permissions: &link.PublicSharePermissions{
   439  						Permissions: linkPermissions,
   440  					},
   441  					Password: "SecretPassw0rd!",
   442  				},
   443  			}
   444  
   445  			res, err := provider.CreatePublicShare(ctx, req)
   446  			Expect(err).ToNot(HaveOccurred())
   447  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   448  			Expect(res.GetShare()).To(Equal(createdLink))
   449  		})
   450  		It("creates a quicklink which already exists", func() {
   451  			// create a quicklink with viewer permissions
   452  			// there is already a quicklink present for that resource
   453  			// instead of creating a new quicklink, we return the existing quicklink without updating it
   454  			existingLink := &link.PublicShare{
   455  				PasswordProtected: true,
   456  				Permissions: &link.PublicSharePermissions{
   457  					Permissions: linkPermissions,
   458  				},
   459  				Quicklink:   true,
   460  				Description: "Quicklink",
   461  			}
   462  			var links = []*link.PublicShare{}
   463  			links = append(links, existingLink)
   464  
   465  			// confirm that list public shares is called with the correct filters
   466  			manager.
   467  				EXPECT().
   468  				ListPublicShares(
   469  					mock.Anything,
   470  					mock.Anything,
   471  					mock.MatchedBy(func(filters []*link.ListPublicSharesRequest_Filter) bool {
   472  						return filters[0].Type == link.ListPublicSharesRequest_Filter_TYPE_RESOURCE_ID &&
   473  							filters[0].GetResourceId().GetOpaqueId() == "project-id" &&
   474  							filters[0].GetResourceId().GetStorageId() == "storage-id" &&
   475  							filters[0].GetResourceId().GetSpaceId() == "project-id"
   476  					}),
   477  					mock.Anything).
   478  				Return(links, nil)
   479  
   480  			req := &link.CreatePublicShareRequest{
   481  				ResourceInfo: &providerpb.ResourceInfo{
   482  					Owner: &userpb.UserId{
   483  						OpaqueId: "alice",
   484  					},
   485  					// this should create a quicklink
   486  					ArbitraryMetadata: &providerpb.ArbitraryMetadata{Metadata: map[string]string{"quicklink": "true"}},
   487  					Path:              "./NewFolder/file.txt",
   488  					Id: &providerpb.ResourceId{
   489  						StorageId: "storage-id",
   490  						OpaqueId:  "project-id",
   491  						SpaceId:   "project-id",
   492  					},
   493  					Space: &providerpb.StorageSpace{SpaceType: "project"},
   494  				},
   495  				Grant: &link.Grant{
   496  					Permissions: &link.PublicSharePermissions{
   497  						Permissions: &providerpb.ResourcePermissions{
   498  							Stat:                 true,
   499  							InitiateFileDownload: true,
   500  							ListContainer:        true,
   501  						},
   502  					},
   503  					Password: "SecretPassw0rd!",
   504  				},
   505  			}
   506  
   507  			res, err := provider.CreatePublicShare(ctx, req)
   508  			Expect(err).ToNot(HaveOccurred())
   509  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   510  			Expect(res.GetShare()).To(Equal(existingLink))
   511  		})
   512  		It("create public share with expiration date in the past", func() {
   513  			yesterday := time.Now().AddDate(0, 0, -1)
   514  			req := &link.CreatePublicShareRequest{
   515  				ResourceInfo: &providerpb.ResourceInfo{
   516  					Owner: &userpb.UserId{
   517  						OpaqueId: "alice",
   518  					},
   519  					Path: "./NewFolder/file.txt",
   520  				},
   521  				Grant: &link.Grant{
   522  					Permissions: &link.PublicSharePermissions{
   523  						Permissions: linkPermissions,
   524  					},
   525  					Expiration: utils.TimeToTS(yesterday),
   526  				},
   527  			}
   528  
   529  			res, err := provider.CreatePublicShare(ctx, req)
   530  			Expect(err).ToNot(HaveOccurred())
   531  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
   532  			Expect(res.GetStatus().GetMessage()).To(ContainSubstring("expiration date is in the past"))
   533  		})
   534  		It("create public share with valid expiration date", func() {
   535  			tomorrow := time.Now().AddDate(0, 0, 1)
   536  			tsTomorrow := utils.TimeToTS(tomorrow)
   537  
   538  			createdLink.Expiration = tsTomorrow
   539  			manager.
   540  				EXPECT().
   541  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   542  				Return(createdLink, nil)
   543  
   544  			req := &link.CreatePublicShareRequest{
   545  				ResourceInfo: &providerpb.ResourceInfo{
   546  					Owner: &userpb.UserId{
   547  						OpaqueId: "alice",
   548  					},
   549  					Path: "./NewFolder/file.txt",
   550  				},
   551  				Grant: &link.Grant{
   552  					Permissions: &link.PublicSharePermissions{
   553  						Permissions: linkPermissions,
   554  					},
   555  					Expiration: tsTomorrow,
   556  					Password:   "SecretPassw0rd!",
   557  				},
   558  			}
   559  
   560  			res, err := provider.CreatePublicShare(ctx, req)
   561  			Expect(err).ToNot(HaveOccurred())
   562  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   563  			Expect(res.GetShare()).To(Equal(createdLink))
   564  		})
   565  		It("creates a public share without a password", func() {
   566  			req := &link.CreatePublicShareRequest{
   567  				ResourceInfo: &providerpb.ResourceInfo{
   568  					Owner: &userpb.UserId{
   569  						OpaqueId: "alice",
   570  					},
   571  					Path: "./NewFolder/file.txt",
   572  				},
   573  				Grant: &link.Grant{
   574  					Permissions: &link.PublicSharePermissions{
   575  						Permissions: linkPermissions,
   576  					},
   577  				},
   578  			}
   579  
   580  			res, err := provider.CreatePublicShare(ctx, req)
   581  			Expect(err).ToNot(HaveOccurred())
   582  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
   583  			Expect(res.GetStatus().GetMessage()).To(Equal("password protection is enforced"))
   584  		})
   585  		It("creates a viewable public share without a password", func() {
   586  			// set password enforcement only on writeable shares
   587  			revaConfig["public_share_must_have_password"] = false
   588  			revaConfig["writeable_share_must_have_password"] = true
   589  
   590  			provider, err := createPublicShareProvider(revaConfig, gatewaySelector, manager)
   591  			Expect(err).ToNot(HaveOccurred())
   592  			Expect(provider).ToNot(BeNil())
   593  
   594  			linkPermissions = &providerpb.ResourcePermissions{
   595  				Stat:                 true,
   596  				ListContainer:        true,
   597  				InitiateFileDownload: true,
   598  			}
   599  			createdLink.PasswordProtected = false
   600  			manager.
   601  				EXPECT().
   602  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   603  				Return(createdLink, nil)
   604  
   605  			req := &link.CreatePublicShareRequest{
   606  				ResourceInfo: &providerpb.ResourceInfo{
   607  					Owner: &userpb.UserId{
   608  						OpaqueId: "alice",
   609  					},
   610  					Path: "./NewFolder/file.txt",
   611  				},
   612  				Grant: &link.Grant{
   613  					Permissions: &link.PublicSharePermissions{
   614  						Permissions: linkPermissions,
   615  					},
   616  				},
   617  			}
   618  
   619  			res, err := provider.CreatePublicShare(ctx, req)
   620  			Expect(err).ToNot(HaveOccurred())
   621  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   622  			Expect(res.GetShare()).To(Equal(createdLink))
   623  		})
   624  		It("creates an editable public share without a password", func() {
   625  			// set password enforcement to false on all public shares
   626  			revaConfig["public_share_must_have_password"] = false
   627  			revaConfig["writeable_share_must_have_password"] = false
   628  
   629  			provider, err := createPublicShareProvider(revaConfig, gatewaySelector, manager)
   630  			Expect(err).ToNot(HaveOccurred())
   631  			Expect(provider).ToNot(BeNil())
   632  
   633  			linkPermissions = &providerpb.ResourcePermissions{
   634  				Stat:                 true,
   635  				ListContainer:        true,
   636  				InitiateFileDownload: true,
   637  				InitiateFileUpload:   true,
   638  				CreateContainer:      true,
   639  				Delete:               true,
   640  				Move:                 true,
   641  			}
   642  			createdLink.PasswordProtected = false
   643  			manager.
   644  				EXPECT().
   645  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   646  				Return(createdLink, nil)
   647  
   648  			req := &link.CreatePublicShareRequest{
   649  				ResourceInfo: &providerpb.ResourceInfo{
   650  					Owner: &userpb.UserId{
   651  						OpaqueId: "alice",
   652  					},
   653  					Path: "./NewFolder/file.txt",
   654  				},
   655  				Grant: &link.Grant{
   656  					Permissions: &link.PublicSharePermissions{
   657  						Permissions: linkPermissions,
   658  					},
   659  				},
   660  			}
   661  
   662  			res, err := provider.CreatePublicShare(ctx, req)
   663  			Expect(err).ToNot(HaveOccurred())
   664  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   665  			Expect(res.GetShare()).To(Equal(createdLink))
   666  		})
   667  		It("applies the password policy even if no enforcement is configured", func() {
   668  			// set password enforcement to false on all public shares
   669  			revaConfig["public_share_must_have_password"] = false
   670  			revaConfig["writeable_share_must_have_password"] = false
   671  
   672  			provider, err := createPublicShareProvider(revaConfig, gatewaySelector, manager)
   673  			Expect(err).ToNot(HaveOccurred())
   674  			Expect(provider).ToNot(BeNil())
   675  
   676  			linkPermissions = &providerpb.ResourcePermissions{
   677  				Stat:                 true,
   678  				ListContainer:        true,
   679  				InitiateFileDownload: true,
   680  				InitiateFileUpload:   true,
   681  				CreateContainer:      true,
   682  				Delete:               true,
   683  				Move:                 true,
   684  			}
   685  
   686  			req := &link.CreatePublicShareRequest{
   687  				ResourceInfo: &providerpb.ResourceInfo{
   688  					Owner: &userpb.UserId{
   689  						OpaqueId: "alice",
   690  					},
   691  					Path: "./NewFolder/file.txt",
   692  				},
   693  				Grant: &link.Grant{
   694  					Permissions: &link.PublicSharePermissions{
   695  						Permissions: linkPermissions,
   696  					},
   697  					Password: "SecretPassword1!",
   698  				},
   699  			}
   700  
   701  			res, err := provider.CreatePublicShare(ctx, req)
   702  			Expect(err).ToNot(HaveOccurred())
   703  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
   704  			Expect(res.GetStatus().GetMessage()).To(Equal("unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety"))
   705  		})
   706  		It("returns internal server error when share manager not functional", func() {
   707  			manager.
   708  				EXPECT().
   709  				CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   710  				Return(nil, errors.New("transport error"))
   711  
   712  			req := &link.CreatePublicShareRequest{
   713  				ResourceInfo: &providerpb.ResourceInfo{
   714  					Owner: &userpb.UserId{
   715  						OpaqueId: "alice",
   716  					},
   717  					Path: "./NewFolder/file.txt",
   718  				},
   719  				Grant: &link.Grant{
   720  					Permissions: &link.PublicSharePermissions{
   721  						Permissions: linkPermissions,
   722  					},
   723  					Password: "SecretPassw0rd123!",
   724  				},
   725  			}
   726  
   727  			res, err := provider.CreatePublicShare(ctx, req)
   728  			Expect(err).ToNot(HaveOccurred())
   729  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
   730  			Expect(res.GetStatus().GetMessage()).To(Equal("error persisting public share:transport error"))
   731  		})
   732  	})
   733  	Describe("Removing a PublicShare", func() {
   734  		BeforeEach(func() {
   735  			createdLink.Id = &link.PublicShareId{
   736  				OpaqueId: "share-id",
   737  			}
   738  		})
   739  		It("cannot load existing share", func() {
   740  			manager.
   741  				EXPECT().
   742  				GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   743  				Return(nil, errors.New("transport error"))
   744  
   745  			req := &link.RemovePublicShareRequest{
   746  				Ref: &link.PublicShareReference{
   747  					Spec: &link.PublicShareReference_Id{
   748  						Id: &link.PublicShareId{
   749  							OpaqueId: "share-id",
   750  						},
   751  					},
   752  				},
   753  			}
   754  			res, err := provider.RemovePublicShare(ctx, req)
   755  			Expect(err).To(HaveOccurred())
   756  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
   757  			Expect(res.GetStatus().GetMessage()).To(Equal("error loading public share"))
   758  		})
   759  		It("can remove an existing share as a creator", func() {
   760  			manager.
   761  				EXPECT().
   762  				GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   763  				Once().
   764  				Return(
   765  					createdLink, nil)
   766  
   767  			gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Return(statResourceResponse, nil)
   768  
   769  			manager.
   770  				EXPECT().
   771  				RevokePublicShare(
   772  					mock.Anything,
   773  					mock.MatchedBy(func(callingUser *userpb.User) bool {
   774  						return callingUser == user
   775  					}),
   776  					mock.MatchedBy(func(linkRef *link.PublicShareReference) bool {
   777  						return linkRef.GetId().GetOpaqueId() == "share-id"
   778  					})).
   779  				Once().
   780  				Return(nil)
   781  
   782  			req := &link.RemovePublicShareRequest{
   783  				Ref: &link.PublicShareReference{
   784  					Spec: &link.PublicShareReference_Id{
   785  						Id: &link.PublicShareId{
   786  							OpaqueId: "share-id",
   787  						},
   788  					},
   789  				},
   790  			}
   791  			res, err := provider.RemovePublicShare(ctx, req)
   792  			Expect(err).ToNot(HaveOccurred())
   793  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   794  		})
   795  		It("can remove an existing share as a space manager", func() {
   796  			// link is neither owned nor created by the acting user
   797  			createdLink.Creator = &userpb.UserId{
   798  				OpaqueId: "admin",
   799  			}
   800  			manager.
   801  				EXPECT().
   802  				GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   803  				Once().Return(createdLink, nil)
   804  
   805  			gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Return(statResourceResponse, nil)
   806  
   807  			manager.
   808  				EXPECT().
   809  				RevokePublicShare(
   810  					mock.Anything,
   811  					mock.MatchedBy(
   812  						func(callingUser *userpb.User) bool {
   813  							return callingUser == user
   814  						}),
   815  					mock.MatchedBy(
   816  						func(linkRef *link.PublicShareReference) bool {
   817  							return linkRef.GetId().GetOpaqueId() == "share-id"
   818  						})).
   819  				Once().Return(nil)
   820  
   821  			req := &link.RemovePublicShareRequest{
   822  				Ref: &link.PublicShareReference{
   823  					Spec: &link.PublicShareReference_Id{
   824  						Id: &link.PublicShareId{
   825  							OpaqueId: "share-id",
   826  						},
   827  					},
   828  				},
   829  			}
   830  			res, err := provider.RemovePublicShare(ctx, req)
   831  			Expect(err).ToNot(HaveOccurred())
   832  			Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
   833  		})
   834  		Context("when the user is not the owner or creator", func() {
   835  			BeforeEach(func() {
   836  				// link is neither owned nor created by the acting user
   837  				createdLink.Creator = &userpb.UserId{
   838  					OpaqueId: "admin",
   839  				}
   840  
   841  				// stat the shared resource to get the users resource permissions
   842  				gatewayClient.
   843  					EXPECT().
   844  					Stat(mock.Anything, mock.Anything).
   845  					Return(statResourceResponse, nil)
   846  			})
   847  			It("cannot remove an existing share as a space editor", func() {
   848  				// downgrade user permissions to editor
   849  				resourcePermissions.AddGrant = false
   850  				resourcePermissions.UpdateGrant = false
   851  				resourcePermissions.RemoveGrant = false
   852  
   853  				manager.
   854  					EXPECT().
   855  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   856  					Once().Return(createdLink, nil)
   857  
   858  				req := &link.RemovePublicShareRequest{
   859  					Ref: &link.PublicShareReference{
   860  						Spec: &link.PublicShareReference_Id{
   861  							Id: &link.PublicShareId{
   862  								OpaqueId: "share-id",
   863  							},
   864  						},
   865  					},
   866  				}
   867  				res, err := provider.RemovePublicShare(ctx, req)
   868  				Expect(err).ToNot(HaveOccurred())
   869  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED))
   870  				Expect(res.GetStatus().GetMessage()).To(Equal("no permission to delete public share"))
   871  			})
   872  			It("triggers an internal server error when the share manager is not available", func() {
   873  				manager.
   874  					EXPECT().
   875  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   876  					Once().Return(createdLink, nil)
   877  
   878  				// Share manager is not functional
   879  				By("experiencing a share delete error in the persistence layer")
   880  				manager.EXPECT().RevokePublicShare(mock.Anything, mock.Anything, mock.Anything).
   881  					Once().Return(errors.New("delete error"))
   882  
   883  				req := &link.RemovePublicShareRequest{
   884  					Ref: &link.PublicShareReference{
   885  						Spec: &link.PublicShareReference_Id{
   886  							Id: &link.PublicShareId{
   887  								OpaqueId: "share-id",
   888  							},
   889  						},
   890  					},
   891  				}
   892  				res, err := provider.RemovePublicShare(ctx, req)
   893  				Expect(err).To(HaveOccurred())
   894  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
   895  				Expect(res.GetStatus().GetMessage()).To(Equal("error deleting public share"))
   896  			})
   897  			It("triggers an internal server error when the storage provider is not functional", func() {
   898  				manager.
   899  					EXPECT().
   900  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   901  					Once().Return(createdLink, nil)
   902  
   903  				// Storage Provider is not functional
   904  				By("experiencing a transport error when trying to stat the shared resource")
   905  				gatewayClient.EXPECT().
   906  					Stat(mock.Anything, mock.Anything).Unset()
   907  				gatewayClient.EXPECT().
   908  					Stat(mock.Anything, mock.Anything).
   909  					Return(nil, errors.New("transport error"))
   910  
   911  				req := &link.RemovePublicShareRequest{
   912  					Ref: &link.PublicShareReference{
   913  						Spec: &link.PublicShareReference_Id{
   914  							Id: &link.PublicShareId{
   915  								OpaqueId: "share-id",
   916  							},
   917  						},
   918  					},
   919  				}
   920  				res, err := provider.RemovePublicShare(ctx, req)
   921  				Expect(err).To(HaveOccurred())
   922  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
   923  				Expect(res.GetStatus().GetMessage()).To(Equal("failed to stat shared resource"))
   924  			})
   925  		})
   926  	})
   927  	Describe("Updating a PublicShare", func() {
   928  		var (
   929  			existingLink *link.PublicShare
   930  			updatedLink  *link.PublicShare
   931  		)
   932  
   933  		BeforeEach(func() {
   934  			// stat the shared resource to get the users resource permissions
   935  			gatewayClient.
   936  				EXPECT().
   937  				Stat(mock.Anything, mock.Anything).
   938  				Return(statResourceResponse, nil)
   939  
   940  			existingLink = &link.PublicShare{
   941  				Id: &link.PublicShareId{
   942  					OpaqueId: "share-id",
   943  				},
   944  				Token: "token",
   945  				Permissions: &link.PublicSharePermissions{
   946  					Permissions: &providerpb.ResourcePermissions{
   947  						Stat:                 true,
   948  						ListContainer:        true,
   949  						InitiateFileDownload: true,
   950  						AddGrant:             true,
   951  					},
   952  				},
   953  				Creator: user.GetId(),
   954  			}
   955  		})
   956  		Context("succeeds when the user downgrades a public link to internal", func() {
   957  			BeforeEach(func() {
   958  				linkPermissions = &providerpb.ResourcePermissions{}
   959  				updatedLink = &link.PublicShare{
   960  					Id: &link.PublicShareId{
   961  						OpaqueId: "share-id",
   962  					},
   963  					Permissions: &link.PublicSharePermissions{
   964  						Permissions: linkPermissions,
   965  					},
   966  					DisplayName: "Updated Link",
   967  				}
   968  			})
   969  			It("fails when it cannot load the existing share", func() {
   970  				manager.
   971  					EXPECT().
   972  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   973  					Return(nil, errors.New("transport error"))
   974  
   975  				gatewayClient.
   976  					EXPECT().
   977  					Stat(mock.Anything, mock.Anything).
   978  					Unset()
   979  
   980  				req := &link.UpdatePublicShareRequest{
   981  					Update: &link.UpdatePublicShareRequest_Update{
   982  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
   983  						Grant: &link.Grant{
   984  							Permissions: &link.PublicSharePermissions{
   985  								Permissions: linkPermissions,
   986  							},
   987  						},
   988  					},
   989  				}
   990  
   991  				res, err := provider.UpdatePublicShare(ctx, req)
   992  				Expect(err).To(HaveOccurred())
   993  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
   994  			})
   995  			It("fails when it cannot connect to the storage provider", func() {
   996  				manager.
   997  					EXPECT().
   998  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
   999  					Once().Return(existingLink, nil)
  1000  
  1001  				gatewayClient.
  1002  					EXPECT().
  1003  					Stat(mock.Anything, mock.Anything).
  1004  					Unset()
  1005  				gatewayClient.
  1006  					EXPECT().
  1007  					Stat(mock.Anything, mock.Anything).
  1008  					Return(nil, errors.New("transport error"))
  1009  
  1010  				req := &link.UpdatePublicShareRequest{
  1011  					Update: &link.UpdatePublicShareRequest_Update{
  1012  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1013  						Grant: &link.Grant{
  1014  							Permissions: &link.PublicSharePermissions{
  1015  								Permissions: linkPermissions,
  1016  							},
  1017  						},
  1018  					},
  1019  				}
  1020  
  1021  				res, err := provider.UpdatePublicShare(ctx, req)
  1022  				Expect(err).To(HaveOccurred())
  1023  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
  1024  			})
  1025  			It("fails when it cannot find the shared resource", func() {
  1026  				manager.
  1027  					EXPECT().
  1028  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1029  					Once().Return(existingLink, nil)
  1030  
  1031  				gatewayClient.
  1032  					EXPECT().
  1033  					Stat(mock.Anything, mock.Anything).
  1034  					Unset()
  1035  
  1036  				statResourceResponse.Status = status.NewNotFound(context.TODO(), "not found")
  1037  				statResourceResponse.Info = nil
  1038  				gatewayClient.
  1039  					EXPECT().
  1040  					Stat(mock.Anything, mock.Anything).
  1041  					Return(statResourceResponse, nil)
  1042  
  1043  				req := &link.UpdatePublicShareRequest{
  1044  					Update: &link.UpdatePublicShareRequest_Update{
  1045  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1046  						Grant: &link.Grant{
  1047  							Permissions: &link.PublicSharePermissions{
  1048  								Permissions: linkPermissions,
  1049  							},
  1050  						},
  1051  					},
  1052  				}
  1053  
  1054  				res, err := provider.UpdatePublicShare(ctx, req)
  1055  				Expect(err).ToNot(HaveOccurred())
  1056  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND))
  1057  			})
  1058  			It("fails when it cannot store share information", func() {
  1059  				manager.
  1060  					EXPECT().
  1061  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1062  					Once().Return(existingLink, nil)
  1063  
  1064  				manager.
  1065  					EXPECT().
  1066  					UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything).
  1067  					Once().Return(nil, errors.New("storage error"))
  1068  
  1069  				req := &link.UpdatePublicShareRequest{
  1070  					Update: &link.UpdatePublicShareRequest_Update{
  1071  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1072  						Grant: &link.Grant{
  1073  							Permissions: &link.PublicSharePermissions{
  1074  								Permissions: linkPermissions,
  1075  							},
  1076  						},
  1077  					},
  1078  				}
  1079  
  1080  				res, err := provider.UpdatePublicShare(ctx, req)
  1081  				Expect(err).ToNot(HaveOccurred())
  1082  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
  1083  				Expect(res.GetStatus().GetMessage()).To(Equal("storage error"))
  1084  			})
  1085  			It("fails when the user is neither the creator nor the owner of the share", func() {
  1086  				existingLink.Creator = &userpb.UserId{
  1087  					OpaqueId: "admin",
  1088  				}
  1089  				manager.
  1090  					EXPECT().
  1091  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1092  					Once().Return(existingLink, nil)
  1093  
  1094  				checkPermissionResponse.Status.Code = rpc.Code_CODE_PERMISSION_DENIED
  1095  				gatewayClient.
  1096  					EXPECT().
  1097  					CheckPermission(mock.Anything, mock.Anything).
  1098  					Return(checkPermissionResponse, nil)
  1099  
  1100  				gatewayClient.
  1101  					EXPECT().
  1102  					Stat(mock.Anything, mock.Anything).
  1103  					Unset()
  1104  
  1105  				req := &link.UpdatePublicShareRequest{
  1106  					Update: &link.UpdatePublicShareRequest_Update{
  1107  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1108  						Grant: &link.Grant{
  1109  							Permissions: &link.PublicSharePermissions{
  1110  								Permissions: linkPermissions,
  1111  							},
  1112  						},
  1113  					},
  1114  
  1115  					Ref: &link.PublicShareReference{
  1116  						Spec: &link.PublicShareReference_Id{
  1117  							Id: &link.PublicShareId{
  1118  								OpaqueId: "share-id",
  1119  							},
  1120  						},
  1121  					},
  1122  				}
  1123  
  1124  				res, err := provider.UpdatePublicShare(ctx, req)
  1125  				Expect(err).ToNot(HaveOccurred())
  1126  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED))
  1127  
  1128  			})
  1129  			It("fails when user is neither the resource owner nor the share creator", func() {
  1130  				existingLink.Creator = &userpb.UserId{
  1131  					OpaqueId: "admin",
  1132  				}
  1133  				manager.
  1134  					EXPECT().
  1135  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1136  					Once().Return(existingLink, nil)
  1137  
  1138  				checkPermissionResponse.Status.Code = rpc.Code_CODE_PERMISSION_DENIED
  1139  				gatewayClient.
  1140  					EXPECT().
  1141  					CheckPermission(mock.Anything, mock.Anything).
  1142  					Return(checkPermissionResponse, nil)
  1143  
  1144  				gatewayClient.
  1145  					EXPECT().
  1146  					Stat(mock.Anything, mock.Anything).
  1147  					Unset()
  1148  
  1149  				linkPermissions.Delete = true
  1150  				req := &link.UpdatePublicShareRequest{
  1151  					Update: &link.UpdatePublicShareRequest_Update{
  1152  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1153  						Grant: &link.Grant{
  1154  							Permissions: &link.PublicSharePermissions{
  1155  								Permissions: linkPermissions,
  1156  							},
  1157  						},
  1158  					},
  1159  
  1160  					Ref: &link.PublicShareReference{
  1161  						Spec: &link.PublicShareReference_Id{
  1162  							Id: &link.PublicShareId{
  1163  								OpaqueId: "share-id",
  1164  							},
  1165  						},
  1166  					},
  1167  				}
  1168  
  1169  				res, err := provider.UpdatePublicShare(ctx, req)
  1170  				Expect(err).ToNot(HaveOccurred())
  1171  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED))
  1172  
  1173  			})
  1174  			It("succeeds", func() {
  1175  				manager.
  1176  					EXPECT().
  1177  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1178  					Once().Return(existingLink, nil)
  1179  
  1180  				manager.
  1181  					EXPECT().
  1182  					UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything).
  1183  					Once().Return(updatedLink, nil)
  1184  
  1185  				req := &link.UpdatePublicShareRequest{
  1186  					Update: &link.UpdatePublicShareRequest_Update{
  1187  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1188  						Grant: &link.Grant{
  1189  							Permissions: &link.PublicSharePermissions{
  1190  								Permissions: linkPermissions,
  1191  							},
  1192  						},
  1193  					},
  1194  
  1195  					Ref: &link.PublicShareReference{
  1196  						Spec: &link.PublicShareReference_Id{
  1197  							Id: &link.PublicShareId{
  1198  								OpaqueId: "share-id",
  1199  							},
  1200  						},
  1201  					},
  1202  				}
  1203  
  1204  				res, err := provider.UpdatePublicShare(ctx, req)
  1205  				Expect(err).ToNot(HaveOccurred())
  1206  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
  1207  				Expect(res.GetShare()).To(Equal(updatedLink))
  1208  			})
  1209  			It("succeeds even if the user is no manager or owner on the resource", func() {
  1210  				manager.
  1211  					EXPECT().
  1212  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1213  					Once().Return(existingLink, nil)
  1214  
  1215  				manager.
  1216  					EXPECT().
  1217  					UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything).
  1218  					Once().Return(updatedLink, nil)
  1219  
  1220  				statResourceResponse.Info.PermissionSet.UpdateGrant = false
  1221  
  1222  				req := &link.UpdatePublicShareRequest{
  1223  					Update: &link.UpdatePublicShareRequest_Update{
  1224  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1225  						Grant: &link.Grant{
  1226  							Permissions: &link.PublicSharePermissions{
  1227  								Permissions: linkPermissions,
  1228  							},
  1229  						},
  1230  					},
  1231  
  1232  					Ref: &link.PublicShareReference{
  1233  						Spec: &link.PublicShareReference_Id{
  1234  							Id: &link.PublicShareId{
  1235  								OpaqueId: "share-id",
  1236  							},
  1237  						},
  1238  					},
  1239  				}
  1240  
  1241  				res, err := provider.UpdatePublicShare(ctx, req)
  1242  				Expect(err).ToNot(HaveOccurred())
  1243  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
  1244  				Expect(res.GetShare()).To(Equal(updatedLink))
  1245  			})
  1246  		})
  1247  		Context("when the user changes permissions", func() {
  1248  			BeforeEach(func() {
  1249  				linkPermissions = &providerpb.ResourcePermissions{
  1250  					Stat:                 true,
  1251  					AddGrant:             true,
  1252  					Delete:               true,
  1253  					Move:                 true,
  1254  					InitiateFileDownload: true,
  1255  					InitiateFileUpload:   true,
  1256  					CreateContainer:      true,
  1257  					ListContainer:        true,
  1258  					ListGrants:           true,
  1259  				}
  1260  
  1261  				updatedLink = &link.PublicShare{
  1262  					Id: &link.PublicShareId{
  1263  						OpaqueId: "share-id",
  1264  					},
  1265  					Permissions: &link.PublicSharePermissions{
  1266  						Permissions: linkPermissions,
  1267  					},
  1268  					DisplayName: "Updated Link",
  1269  				}
  1270  
  1271  				manager.
  1272  					EXPECT().
  1273  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1274  					Once().Return(existingLink, nil)
  1275  			})
  1276  			It("fails when the user has not enough permissions on the resource", func() {
  1277  				statResourceResponse.Info.PermissionSet.Delete = false
  1278  
  1279  				req := &link.UpdatePublicShareRequest{
  1280  					Update: &link.UpdatePublicShareRequest_Update{
  1281  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1282  						Grant: &link.Grant{
  1283  							Permissions: &link.PublicSharePermissions{
  1284  								Permissions: linkPermissions,
  1285  							},
  1286  						},
  1287  					},
  1288  				}
  1289  
  1290  				res, err := provider.UpdatePublicShare(ctx, req)
  1291  				Expect(err).ToNot(HaveOccurred())
  1292  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
  1293  				Expect(res.GetStatus().GetMessage()).To(Equal("insufficient permissions to update that kind of share"))
  1294  			})
  1295  			It("fails when the permissions client is not responding", func() {
  1296  				gatewayClient.
  1297  					EXPECT().
  1298  					CheckPermission(mock.Anything, mock.Anything).
  1299  					Return(nil, errors.New("transport error"))
  1300  
  1301  				req := &link.UpdatePublicShareRequest{
  1302  					Update: &link.UpdatePublicShareRequest_Update{
  1303  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1304  						Grant: &link.Grant{
  1305  							Permissions: &link.PublicSharePermissions{
  1306  								Permissions: linkPermissions,
  1307  							},
  1308  						},
  1309  					},
  1310  				}
  1311  
  1312  				res, err := provider.UpdatePublicShare(ctx, req)
  1313  				Expect(err).ToNot(HaveOccurred())
  1314  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
  1315  				Expect(res.GetStatus().GetMessage()).To(Equal("transport error"))
  1316  			})
  1317  			It("fails when the user has no permission to write public shares and is not the creator", func() {
  1318  				checkPermissionResponse.Status.Code = rpc.Code_CODE_PERMISSION_DENIED
  1319  				gatewayClient.
  1320  					EXPECT().
  1321  					CheckPermission(mock.Anything, mock.Anything).
  1322  					Return(checkPermissionResponse, nil)
  1323  
  1324  				existingLink.Creator = &userpb.UserId{
  1325  					OpaqueId: "admin",
  1326  				}
  1327  				gatewayClient.
  1328  					EXPECT().
  1329  					Stat(mock.Anything, mock.Anything).
  1330  					Unset()
  1331  
  1332  				req := &link.UpdatePublicShareRequest{
  1333  					Update: &link.UpdatePublicShareRequest_Update{
  1334  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1335  						Grant: &link.Grant{
  1336  							Permissions: &link.PublicSharePermissions{
  1337  								Permissions: linkPermissions,
  1338  							},
  1339  						},
  1340  					},
  1341  				}
  1342  
  1343  				res, err := provider.UpdatePublicShare(ctx, req)
  1344  				Expect(err).ToNot(HaveOccurred())
  1345  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED))
  1346  				Expect(res.GetStatus().GetMessage()).To(Equal("no permission to update public share"))
  1347  			})
  1348  			It("fails when the user is not the creator and has no manager or owner permissions", func() {
  1349  				existingLink.Creator = &userpb.UserId{
  1350  					OpaqueId: "admin",
  1351  				}
  1352  
  1353  				gatewayClient.
  1354  					EXPECT().
  1355  					CheckPermission(mock.Anything, mock.Anything).
  1356  					Return(checkPermissionResponse, nil)
  1357  
  1358  				statResourceResponse.Info.PermissionSet.UpdateGrant = false
  1359  
  1360  				req := &link.UpdatePublicShareRequest{
  1361  					Update: &link.UpdatePublicShareRequest_Update{
  1362  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1363  						Grant: &link.Grant{
  1364  							Permissions: &link.PublicSharePermissions{
  1365  								Permissions: linkPermissions,
  1366  							},
  1367  						},
  1368  					},
  1369  				}
  1370  
  1371  				res, err := provider.UpdatePublicShare(ctx, req)
  1372  				Expect(err).ToNot(HaveOccurred())
  1373  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED))
  1374  				Expect(res.GetStatus().GetMessage()).To(Equal("no permission to update public share"))
  1375  			})
  1376  			It("fails when the expiration date is in the past", func() {
  1377  				yesterday := time.Now().AddDate(0, 0, -1)
  1378  				req := &link.UpdatePublicShareRequest{
  1379  					Update: &link.UpdatePublicShareRequest_Update{
  1380  						Type: link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION,
  1381  						Grant: &link.Grant{
  1382  							Expiration: utils.TimeToTS(yesterday),
  1383  						},
  1384  					},
  1385  				}
  1386  
  1387  				res, err := provider.UpdatePublicShare(ctx, req)
  1388  				Expect(err).ToNot(HaveOccurred())
  1389  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
  1390  				Expect(res.GetStatus().GetMessage()).To(ContainSubstring("expiration date is in the past"))
  1391  			})
  1392  			It("fails when the password is changed to on a writable share", func() {
  1393  				gatewayClient.
  1394  					EXPECT().
  1395  					CheckPermission(
  1396  						mock.Anything,
  1397  						mock.MatchedBy(
  1398  							func(req *permissions.CheckPermissionRequest) bool {
  1399  								return req.GetPermission() == permission.DeleteReadOnlyPassword
  1400  							},
  1401  						),
  1402  					).
  1403  					Return(checkPermissionResponse, nil)
  1404  
  1405  				req := &link.UpdatePublicShareRequest{
  1406  					Update: &link.UpdatePublicShareRequest_Update{
  1407  						Type: link.UpdatePublicShareRequest_Update_TYPE_PASSWORD,
  1408  						Grant: &link.Grant{
  1409  							Password: "",
  1410  						},
  1411  					},
  1412  				}
  1413  
  1414  				res, err := provider.UpdatePublicShare(ctx, req)
  1415  				Expect(err).ToNot(HaveOccurred())
  1416  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
  1417  				Expect(res.GetStatus().GetMessage()).To(ContainSubstring("password protection is enforced"))
  1418  			})
  1419  			It("fails when the password is already empty on a writable share", func() {
  1420  				gatewayClient.
  1421  					EXPECT().
  1422  					CheckPermission(
  1423  						mock.Anything,
  1424  						mock.MatchedBy(
  1425  							func(req *permissions.CheckPermissionRequest) bool {
  1426  								return req.GetPermission() == permission.DeleteReadOnlyPassword
  1427  							},
  1428  						),
  1429  					).
  1430  					Return(checkPermissionResponse, nil)
  1431  
  1432  				req := &link.UpdatePublicShareRequest{
  1433  					Update: &link.UpdatePublicShareRequest_Update{
  1434  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1435  						Grant: &link.Grant{
  1436  							Permissions: &link.PublicSharePermissions{
  1437  								Permissions: &providerpb.ResourcePermissions{
  1438  									Stat:                 true,
  1439  									ListContainer:        true,
  1440  									InitiateFileDownload: true,
  1441  									Move:                 true,
  1442  								},
  1443  							},
  1444  						},
  1445  					},
  1446  				}
  1447  
  1448  				res, err := provider.UpdatePublicShare(ctx, req)
  1449  				Expect(err).ToNot(HaveOccurred())
  1450  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
  1451  				Expect(res.GetStatus().GetMessage()).To(ContainSubstring("password protection is enforced"))
  1452  			})
  1453  			It("succeeds when the password is empty on a readable share with opt out permission", func() {
  1454  				gatewayClient.
  1455  					EXPECT().
  1456  					CheckPermission(
  1457  						mock.Anything,
  1458  						mock.MatchedBy(
  1459  							func(req *permissions.CheckPermissionRequest) bool {
  1460  								return req.GetPermission() == permission.DeleteReadOnlyPassword
  1461  							},
  1462  						),
  1463  					).
  1464  					Return(checkPermissionResponse, nil)
  1465  
  1466  				manager.
  1467  					EXPECT().
  1468  					UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything).
  1469  					Once().Return(updatedLink, nil)
  1470  
  1471  				req := &link.UpdatePublicShareRequest{
  1472  					Update: &link.UpdatePublicShareRequest_Update{
  1473  						Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS,
  1474  						Grant: &link.Grant{
  1475  							Permissions: &link.PublicSharePermissions{
  1476  								Permissions: &providerpb.ResourcePermissions{
  1477  									Stat:                 true,
  1478  									ListContainer:        true,
  1479  									InitiateFileDownload: true,
  1480  								},
  1481  							},
  1482  						},
  1483  					},
  1484  				}
  1485  
  1486  				res, err := provider.UpdatePublicShare(ctx, req)
  1487  				Expect(err).ToNot(HaveOccurred())
  1488  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK))
  1489  				Expect(res.GetShare()).To(Equal(updatedLink))
  1490  			})
  1491  			It("fails when the updated password doesn't fulfil the policy", func() {
  1492  				gatewayClient.
  1493  					EXPECT().
  1494  					CheckPermission(
  1495  						mock.Anything,
  1496  						mock.MatchedBy(
  1497  							func(req *permissions.CheckPermissionRequest) bool {
  1498  								return req.GetPermission() == permission.DeleteReadOnlyPassword
  1499  							},
  1500  						),
  1501  					).
  1502  					Return(checkPermissionResponse, nil)
  1503  
  1504  				req := &link.UpdatePublicShareRequest{
  1505  					Update: &link.UpdatePublicShareRequest_Update{
  1506  						Type: link.UpdatePublicShareRequest_Update_TYPE_PASSWORD,
  1507  						Grant: &link.Grant{
  1508  							Password: "Test",
  1509  						},
  1510  					},
  1511  				}
  1512  
  1513  				res, err := provider.UpdatePublicShare(ctx, req)
  1514  				Expect(err).ToNot(HaveOccurred())
  1515  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT))
  1516  				Expect(res.GetStatus().GetMessage()).To(ContainSubstring("characters are required"))
  1517  			})
  1518  		})
  1519  		Context("when the user gets a public share", func() {
  1520  			BeforeEach(func() {
  1521  				manager.
  1522  					EXPECT().
  1523  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1524  					Once().Return(existingLink, nil)
  1525  
  1526  				gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Unset()
  1527  			})
  1528  			It("succeeds", func() {
  1529  				res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{
  1530  					Ref: &link.PublicShareReference{
  1531  						Spec: &link.PublicShareReference_Id{
  1532  							Id: &link.PublicShareId{
  1533  								OpaqueId: "share-id",
  1534  							},
  1535  						},
  1536  					},
  1537  				})
  1538  				Expect(err).ToNot(HaveOccurred())
  1539  				Expect(res.GetShare()).To(Equal(existingLink))
  1540  			})
  1541  			It("fails when it finds no share", func() {
  1542  				manager.EXPECT().GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset()
  1543  				manager.
  1544  					EXPECT().
  1545  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1546  					Once().Return(nil, errtypes.NotFound("not found"))
  1547  				res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{
  1548  					Ref: &link.PublicShareReference{
  1549  						Spec: &link.PublicShareReference_Id{
  1550  							Id: &link.PublicShareId{
  1551  								OpaqueId: "share-id",
  1552  							},
  1553  						},
  1554  					},
  1555  				})
  1556  				Expect(err).ToNot(HaveOccurred())
  1557  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND))
  1558  				Expect(res.GetStatus().GetMessage()).To(ContainSubstring("not found"))
  1559  			})
  1560  			It("fails when it finds no share due to internal error", func() {
  1561  				manager.EXPECT().GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset()
  1562  				manager.
  1563  					EXPECT().
  1564  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1565  					Once().Return(nil, errtypes.InternalError("internal error"))
  1566  				res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{
  1567  					Ref: &link.PublicShareReference{
  1568  						Spec: &link.PublicShareReference_Id{
  1569  							Id: &link.PublicShareId{
  1570  								OpaqueId: "share-id",
  1571  							},
  1572  						},
  1573  					},
  1574  				})
  1575  				Expect(err).ToNot(HaveOccurred())
  1576  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
  1577  				Expect(res.GetStatus().GetMessage()).To(ContainSubstring("internal error"))
  1578  			})
  1579  			It("fails when the share manager response is empty", func() {
  1580  				manager.EXPECT().GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset()
  1581  				manager.
  1582  					EXPECT().
  1583  					GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1584  					Once().Return(nil, nil)
  1585  				res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{
  1586  					Ref: &link.PublicShareReference{
  1587  						Spec: &link.PublicShareReference_Id{
  1588  							Id: &link.PublicShareId{
  1589  								OpaqueId: "share-id",
  1590  							},
  1591  						},
  1592  					},
  1593  				})
  1594  				Expect(err).ToNot(HaveOccurred())
  1595  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND))
  1596  				Expect(res.GetStatus().GetMessage()).To(ContainSubstring("not found"))
  1597  			})
  1598  		})
  1599  		Context("when the user gets a public share by token", func() {
  1600  			BeforeEach(func() {
  1601  				manager.
  1602  					EXPECT().
  1603  					GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1604  					Once().Return(existingLink, nil)
  1605  
  1606  				gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Unset()
  1607  			})
  1608  			It("succeeds", func() {
  1609  				res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{
  1610  					Token: "token",
  1611  					Authentication: &link.PublicShareAuthentication{
  1612  						Spec: &link.PublicShareAuthentication_Password{
  1613  							Password: "password",
  1614  						},
  1615  					},
  1616  				})
  1617  				Expect(err).ToNot(HaveOccurred())
  1618  				Expect(res.GetShare()).To(Equal(existingLink))
  1619  			})
  1620  			It("fails with invalid credentials", func() {
  1621  				manager.EXPECT().GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset()
  1622  				manager.
  1623  					EXPECT().
  1624  					GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1625  					Once().Return(nil, errtypes.InvalidCredentials("wrong password"))
  1626  
  1627  				res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{
  1628  					Token: "token",
  1629  					Authentication: &link.PublicShareAuthentication{
  1630  						Spec: &link.PublicShareAuthentication_Password{
  1631  							Password: "password",
  1632  						},
  1633  					},
  1634  				})
  1635  				Expect(err).ToNot(HaveOccurred())
  1636  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED))
  1637  				Expect(res.GetStatus().GetMessage()).To(Equal("wrong password"))
  1638  			})
  1639  			It("fails with an unknown token", func() {
  1640  				manager.EXPECT().GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset()
  1641  				manager.
  1642  					EXPECT().
  1643  					GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1644  					Once().Return(nil, errtypes.NotFound("public share not found"))
  1645  
  1646  				res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{
  1647  					Token: "token",
  1648  					Authentication: &link.PublicShareAuthentication{
  1649  						Spec: &link.PublicShareAuthentication_Password{
  1650  							Password: "password",
  1651  						},
  1652  					},
  1653  				})
  1654  				Expect(err).ToNot(HaveOccurred())
  1655  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND))
  1656  				Expect(res.GetStatus().GetMessage()).To(Equal("unknown token"))
  1657  			})
  1658  			It("fails with an unknown error", func() {
  1659  				manager.EXPECT().GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset()
  1660  				manager.
  1661  					EXPECT().
  1662  					GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).
  1663  					Once().Return(nil, errtypes.InternalError("internal error"))
  1664  
  1665  				res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{
  1666  					Token: "token",
  1667  					Authentication: &link.PublicShareAuthentication{
  1668  						Spec: &link.PublicShareAuthentication_Password{
  1669  							Password: "password",
  1670  						},
  1671  					},
  1672  				})
  1673  				Expect(err).ToNot(HaveOccurred())
  1674  				Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL))
  1675  				Expect(res.GetStatus().GetMessage()).To(Equal("unexpected error"))
  1676  			})
  1677  		})
  1678  	})
  1679  })