From 50ea1f46e791bb66b4dd10ea865934107634c387 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Mon, 29 Jan 2024 15:38:15 +0100 Subject: [PATCH] enhancement: add basic share accept feature, error handling and detailed implementation still missed (cherry picked from commit a5b70b3d7a7d4471f97643e5a6ad0a4de12f2b03) --- .../pkg/service/v0/api_drives_drive_item.go | 95 +++++++++++++++++-- services/graph/pkg/service/v0/driveitems.go | 2 +- services/graph/pkg/service/v0/links.go | 5 +- services/graph/pkg/service/v0/service.go | 2 +- 4 files changed, 93 insertions(+), 11 deletions(-) diff --git a/services/graph/pkg/service/v0/api_drives_drive_item.go b/services/graph/pkg/service/v0/api_drives_drive_item.go index d8c0444e31..edf46f92bb 100644 --- a/services/graph/pkg/service/v0/api_drives_drive_item.go +++ b/services/graph/pkg/service/v0/api_drives_drive_item.go @@ -4,50 +4,131 @@ import ( "context" "net/http" + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/go-chi/render" libregraph "github.com/owncloud/libre-graph-api-go" + "google.golang.org/protobuf/types/known/fieldmaskpb" "github.com/owncloud/ocis/v2/ocis-pkg/log" "github.com/owncloud/ocis/v2/services/graph/pkg/errorcode" ) -type DrivesDriveItemServicer interface { +// DrivesDriveItemProvider is the interface that needs to be implemented by the individual space service +type DrivesDriveItemProvider interface { CreateChildren(ctx context.Context, driveId, itemId storageprovider.ResourceId, driveItem libregraph.DriveItem) (libregraph.DriveItem, error) } +// DrivesDriveItemService contains the production business logic for everything that relates to drives type DrivesDriveItemService struct { - logger log.Logger + logger log.Logger + gatewaySelector pool.Selectable[gateway.GatewayAPIClient] } -func NewDrivesDriveItemService(logger log.Logger) (DrivesDriveItemService, error) { +// NewDrivesDriveItemService creates a new DrivesDriveItemService +func NewDrivesDriveItemService(logger log.Logger, gatewaySelector pool.Selectable[gateway.GatewayAPIClient]) (DrivesDriveItemService, error) { return DrivesDriveItemService{ - logger: log.Logger{Logger: logger.With().Str("graph api", "DrivesDriveItemService").Logger()}, + logger: log.Logger{Logger: logger.With().Str("graph api", "DrivesDriveItemService").Logger()}, + gatewaySelector: gatewaySelector, }, nil } -func (s DrivesDriveItemService) CreateChildren(ctx context.Context, driveId, itemId storageprovider.ResourceId, driveItem libregraph.DriveItem) (libregraph.DriveItem, error) { +// CreateChildren is currently only used for accepting pending//dangling shares. +// fixMe: currently the driveItem is not used, why is it needed? +func (s DrivesDriveItemService) CreateChildren(ctx context.Context, driveId, itemId storageprovider.ResourceId, _ libregraph.DriveItem) (libregraph.DriveItem, error) { + gatewayClient, err := s.gatewaySelector.Next() + if err != nil { + return libregraph.DriveItem{}, err + } + + receivedSharesResponse, err := gatewayClient.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{ + Filters: []*collaboration.Filter{ + { + Type: collaboration.Filter_TYPE_STATE, + Term: &collaboration.Filter_State{ + State: collaboration.ShareState_SHARE_STATE_PENDING, + }, + }, + { + Type: collaboration.Filter_TYPE_STATE, + Term: &collaboration.Filter_State{ + State: collaboration.ShareState_SHARE_STATE_REJECTED, + }, + }, + { + Type: collaboration.Filter_TYPE_RESOURCE_ID, + Term: &collaboration.Filter_ResourceId{ + ResourceId: &storageprovider.ResourceId{ + StorageId: driveId.GetStorageId(), + SpaceId: driveId.GetSpaceId(), + OpaqueId: itemId.GetOpaqueId(), + }, + }, + }, + }, + }) + + for _, receivedShare := range receivedSharesResponse.GetShares() { + mountPoint := receivedShare.GetMountPoint() + if mountPoint == nil { + // fixMe: should not happen, add exception handling + continue + } + + receivedShare.State = collaboration.ShareState_SHARE_STATE_ACCEPTED + receivedShare.MountPoint = &storageprovider.Reference{ + // keep the original mount point path, + // custom path handling should come here later + Path: mountPoint.GetPath(), + } + + updateReceivedShareRequest := &collaboration.UpdateReceivedShareRequest{ + Share: receivedShare, + // mount_point currently contain no changes, this is for future use + // state changes from pending or rejected to accept + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state", "mount_point"}}, + } + + //fixMe: should be processed in parallel + updateReceivedShareResponse, err := gatewayClient.UpdateReceivedShare(ctx, updateReceivedShareRequest) + if err != nil { + // fixMe: should not happen, add exception handling + continue + } + + // fixMe: send to nirvana, add status handling + _ = updateReceivedShareResponse + } + + // fixMe: return a concrete driveItem return libregraph.DriveItem{}, nil } +// DrivesDriveItemApi is the api that registers the http endpoints which expose needed operation to the graph api. +// the business logic is delegated to the space service and further down to the cs3 client. type DrivesDriveItemApi struct { logger log.Logger - drivesDriveItemService DrivesDriveItemServicer + drivesDriveItemService DrivesDriveItemProvider } -func NewDrivesDriveItemApi(drivesDriveItemService DrivesDriveItemServicer, logger log.Logger) (DrivesDriveItemApi, error) { +// NewDrivesDriveItemApi creates a new DrivesDriveItemApi +func NewDrivesDriveItemApi(drivesDriveItemService DrivesDriveItemProvider, logger log.Logger) (DrivesDriveItemApi, error) { return DrivesDriveItemApi{ logger: log.Logger{Logger: logger.With().Str("graph api", "DrivesDriveItemApi").Logger()}, drivesDriveItemService: drivesDriveItemService, }, nil } +// Routes returns the routes that should be registered for this api func (api DrivesDriveItemApi) Routes() []Route { return []Route{ {http.MethodPost, "/v1beta1/drives/{driveID}/items/{itemID}/children", api.CreateChildren}, } } +// CreateChildren exposes the CreateChildren operation of the space service as an http endpoint func (api DrivesDriveItemApi) CreateChildren(w http.ResponseWriter, r *http.Request) { ctx := r.Context() driveID, itemID, err := GetDriveAndItemIDParam(r, &api.logger) diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index f116916856..f6dd52b0a5 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -580,7 +580,7 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { // UpdatePermission updates a Permission of a Drive item func (g Graph) UpdatePermission(w http.ResponseWriter, r *http.Request) { - _, itemID, err := g.GetDriveAndItemIDParam(r) + _, itemID, err := GetDriveAndItemIDParam(r, g.logger) if err != nil { errorcode.RenderError(w, r, err) return diff --git a/services/graph/pkg/service/v0/links.go b/services/graph/pkg/service/v0/links.go index 684dd8e67b..0a71dc4fef 100644 --- a/services/graph/pkg/service/v0/links.go +++ b/services/graph/pkg/service/v0/links.go @@ -18,6 +18,7 @@ import ( "github.com/go-chi/chi/v5" "github.com/go-chi/render" libregraph "github.com/owncloud/libre-graph-api-go" + "github.com/owncloud/ocis/v2/services/graph/pkg/errorcode" "github.com/owncloud/ocis/v2/services/graph/pkg/linktype" ) @@ -27,7 +28,7 @@ func (g Graph) CreateLink(w http.ResponseWriter, r *http.Request) { logger := g.logger.SubloggerWithRequestID(r.Context()) logger.Info().Msg("calling create link") - _, driveItemID, err := g.GetDriveAndItemIDParam(r) + _, driveItemID, err := GetDriveAndItemIDParam(r, g.logger) if err != nil { errorcode.RenderError(w, r, err) return @@ -60,7 +61,7 @@ func (g Graph) CreateLink(w http.ResponseWriter, r *http.Request) { // SetLinkPassword sets public link password on the cs3 api func (g Graph) SetLinkPassword(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - _, itemID, err := g.GetDriveAndItemIDParam(r) + _, itemID, err := GetDriveAndItemIDParam(r, g.logger) if err != nil { errorcode.RenderError(w, r, err) return diff --git a/services/graph/pkg/service/v0/service.go b/services/graph/pkg/service/v0/service.go index 5813b08d05..7cb180c819 100644 --- a/services/graph/pkg/service/v0/service.go +++ b/services/graph/pkg/service/v0/service.go @@ -204,7 +204,7 @@ func NewService(opts ...Option) (Graph, error) { requireAdmin = options.RequireAdminMiddleware } - drivesDriveItemService, err := NewDrivesDriveItemService(options.Logger) + drivesDriveItemService, err := NewDrivesDriveItemService(options.Logger, options.GatewaySelector) if err != nil { return svc, err }