Skip to content

Commit

Permalink
Stat mount points only for accepted shares, configure updating existi…
Browse files Browse the repository at this point in the history
…ng shares (#2932)
  • Loading branch information
ishank011 authored Jun 9, 2022
1 parent cb9c827 commit fd1fbf3
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 91 deletions.
3 changes: 3 additions & 0 deletions changelog/unreleased/ocs-optimizations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Enhancement: Stat accepted shares mountpoints, configure existing share updates

https://github.com/cs3org/reva/pull/2932
35 changes: 18 additions & 17 deletions internal/http/services/owncloud/ocs/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,24 @@ import (

// Config holds the config options that need to be passed down to all ocs handlers
type Config struct {
Prefix string `mapstructure:"prefix"`
Config data.ConfigData `mapstructure:"config"`
Capabilities data.CapabilitiesData `mapstructure:"capabilities"`
GatewaySvc string `mapstructure:"gatewaysvc"`
StorageregistrySvc string `mapstructure:"storage_registry_svc"`
DefaultUploadProtocol string `mapstructure:"default_upload_protocol"`
UserAgentChunkingMap map[string]string `mapstructure:"user_agent_chunking_map"`
SharePrefix string `mapstructure:"share_prefix"`
HomeNamespace string `mapstructure:"home_namespace"`
AdditionalInfoAttribute string `mapstructure:"additional_info_attribute"`
CacheWarmupDriver string `mapstructure:"cache_warmup_driver"`
CacheWarmupDrivers map[string]map[string]interface{} `mapstructure:"cache_warmup_drivers"`
ResourceInfoCacheDriver string `mapstructure:"resource_info_cache_type"`
ResourceInfoCacheTTL int `mapstructure:"resource_info_cache_ttl"`
ResourceInfoCacheDrivers map[string]map[string]interface{} `mapstructure:"resource_info_caches"`
UserIdentifierCacheTTL int `mapstructure:"user_identifier_cache_ttl"`
MachineAuthAPIKey string `mapstructure:"machine_auth_apikey"`
Prefix string `mapstructure:"prefix"`
Config data.ConfigData `mapstructure:"config"`
Capabilities data.CapabilitiesData `mapstructure:"capabilities"`
GatewaySvc string `mapstructure:"gatewaysvc"`
StorageregistrySvc string `mapstructure:"storage_registry_svc"`
DefaultUploadProtocol string `mapstructure:"default_upload_protocol"`
UserAgentChunkingMap map[string]string `mapstructure:"user_agent_chunking_map"`
SharePrefix string `mapstructure:"share_prefix"`
HomeNamespace string `mapstructure:"home_namespace"`
AdditionalInfoAttribute string `mapstructure:"additional_info_attribute"`
CacheWarmupDriver string `mapstructure:"cache_warmup_driver"`
CacheWarmupDrivers map[string]map[string]interface{} `mapstructure:"cache_warmup_drivers"`
ResourceInfoCacheDriver string `mapstructure:"resource_info_cache_type"`
ResourceInfoCacheTTL int `mapstructure:"resource_info_cache_ttl"`
ResourceInfoCacheDrivers map[string]map[string]interface{} `mapstructure:"resource_info_caches"`
UserIdentifierCacheTTL int `mapstructure:"user_identifier_cache_ttl"`
MachineAuthAPIKey string `mapstructure:"machine_auth_apikey"`
SkipUpdatingExistingSharesMountpoints bool `mapstructure:"skip_updating_existing_shares_mountpoint"`
}

// Init sets sane defaults
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,17 @@ var (

// Handler implements the shares part of the ownCloud sharing API
type Handler struct {
gatewayAddr string
machineAuthAPIKey string
storageRegistryAddr string
publicURL string
sharePrefix string
homeNamespace string
additionalInfoTemplate *template.Template
userIdentifierCache *ttlcache.Cache
resourceInfoCache cache.ResourceInfoCache
resourceInfoCacheTTL time.Duration
gatewayAddr string
machineAuthAPIKey string
storageRegistryAddr string
publicURL string
sharePrefix string
homeNamespace string
skipUpdatingExistingSharesMountpoints bool
additionalInfoTemplate *template.Template
userIdentifierCache *ttlcache.Cache
resourceInfoCache cache.ResourceInfoCache
resourceInfoCacheTTL time.Duration

getClient GatewayClientGetter
}
Expand Down Expand Up @@ -123,6 +124,7 @@ func (h *Handler) Init(c *config.Config) {
h.publicURL = c.Config.Host
h.sharePrefix = c.SharePrefix
h.homeNamespace = c.HomeNamespace
h.skipUpdatingExistingSharesMountpoints = c.SkipUpdatingExistingSharesMountpoints

h.additionalInfoTemplate, _ = template.New("additionalInfo").Parse(c.AdditionalInfoAttribute)
h.resourceInfoCacheTTL = time.Second * time.Duration(c.ResourceInfoCacheTTL)
Expand Down Expand Up @@ -274,68 +276,15 @@ func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) {
}

h.mapUserIds(ctx, client, s)
if shareType == int(conversions.ShareTypeUser) {
res, err := client.GetUser(ctx, &userpb.GetUserRequest{
UserId: &userpb.UserId{
OpaqueId: share.Grantee.GetUserId().GetOpaqueId(),
},
})
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not look up user", err)
return
}
if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "get user call failed", nil)
return
}
if res.User == nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grantee not found", nil)
return
}

// Get auth
granteeCtx := ctxpkg.ContextSetUser(context.Background(), res.User)

