From f1c955ad3ee4a4a028b1346e12c261e84d3fdcf8 Mon Sep 17 00:00:00 2001 From: Roman Perekhod Date: Tue, 20 Jun 2023 11:57:50 +0200 Subject: [PATCH] the enforcePassword added to the carate action. the tests updated --- .../handlers/apps/sharing/shares/public.go | 32 ++-- .../apps/sharing/shares/shares_test.go | 160 +++++++++++++++++- 2 files changed, 176 insertions(+), 16 deletions(-) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go index 029ac6808f9..c290b984eaa 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go @@ -128,7 +128,12 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, } } - permissions, err := ocPublicPermToCs3(permKey, h) + // default perms: read-only + // TODO: the default might change depending on allowed permissions and configs + if permKey == nil { + permKey = &_defaultPublicLinkPermission + } + permissions, err := ocPublicPermToCs3(permKey) if err != nil { return nil, &ocsError{ Code: response.MetaBadRequest.StatusCode, @@ -136,16 +141,13 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, Error: err, } } - if permissions == nil { - // default perms: read-only - // TODO: the default might change depending on allowed permissions and configs - permissions, err = ocPublicPermToCs3(&_defaultPublicLinkPermission, h) - if err != nil { - return nil, &ocsError{ - Code: response.MetaServerError.StatusCode, - Message: "Could not convert default permissions", - Error: err, - } + + password := strings.TrimSpace(r.FormValue("password")) + if h.enforcePassword(permKey) && len(password) == 0 { + return nil, &ocsError{ + Code: response.MetaBadRequest.StatusCode, + Message: "missing required password", + Error: errors.New("missing required password"), } } @@ -173,7 +175,7 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, Permissions: &link.PublicSharePermissions{ Permissions: permissions, }, - Password: r.FormValue("password"), + Password: password, }, } @@ -199,7 +201,7 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, Metadata: map[string]string{ "name": r.FormValue("name"), "quicklink": r.FormValue("quicklink"), - // "password": r.FormValue("password"), + // "password": password, }, } @@ -379,7 +381,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar } // Permissions - newPermissions, err := ocPublicPermToCs3(permKey, h) + newPermissions, err := ocPublicPermToCs3(permKey) logger.Debug().Interface("newPermissions", newPermissions).Msg("Parsed permissions") if err != nil { response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "invalid permissions", err) @@ -599,7 +601,7 @@ func decreasePermissionsIfNecessary(perm int) int { return perm } -func ocPublicPermToCs3(pk *int, h *Handler) (*provider.ResourcePermissions, error) { +func ocPublicPermToCs3(pk *int) (*provider.ResourcePermissions, error) { if pk == nil { return nil, nil } diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go index 93ef3f32191..09cf66a23f3 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares_test.go @@ -474,6 +474,7 @@ var _ = Describe("The ocs API", func() { c := &config.Config{} c.GatewaySvc = "gatewaysvc" c.StatCacheDatabase = strconv.FormatInt(rand.Int63(), 10) // Use a fresh database for each test + // this is equivalent of the ocis OCIS_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD=true c.Capabilities = cdata.CapabilitiesData{ Capabilities: &cdata.Capabilities{FilesSharing: &cdata.CapabilitiesFilesSharing{Public: &cdata.CapabilitiesFilesSharingPublic{ Password: &cdata.CapabilitiesFilesSharingPublicPassword{ @@ -514,7 +515,6 @@ var _ = Describe("The ocs API", func() { Context("when change the permission to 3", func() { It("the password exists. update succeed", func() { - form := url.Values{} form.Add("permissions", "3") form.Add("password", "passwass") @@ -544,6 +544,164 @@ var _ = Describe("The ocs API", func() { Expect(w.Result().StatusCode).To(Equal(400)) gatewayClient.AssertNumberOfCalls(GinkgoT(), "UpdatePublicShare", 0) }) + + It("permissions=1, the password doesn't exist. update succeed", func() { + form := url.Values{} + form.Add("permissions", "1") + req := httptest.NewRequest("PUT", "/ocs/v1.php/apps/files_sharing/api/v1/shares", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + rctx := chi.NewRouteContext() + rctx.URLParams.Add("shareid", "2") + req = req.WithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx)) + + w := httptest.NewRecorder() + h.UpdateShare(w, req) + Expect(w.Result().StatusCode).To(Equal(200)) + gatewayClient.AssertNumberOfCalls(GinkgoT(), "UpdatePublicShare", 1) + }) + }) + }) + + Context("Password Enforced when update a share", func() { + var ( + resID = &provider.ResourceId{ + StorageId: "share1-storageid", + OpaqueId: "share1", + } + share2 = &link.PublicShare{ + Id: &link.PublicShareId{OpaqueId: "3"}, + ResourceId: resID, + Owner: user.Id, + Quicklink: true, + PasswordProtected: false, + } + + statResponse = &provider.StatResponse{ + Status: status.NewOK(context.Background()), + Info: &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_CONTAINER, + Path: "/3", + Id: resID, + Owner: user.Id, + PermissionSet: &provider.ResourcePermissions{ + AddGrant: true, + CreateContainer: true, + Delete: true, + GetPath: true, + GetQuota: true, + InitiateFileDownload: true, + InitiateFileUpload: true, + ListGrants: true, + ListContainer: true, + ListRecycle: true, + Move: true, + RemoveGrant: true, + PurgeRecycle: true, + RestoreFileVersion: true, + RestoreRecycleItem: true, + Stat: true, + UpdateGrant: true, + DenyGrant: true, + }, + }, + } + ) + + BeforeEach(func() { + h = &shares.Handler{} + pool.RemoveSelector("GatewaySelector" + "any") + gatewayClient = &cs3mocks.GatewayAPIClient{} + + c := &config.Config{} + c.GatewaySvc = "gatewaysvc" + c.StatCacheDatabase = strconv.FormatInt(rand.Int63(), 10) // Use a fresh database for each test + // this is equivalent of the ocis OCIS_SHARING_PUBLIC_WRITEABLE_SHARE_MUST_HAVE_PASSWORD=true + c.Capabilities = cdata.CapabilitiesData{ + Capabilities: &cdata.Capabilities{FilesSharing: &cdata.CapabilitiesFilesSharing{Public: &cdata.CapabilitiesFilesSharingPublic{ + Password: &cdata.CapabilitiesFilesSharingPublicPassword{ + EnforcedFor: &cdata.CapabilitiesFilesSharingPublicPasswordEnforcedFor{ + ReadOnly: false, + ReadWrite: true, + ReadWriteDelete: true, + UploadOnly: true, + }, + }}}}, + } + c.Init() + h.InitWithGetter(c, func() (gateway.GatewayAPIClient, error) { + return gatewayClient, nil + }) + gatewayClient.On("GetPublicShare", mock.Anything, mock.Anything).Return(&link.GetPublicShareResponse{ + Status: status.NewOK(context.Background()), + Share: share2, + }, nil) + + gatewayClient.On("CheckPermission", mock.Anything, mock.Anything, mock.Anything).Return(&permissions.CheckPermissionResponse{ + Status: &rpc.Status{Code: rpc.Code_CODE_OK}, + }, nil) + + gatewayClient.On("Stat", mock.Anything, mock.Anything).Return(statResponse, nil) + + gatewayClient.On("UpdatePublicShare", mock.Anything, mock.Anything).Return(&link.UpdatePublicShareResponse{ + Status: &rpc.Status{Code: rpc.Code_CODE_OK}, + Share: share2, + }, nil) + + gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(&userpb.GetUserResponse{ + Status: status.NewOK(context.Background()), + User: user, + }, nil) + }) + + Context("when change the permission", func() { + for _, perm := range []string{"4", "5", "15"} { + perm := perm + It("the password exists. update succeed", func() { + form := url.Values{} + form.Add("permissions", perm) + form.Add("password", "passwass") + req := httptest.NewRequest("PUT", "/ocs/v1.php/apps/files_sharing/api/v1/shares", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + rctx := chi.NewRouteContext() + rctx.URLParams.Add("shareid", "3") + req = req.WithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx)) + + w := httptest.NewRecorder() + h.UpdateShare(w, req) + Expect(w.Result().StatusCode).To(Equal(200)) + gatewayClient.AssertNumberOfCalls(GinkgoT(), "UpdatePublicShare", 2) + }) + } + + It("the password doesn't exist. update failed", func() { + form := url.Values{} + form.Add("permissions", "3") + req := httptest.NewRequest("PUT", "/ocs/v1.php/apps/files_sharing/api/v1/shares", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + rctx := chi.NewRouteContext() + rctx.URLParams.Add("shareid", "3") + req = req.WithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx)) + + w := httptest.NewRecorder() + h.UpdateShare(w, req) + Expect(w.Result().StatusCode).To(Equal(400)) + gatewayClient.AssertNumberOfCalls(GinkgoT(), "UpdatePublicShare", 0) + }) + + It("permissions=1, the password doesn't exist. update succeed", func() { + form := url.Values{} + form.Add("permissions", "1") + req := httptest.NewRequest("PUT", "/ocs/v1.php/apps/files_sharing/api/v1/shares", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + rctx := chi.NewRouteContext() + rctx.URLParams.Add("shareid", "3") + req = req.WithContext(context.WithValue(ctx, chi.RouteCtxKey, rctx)) + + w := httptest.NewRecorder() + h.UpdateShare(w, req) + Expect(w.Result().StatusCode).To(Equal(200)) + gatewayClient.AssertNumberOfCalls(GinkgoT(), "UpdatePublicShare", 1) + }) }) }) })