diff --git a/services/graph/pkg/service/v0/api_drives_drive_item.go b/services/graph/pkg/service/v0/api_drives_drive_item.go new file mode 100644 index 000000000..d8c0444e3 --- /dev/null +++ b/services/graph/pkg/service/v0/api_drives_drive_item.go @@ -0,0 +1,64 @@ +package svc + +import ( + "context" + "net/http" + + storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/go-chi/render" + libregraph "github.com/owncloud/libre-graph-api-go" + + "github.com/owncloud/ocis/v2/ocis-pkg/log" + "github.com/owncloud/ocis/v2/services/graph/pkg/errorcode" +) + +type DrivesDriveItemServicer interface { + CreateChildren(ctx context.Context, driveId, itemId storageprovider.ResourceId, driveItem libregraph.DriveItem) (libregraph.DriveItem, error) +} + +type DrivesDriveItemService struct { + logger log.Logger +} + +func NewDrivesDriveItemService(logger log.Logger) (DrivesDriveItemService, error) { + return DrivesDriveItemService{ + logger: log.Logger{Logger: logger.With().Str("graph api", "DrivesDriveItemService").Logger()}, + }, nil +} + +func (s DrivesDriveItemService) CreateChildren(ctx context.Context, driveId, itemId storageprovider.ResourceId, driveItem libregraph.DriveItem) (libregraph.DriveItem, error) { + return libregraph.DriveItem{}, nil +} + +type DrivesDriveItemApi struct { + logger log.Logger + drivesDriveItemService DrivesDriveItemServicer +} + +func NewDrivesDriveItemApi(drivesDriveItemService DrivesDriveItemServicer, logger log.Logger) (DrivesDriveItemApi, error) { + return DrivesDriveItemApi{ + logger: log.Logger{Logger: logger.With().Str("graph api", "DrivesDriveItemApi").Logger()}, + drivesDriveItemService: drivesDriveItemService, + }, nil +} + +func (api DrivesDriveItemApi) Routes() []Route { + return []Route{ + {http.MethodPost, "/v1beta1/drives/{driveID}/items/{itemID}/children", api.CreateChildren}, + } +} + +func (api DrivesDriveItemApi) CreateChildren(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + driveID, itemID, err := GetDriveAndItemIDParam(r, &api.logger) + if err != nil { + errorcode.RenderError(w, r, err) + return + } + + driveItem, err := api.drivesDriveItemService. + CreateChildren(ctx, driveID, itemID, libregraph.DriveItem{}) + + render.Status(r, http.StatusOK) + render.JSON(w, r, driveItem) +} diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index cae2d90d5..f11691685 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -366,7 +366,7 @@ func (g Graph) ListPermissions(w http.ResponseWriter, r *http.Request) { return } - _, itemID, err := g.GetDriveAndItemIDParam(r) + _, itemID, err := GetDriveAndItemIDParam(r, g.logger) if err != nil { errorcode.RenderError(w, r, err) return @@ -439,7 +439,7 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { return } - _, itemID, err := g.GetDriveAndItemIDParam(r) + _, itemID, err := GetDriveAndItemIDParam(r, g.logger) if err != nil { errorcode.RenderError(w, r, err) return @@ -646,7 +646,7 @@ func (g Graph) UpdatePermission(w http.ResponseWriter, r *http.Request) { // DeletePermission removes a Permission from a Drive item func (g Graph) DeletePermission(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/graph.go b/services/graph/pkg/service/v0/graph.go index 33893e18e..3767e6dc0 100644 --- a/services/graph/pkg/service/v0/graph.go +++ b/services/graph/pkg/service/v0/graph.go @@ -59,6 +59,18 @@ type RoleService interface { RemoveRoleFromUser(ctx context.Context, in *settingssvc.RemoveRoleFromUserRequest, opts ...client.CallOption) (*emptypb.Empty, error) } +// A Route defines the parameters for an api endpoint +type Route struct { + Method string + Pattern string + HandlerFunc http.HandlerFunc +} + +// Router defines the required methods for retrieving api routes +type Router interface { + Routes() []Route +} + // Graph defines implements the business logic for Service. type Graph struct { config *config.Config diff --git a/services/graph/pkg/service/v0/service.go b/services/graph/pkg/service/v0/service.go index e64e41a3d..5813b08d0 100644 --- a/services/graph/pkg/service/v0/service.go +++ b/services/graph/pkg/service/v0/service.go @@ -204,8 +204,27 @@ func NewService(opts ...Option) (Graph, error) { requireAdmin = options.RequireAdminMiddleware } + drivesDriveItemService, err := NewDrivesDriveItemService(options.Logger) + if err != nil { + return svc, err + } + + drivesDriveItemApi, err := NewDrivesDriveItemApi(drivesDriveItemService, options.Logger) + if err != nil { + return svc, err + } + m.Route(options.Config.HTTP.Root, func(r chi.Router) { r.Use(middleware.StripSlashes) + + for _, router := range []Router{ + drivesDriveItemApi, + } { + for _, route := range router.Routes() { + r.Method(route.Method, route.Pattern, route.HandlerFunc) + } + } + r.Route("/v1beta1", func(r chi.Router) { r.Route("/me", func(r chi.Router) { r.Get("/drives", svc.GetDrives(APIVersion_1_Beta_1)) diff --git a/services/graph/pkg/service/v0/utils.go b/services/graph/pkg/service/v0/utils.go index d566448bf..1756bde7b 100644 --- a/services/graph/pkg/service/v0/utils.go +++ b/services/graph/pkg/service/v0/utils.go @@ -8,6 +8,8 @@ import ( gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/owncloud/ocis/v2/ocis-pkg/log" + "github.com/owncloud/ocis/v2/services/graph/pkg/errorcode" ) @@ -32,28 +34,28 @@ func IsSpaceRoot(rid *storageprovider.ResourceId) bool { // GetDriveAndItemIDParam parses the driveID and itemID from the request, // validates the common fields and returns the parsed IDs if ok. -func (g Graph) GetDriveAndItemIDParam(r *http.Request) (storageprovider.ResourceId, storageprovider.ResourceId, error) { +func GetDriveAndItemIDParam(r *http.Request, logger *log.Logger) (storageprovider.ResourceId, storageprovider.ResourceId, error) { empty := storageprovider.ResourceId{} driveID, err := parseIDParam(r, "driveID") if err != nil { - g.logger.Debug().Err(err).Msg("could not parse driveID") + logger.Debug().Err(err).Msg("could not parse driveID") return empty, empty, errorcode.New(errorcode.InvalidRequest, "invalid driveID") } itemID, err := parseIDParam(r, "itemID") if err != nil { - g.logger.Debug().Err(err).Msg("could not parse itemID") + logger.Debug().Err(err).Msg("could not parse itemID") return empty, empty, errorcode.New(errorcode.InvalidRequest, "invalid itemID") } if itemID.GetOpaqueId() == "" { - g.logger.Debug().Interface("driveID", driveID).Interface("itemID", itemID).Msg("empty item opaqueID") + logger.Debug().Interface("driveID", driveID).Interface("itemID", itemID).Msg("empty item opaqueID") return empty, empty, errorcode.New(errorcode.InvalidRequest, "invalid itemID") } if driveID.GetStorageId() != itemID.GetStorageId() || driveID.GetSpaceId() != itemID.GetSpaceId() { - g.logger.Debug().Interface("driveID", driveID).Interface("itemID", itemID).Msg("driveID and itemID do not match") + logger.Debug().Interface("driveID", driveID).Interface("itemID", itemID).Msg("driveID and itemID do not match") return empty, empty, errorcode.New(errorcode.ItemNotFound, "driveID and itemID do not match") } diff --git a/services/graph/pkg/service/v0/utils_test.go b/services/graph/pkg/service/v0/utils_test.go index 1d1f60952..c1cfa722b 100644 --- a/services/graph/pkg/service/v0/utils_test.go +++ b/services/graph/pkg/service/v0/utils_test.go @@ -11,40 +11,25 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/pkg/storagespace" - "github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults" - identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks" - "github.com/owncloud/ocis/v2/ocis-pkg/shared" + "github.com/owncloud/ocis/v2/ocis-pkg/conversions" + "github.com/owncloud/ocis/v2/ocis-pkg/log" service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0" ) var _ = Describe("Utils", func() { - var ( - svc service.Graph - ) - - BeforeEach(func() { - cfg := defaults.FullDefaultConfig() - cfg.GRPCClientTLS = &shared.GRPCClientTLS{} - - identityBackend := &identitymocks.Backend{} - svc, _ = service.NewService( - service.Config(cfg), - service.WithIdentityBackend(identityBackend), - ) - }) - DescribeTable("GetDriveAndItemIDParam", func(driveID, itemID string, shouldPass bool) { rctx := chi.NewRouteContext() rctx.URLParams.Add("driveID", driveID) rctx.URLParams.Add("itemID", itemID) - extractedDriveID, extractedItemID, err := svc.GetDriveAndItemIDParam( + extractedDriveID, extractedItemID, err := service.GetDriveAndItemIDParam( httptest.NewRequest(http.MethodGet, "/", nil). WithContext( context.WithValue(context.Background(), chi.RouteCtxKey, rctx), ), + conversions.ToPointer(log.NopLogger()), ) switch shouldPass {