Skip to content

Commit a9d5432

Browse files
authored
feat: [OCISDEV-949] add option to disable direct (user/group) sharing (#651)
* feat: [OCISDEV-949] add option to disable direct (user/group) sharing Adds an `enable_user_sharing` config option to the ocs, usershareprovider and ocmshareprovider services. Defaults to true. When set to false, the usershareprovider and ocmshareprovider gRPC services reject requests to share a resource with a user, group, or federated (remote) user. The sharees search endpoint returns no results, and the files_sharing.user.enabled capability is set to false. Public link sharing is not affected. * feat: [OCISDEV-949] add option to disable public link sharing Adds an enable_public_sharing config option to the publicshareprovider service, defaulting to true. When set to false, creating new public links is rejected (internal links, which carry no permissions, are unaffected). Also removes a hardcoded override in the capabilities handler that always forced files_sharing.public.enabled to true, letting it reflect whatever value is actually configured.
1 parent 1d89f93 commit a9d5432

21 files changed

Lines changed: 93 additions & 13 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Enhancement: Add config option to disable public link sharing
2+
3+
Added an `enable_public_sharing` config option to the publicshareprovider
4+
service. When set to `false`, creating new public links is rejected
5+
(internal links, which carry no permissions, are unaffected), and the
6+
`files_sharing.public.enabled` capability reports `false`. A hardcoded
7+
override that always forced `files_sharing.public.enabled` to `true` was
8+
also removed so the capability reflects the actual configured value.
9+
10+
https://github.com/owncloud/reva/pull/651
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Enhancement: Add config option to disable direct (user/group) sharing
2+
3+
Added an `enable_user_sharing` config option to the ocs, usershareprovider
4+
and ocmshareprovider services. When set to `false`, creating user, group
5+
or federated shares is rejected, the `sharees` search endpoint returns
6+
empty results, and the `files_sharing.user.enabled` capability reports
7+
`false`. Public link sharing is unaffected.
8+
9+
https://github.com/owncloud/reva/pull/651

internal/grpc/services/ocmshareprovider/ocmshareprovider.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,15 @@ func init() {
5959
}
6060

6161
type config struct {
62-
Driver string `mapstructure:"driver"`
63-
Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
64-
ClientTimeout int `mapstructure:"client_timeout"`
65-
ClientInsecure bool `mapstructure:"client_insecure"`
66-
GatewaySVC string `mapstructure:"gatewaysvc" validate:"required"`
67-
ProviderDomain string `mapstructure:"provider_domain" validate:"required" docs:"The same domain registered in the provider authorizer"`
68-
WebDAVEndpoint string `mapstructure:"webdav_endpoint" validate:"required"`
69-
WebappTemplate string `mapstructure:"webapp_template"`
62+
Driver string `mapstructure:"driver"`
63+
Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
64+
ClientTimeout int `mapstructure:"client_timeout"`
65+
ClientInsecure bool `mapstructure:"client_insecure"`
66+
GatewaySVC string `mapstructure:"gatewaysvc" validate:"required"`
67+
ProviderDomain string `mapstructure:"provider_domain" validate:"required" docs:"The same domain registered in the provider authorizer"`
68+
WebDAVEndpoint string `mapstructure:"webdav_endpoint" validate:"required"`
69+
WebappTemplate string `mapstructure:"webapp_template"`
70+
EnableUserSharing bool `mapstructure:"enable_user_sharing"`
7071
}
7172

7273
type service struct {
@@ -254,6 +255,12 @@ func (s *service) getProtocols(ctx context.Context, share *ocm.Share) ocmd.Proto
254255
}
255256

256257
func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareRequest) (*ocm.CreateOCMShareResponse, error) {
258+
if !s.conf.EnableUserSharing {
259+
return &ocm.CreateOCMShareResponse{
260+
Status: status.NewPermissionDenied(ctx, nil, "direct sharing is disabled"),
261+
}, nil
262+
}
263+
257264
gatewayClient, err := s.gatewaySelector.Next()
258265
if err != nil {
259266
return nil, err

internal/grpc/services/publicshareprovider/publicshareprovider.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ type config struct {
6767
WriteableShareMustHavePassword bool `mapstructure:"writeable_share_must_have_password"`
6868
PublicShareMustHavePassword bool `mapstructure:"public_share_must_have_password"`
6969
PasswordPolicy map[string]interface{} `mapstructure:"password_policy"`
70+
EnablePublicSharing bool `mapstructure:"enable_public_sharing"`
7071
}
7172

7273
type passwordPolicy struct {
@@ -213,6 +214,12 @@ func (s *service) CreatePublicShare(ctx context.Context, req *link.CreatePublicS
213214

214215
isInternalLink := grants.PermissionsEqual(req.GetGrant().GetPermissions().GetPermissions(), &provider.ResourcePermissions{})
215216

217+
if !isInternalLink && !s.conf.EnablePublicSharing {
218+
return &link.CreatePublicShareResponse{
219+
Status: status.NewPermissionDenied(ctx, nil, "public sharing is disabled"),
220+
}, nil
221+
}
222+
216223
sRes, err := gatewayClient.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: req.GetResourceInfo().GetId()}})
217224
if err != nil {
218225
log.Err(err).Interface("resource_id", req.GetResourceInfo().GetId()).Msg("failed to stat resource to share")

internal/grpc/services/publicshareprovider/publicshareprovider_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ var _ = Describe("PublicShareProvider", func() {
146146
"allowed_paths_for_shares": []string{"/NewFolder"},
147147
"writeable_share_must_have_password": false,
148148
"public_share_must_have_password": true,
149+
"enable_public_sharing": true,
149150
"password_policy": map[string]interface{}{
150151
"min_digits": 1,
151152
"min_characters": 8,

internal/grpc/services/usershareprovider/usershareprovider.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type config struct {
6565
Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
6666
GatewayAddr string `mapstructure:"gateway_addr"`
6767
AllowedPathsForShares []string `mapstructure:"allowed_paths_for_shares"`
68+
EnableUserSharing bool `mapstructure:"enable_user_sharing"`
6869
}
6970

7071
func (c *config) init() {
@@ -77,6 +78,7 @@ type service struct {
7778
sm share.Manager
7879
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
7980
allowedPathsForShares []*regexp.Regexp
81+
enableUserSharing bool
8082
}
8183

8284
func getShareManager(c *config) (share.Manager, error) {
@@ -137,15 +139,16 @@ func NewDefault(m map[string]interface{}, ss *grpc.Server, _ *zerolog.Logger) (r
137139
return nil, err
138140
}
139141

140-
return New(gatewaySelector, sm, allowedPathsForShares), nil
142+
return New(gatewaySelector, sm, allowedPathsForShares, c.EnableUserSharing), nil
141143
}
142144

143145
// New creates a new user share provider svc
144-
func New(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], sm share.Manager, allowedPathsForShares []*regexp.Regexp) rgrpc.Service {
146+
func New(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], sm share.Manager, allowedPathsForShares []*regexp.Regexp, enableUserSharing bool) rgrpc.Service {
145147
service := &service{
146148
sm: sm,
147149
gatewaySelector: gatewaySelector,
148150
allowedPathsForShares: allowedPathsForShares,
151+
enableUserSharing: enableUserSharing,
149152
}
150153

151154
return service
@@ -174,6 +177,12 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
174177
}, nil
175178
}
176179

180+
if !s.enableUserSharing {
181+
return &collaboration.CreateShareResponse{
182+
Status: status.NewPermissionDenied(ctx, nil, "direct sharing is disabled"),
183+
}, nil
184+
}
185+
177186
gatewayClient, err := s.gatewaySelector.Next()
178187
if err != nil {
179188
return nil, err

internal/grpc/services/usershareprovider/usershareprovider_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ var _ = Describe("user share provider service", func() {
115115
}
116116
manager.On("GetShare", mock.Anything, mock.Anything).Return(getShareResponse, nil)
117117

118-
rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{})
118+
rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{}, true)
119119

120120
provider = rgrpcService.(collaborationpb.CollaborationAPIServer)
121121
Expect(provider).ToNot(BeNil())
@@ -367,7 +367,7 @@ var _ = Describe("user share provider service", func() {
367367
)
368368
Context("resharing is not allowed", func() {
369369
JustBeforeEach(func() {
370-
rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{})
370+
rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{}, true)
371371

372372
provider = rgrpcService.(collaborationpb.CollaborationAPIServer)
373373
Expect(provider).ToNot(BeNil())

internal/http/services/owncloud/ocs/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type Config struct {
4949
Notifications map[string]interface{} `mapstructure:"notifications"`
5050
IncludeOCMSharees bool `mapstructure:"include_ocm_sharees"`
5151
ShowEmailInResults bool `mapstructure:"show_email_in_results"`
52+
EnableUserSharing bool `mapstructure:"enable_user_sharing"`
5253
}
5354

5455
// Init sets sane defaults

internal/http/services/owncloud/ocs/handlers/apps/sharing/sharees/sharees.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type Handler struct {
4141
additionalInfoAttribute string
4242
includeOCMSharees bool
4343
showUserEmailInResults bool
44+
enableUserSharing bool
4445
}
4546

4647
// Init initializes this and any contained handlers
@@ -49,6 +50,7 @@ func (h *Handler) Init(c *config.Config) {
4950
h.additionalInfoAttribute = c.AdditionalInfoAttribute
5051
h.includeOCMSharees = c.IncludeOCMSharees
5152
h.showUserEmailInResults = c.ShowEmailInResults
53+
h.enableUserSharing = c.EnableUserSharing
5254
}
5355

5456
// FindSharees implements the /apps/files_sharing/api/v1/sharees endpoint
@@ -61,6 +63,20 @@ func (h *Handler) FindSharees(w http.ResponseWriter, r *http.Request) {
6163
return
6264
}
6365

66+
if !h.enableUserSharing {
67+
response.WriteOCSSuccess(w, r, &conversions.ShareeData{
68+
Exact: &conversions.ExactMatchesData{
69+
Users: []*conversions.MatchData{},
70+
Groups: []*conversions.MatchData{},
71+
Remotes: []*conversions.MatchData{},
72+
},
73+
Users: []*conversions.MatchData{},
74+
Groups: []*conversions.MatchData{},
75+
Remotes: []*conversions.MatchData{},
76+
})
77+
return
78+
}
79+
6480
gwc, err := pool.GetGatewayServiceClient(h.gatewayAddr)
6581
if err != nil {
6682
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting gateway grpc client", err)

internal/http/services/owncloud/ocs/handlers/cloud/capabilities/capabilities.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ func (h *Handler) Init(c *config.Config) {
141141
}
142142

143143
// h.c.Capabilities.FilesSharing.IsPublic.Enabled is boolean
144-
h.c.Capabilities.FilesSharing.Public.Enabled = true
145144

146145
if h.c.Capabilities.FilesSharing.Public.Password == nil {
147146
h.c.Capabilities.FilesSharing.Public.Password = &ocs.CapabilitiesFilesSharingPublicPassword{}

0 commit comments

Comments
 (0)