Skip to content

Commit

Permalink
auto accept shares
Browse files Browse the repository at this point in the history
Signed-off-by: jkoberg <jkoberg@owncloud.com>
  • Loading branch information
kobergj committed Aug 22, 2023
1 parent 104d697 commit 80b2b91
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 5 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/auto-accept-shares.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Auto-Accept Shares

Automatically accept shares when configured by the user or admin

https://github.com/owncloud/ocis/pull/7097
3 changes: 2 additions & 1 deletion services/ocs/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ type Config struct {

TokenManager *TokenManager `yaml:"token_manager"`

Events Events `yaml:"events"`
RevaGateway string `yaml:"reva_gateway" env:"OCIS_REVA_GATEWAY;REVA_GATEWAY" desc:"CS3 gateway used to look up user metadata" deprecationVersion:"3.0" removalVersion:"4.0.0" deprecationInfo:"REVA_GATEWAY changing name for consistency" deprecationReplacement:"OCIS_REVA_GATEWAY"`
Events Events `yaml:"events"`

Context context.Context `yaml:"-"`
}
Expand Down
2 changes: 2 additions & 0 deletions services/ocs/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package defaults
import (
"strings"

"github.com/owncloud/ocis/v2/ocis-pkg/shared"
"github.com/owncloud/ocis/v2/ocis-pkg/structs"
"github.com/owncloud/ocis/v2/services/ocs/pkg/config"
)
Expand Down Expand Up @@ -43,6 +44,7 @@ func DefaultConfig() *config.Config {
Cluster: "ocis-cluster",
EnableTLS: false,
},
RevaGateway: shared.DefaultRevaConfig().Address,
}
}

Expand Down
98 changes: 95 additions & 3 deletions services/ocs/pkg/service/v0/events.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,124 @@
package svc

import (
"context"
"errors"

"github.com/cs3org/reva/v2/pkg/events"
"github.com/cs3org/reva/v2/pkg/events/stream"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
"github.com/owncloud/ocis/v2/services/ocs/pkg/config"
"google.golang.org/protobuf/types/known/fieldmaskpb"

gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
)

var _registeredEvents = []events.Unmarshaller{
events.ShareCreated{},
}

// ListenForEvents listens for events and acts accordingly
func ListenForEvents(cfg *config.Config, l log.Logger) {
bus, err := stream.NatsFromConfig(cfg.Service.Name, stream.NatsConfig(cfg.Events))
if err != nil {
l.Error().Err(err).Msg("cannot connect to nats")
return
}

evChannel, err := events.Consume(bus, "ocs", events.ShareCreated{})
evChannel, err := events.Consume(bus, "ocs", _registeredEvents...)
if err != nil {
l.Error().Err(err).Msg("cannot consume from nats")
}

tm, err := pool.StringToTLSMode(cfg.GRPCClientTLS.Mode)
if err != nil {
return
}
gatewaySelector, err := pool.GatewaySelector(
cfg.RevaGateway,
pool.WithTLSCACert(cfg.GRPCClientTLS.CACert),
pool.WithTLSMode(tm),
pool.WithRegistry(registry.GetRegistry()),
)
if err != nil {
return
}
gwc, err := gatewaySelector.Next()
if err != nil {
return
}

for e := range evChannel {
switch ev := e.Event.(type) {
default:
l.Error().Interface("event", e).Msg("unhandled event")
case events.ShareCreated:
// auto accept shares
_ = ev.ShareID
// TODO: impersonate via service accounts instead
ctx, _, err := utils.Impersonate(ev.Sharer, gwc, "%oTnXx@G4qPQKu%@eTz5X-$Y518A=*Lm")
if err != nil {
l.Error().Err(err).Msg("cannot impersonate user")
continue
}

uids, err := getUserIDs(ctx, gwc, ev.GranteeUserID, ev.GranteeGroupID)
if err != nil {
l.Error().Err(err).Msg("cannot get granteess")
}

for _, uid := range uids {
// TODO: remove impersonate call when using service accounts
ctx, _, err := utils.Impersonate(uid, gwc, "%oTnXx@G4qPQKu%@eTz5X-$Y518A=*Lm")
if err != nil {
l.Error().Err(err).Msg("cannot impersonate user")
continue
}

resp, err := gwc.UpdateReceivedShare(ctx, updateShareRequest(ev.ShareID, uid))
if err != nil {
l.Error().Err(err).Msg("error sending grpc request")
continue
}
if resp.GetStatus().GetCode() != rpc.Code_CODE_OK {
l.Error().Interface("status", resp.GetStatus()).Str("userid", uid.GetOpaqueId()).Msg("unexpected status code while accepting share")
}
}

}
}
}

func getUserIDs(ctx context.Context, gwc gateway.GatewayAPIClient, uid *user.UserId, gid *group.GroupId) ([]*user.UserId, error) {
if uid != nil {
return []*user.UserId{uid}, nil
}

res, err := gwc.GetGroup(ctx, &group.GetGroupRequest{GroupId: gid})
if err != nil {
return nil, err
}
if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
return nil, errors.New("could not get group")
}

return res.GetGroup().GetMembers(), nil
}

func updateShareRequest(shareID *collaboration.ShareId, uid *user.UserId) *collaboration.UpdateReceivedShareRequest {
return &collaboration.UpdateReceivedShareRequest{
Opaque: utils.AppendPlainToOpaque(nil, "userid", uid.GetOpaqueId()),
Share: &collaboration.ReceivedShare{
Share: &collaboration.Share{
Id: shareID,
},
State: collaboration.ShareState_SHARE_STATE_ACCEPTED,
},
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state"}},
}
}
2 changes: 1 addition & 1 deletion services/ocs/pkg/service/v0/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewService(opts ...Option) Service {
return nil
})

go ListenForEvents(options.Config)
go ListenForEvents(options.Config, options.Logger)

return svc
}
Expand Down

0 comments on commit 80b2b91

Please sign in to comment.