authRes, err := client.Authenticate(granteeCtx, &gateway.AuthenticateRequest{
Type: "machine",
ClientId: res.User.Username,
ClientSecret: h.machineAuthAPIKey,
})
if err != nil {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not do machine authentication", err)
return
}
if authRes.GetStatus().GetCode() != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "machine authentication failed", nil)
return
}
granteeCtx = metadata.AppendToOutgoingContext(granteeCtx, ctxpkg.TokenHeader, authRes.Token)

lrs, ocsResponse := getSharesList(granteeCtx, client)
if ocsResponse != nil {
response.WriteOCSResponse(w, r, *ocsResponse, nil)
if !h.skipUpdatingExistingSharesMountpoints {
status, msg, err := h.updateExistingShareMountpoints(ctx, shareType, share, statRes.Info, client)
if status != response.MetaOK.StatusCode {
response.WriteOCSError(w, r, status, msg, err)
return
}

for _, s := range lrs.Shares {
if s.GetShare().GetId() != share.Id && s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED && utils.ResourceIDEqual(s.Share.ResourceId, statRes.Info.GetId()) {
updateRequest := &collaboration.UpdateReceivedShareRequest{
Share: &collaboration.ReceivedShare{
Share: share,
MountPoint: s.MountPoint,
State: collaboration.ShareState_SHARE_STATE_ACCEPTED,
},
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state", "mount_point"}},
}

shareRes, err := client.UpdateReceivedShare(granteeCtx, updateRequest)
if err != nil || shareRes.Status.Code != rpc.Code_CODE_OK {
response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", err)
return
}
}
}
}

response.WriteOCSSuccess(w, r, s)
case int(conversions.ShareTypePublicLink):
// public links default to read only
Expand Down Expand Up @@ -379,6 +328,65 @@ func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) {
}
}

func (h *Handler) updateExistingShareMountpoints(ctx context.Context, shareType int, share *collaboration.Share, info *provider.ResourceInfo, client gateway.GatewayAPIClient) (int, string, error) {
if shareType == int(conversions.ShareTypeUser) {
res, err := client.GetUser(ctx, &userpb.GetUserRequest{
UserId: &userpb.UserId{
OpaqueId: share.Grantee.GetUserId().GetOpaqueId(),
},
})
if err != nil {
return response.MetaServerError.StatusCode, "could not look up user", err
}
if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
return response.MetaServerError.StatusCode, "get user call failed", nil
}
if res.User == nil {
return response.MetaServerError.StatusCode, "grantee not found", nil
}

// Get auth
granteeCtx := ctxpkg.ContextSetUser(context.Background(), res.User)

authRes, err := client.Authenticate(granteeCtx, &gateway.AuthenticateRequest{
Type: "machine",
ClientId: res.User.Username,
ClientSecret: h.machineAuthAPIKey,
})
if err != nil {
return response.MetaServerError.StatusCode, "could not do machine authentication", err
}
if authRes.GetStatus().GetCode() != rpc.Code_CODE_OK {
return response.MetaServerError.StatusCode, "machine authentication failed", nil
}
granteeCtx = metadata.AppendToOutgoingContext(granteeCtx, ctxpkg.TokenHeader, authRes.Token)

lrs, ocsResponse := getSharesList(granteeCtx, client)
if ocsResponse != nil {
return ocsResponse.OCS.Meta.StatusCode, ocsResponse.OCS.Meta.Message, nil
}

for _, s := range lrs.Shares {
if s.GetShare().GetId() != share.Id && s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED && utils.ResourceIDEqual(s.Share.ResourceId, info.GetId()) {
updateRequest := &collaboration.UpdateReceivedShareRequest{
Share: &collaboration.ReceivedShare{
Share: share,
MountPoint: s.MountPoint,
State: collaboration.ShareState_SHARE_STATE_ACCEPTED,
},
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state", "mount_point"}},
}

shareRes, err := client.UpdateReceivedShare(granteeCtx, updateRequest)
if err != nil || shareRes.Status.Code != rpc.Code_CODE_OK {
return response.MetaServerError.StatusCode, "grpc update received share request failed", err
}
}
}
}
return response.MetaOK.StatusCode, "", nil
}

func (h *Handler) extractPermissions(w http.ResponseWriter, r *http.Request, ri *provider.ResourceInfo, defaultPermissions *conversions.Role) (*conversions.Role, []byte, *ocsError) {
reqRole, reqPermissions := r.FormValue("role"), r.FormValue("permissions")
var role *conversions.Role
Expand Down Expand Up @@ -834,13 +842,15 @@ func (h *Handler) listSharesWithMe(w http.ResponseWriter, r *http.Request) {
} else {
var status *rpc.Status
// FIXME the ResourceID is the id of the resource, but we want the id of the mount point so we can fetch that path, well we have the mountpoint path in the receivedshare
// first stat mount point
mountID := &provider.ResourceId{
StorageId: utils.ShareStorageProviderID,
OpaqueId: rs.Share.Id.OpaqueId,
// first stat mount point, but the shares storage provider only handles accepted shares so we send the try to make the requests for only those
if rs.State == collaboration.ShareState_SHARE_STATE_ACCEPTED {
mountID := &provider.ResourceId{
StorageId: utils.ShareStorageProviderID,
OpaqueId: rs.Share.Id.OpaqueId,
}
info, status, err = h.getResourceInfoByID(ctx, client, mountID)
}
info, status, err = h.getResourceInfoByID(ctx, client, mountID)
if err != nil || status.Code != rpc.Code_CODE_OK {
if rs.State != collaboration.ShareState_SHARE_STATE_ACCEPTED || err != nil || status.Code != rpc.Code_CODE_OK {
// fallback to unmounted resource
info, status, err = h.getResourceInfoByID(ctx, client, rs.Share.ResourceId)
if err != nil || status.Code != rpc.Code_CODE_OK {
Expand Down

0 comments on commit fd1fbf3

Please sign in to comment.