Repository: owncloud/ocis
Pull request #8281 (2024-01-24 15:42:07)

Fix NatsRegistry
Fixes a rather strange issue with the natsjskv registry.

Thanks @butonic @rhafer @dragonchaser @fschade for the help in debugging this!


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c749f8486b..57a761f61b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -54,6 +54,7 @@ The following sections list the changes for unreleased.
 * Bugfix - Graph/sharedWithMe works for shares from project spaces now: [#8233](https://github.com/owncloud/ocis/pull/8233)
 * Bugfix - Fix PATCH/DELETE status code for drives that don't support them: [#8235](https://github.com/owncloud/ocis/pull/8235)
 * Bugfix - Fix nats authentication: [#8236](https://github.com/owncloud/ocis/pull/8236)
+* Bugfix - Apply role constraints when creating shares via the graph API: [#8247](https://github.com/owncloud/ocis/pull/8247)
 * Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269)
 * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985)
 * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062)
@@ -164,6 +165,15 @@ The following sections list the changes for unreleased.
 
    https://github.com/owncloud/ocis/pull/8236
 
+* Bugfix - Apply role constraints when creating shares via the graph API: [#8247](https://github.com/owncloud/ocis/pull/8247)
+
+   We fixed a bug in the graph API for creating and updating shares so that
+   Spaceroot specific roles like 'Manager' and 'Co-owner' can no longer be assigned
+   for shares on files or directories.
+
+   https://github.com/owncloud/ocis/issues/8131
+   https://github.com/owncloud/ocis/pull/8247
+
 * Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269)
 
    We fixed the race condition that led to concurrent map access in a publicshare
diff --git a/changelog/unreleased/fix-nats-registry.md b/changelog/unreleased/fix-nats-registry.md
new file mode 100644
index 00000000000..ba5b29d0e38
--- /dev/null
+++ b/changelog/unreleased/fix-nats-registry.md
@@ -0,0 +1,6 @@
+Bugfix: Fix nats registry
+
+The nats registry would behave badly when configuring `nats-js-kv` via envvar. Reason is the way go-micro initializes.
+It took 5 developers to find the issue and the fix so the details cannot be shared here. Just accept that it is working now
+
+https://github.com/owncloud/ocis/pull/8281
diff --git a/changelog/unreleased/sharing-ng-roleconditions.md b/changelog/unreleased/sharing-ng-roleconditions.md
new file mode 100644
index 00000000000..efad06c1043
--- /dev/null
+++ b/changelog/unreleased/sharing-ng-roleconditions.md
@@ -0,0 +1,8 @@
+Bugfix: apply role constraints when creating shares via the graph API
+
+We fixed a bug in the graph API for creating and updating shares so that
+Spaceroot specific roles like 'Manager' and 'Co-owner' can no longer be
+assigned for shares on files or directories.
+
+https://github.com/owncloud/ocis/pull/8247
+https://github.com/owncloud/ocis/issues/8131
diff --git a/ocis-pkg/natsjsregistry/options.go b/ocis-pkg/natsjsregistry/options.go
index a6e862a62a2..dfcda616a59 100644
--- a/ocis-pkg/natsjsregistry/options.go
+++ b/ocis-pkg/natsjsregistry/options.go
@@ -10,7 +10,6 @@ import (
 
 type storeOptionsKey struct{}
 type expiryKey struct{}
-type authKey struct{}
 
 // StoreOptions sets the options for the underlying store
 func StoreOptions(opts []store.Option) registry.Option {
@@ -31,13 +30,3 @@ func ServiceExpiry(t time.Duration) registry.Option {
 		o.Context = context.WithValue(o.Context, expiryKey{}, t)
 	}
 }
-
-// Authenticate sets the username/password for the nats connection
-func Authenticate(username, password string) registry.Option {
-	return func(o *registry.Options) {
-		if o.Context == nil {
-			o.Context = context.Background()
-		}
-		o.Context = context.WithValue(o.Context, authKey{}, []string{username, password})
-	}
-}
diff --git a/ocis-pkg/natsjsregistry/registry.go b/ocis-pkg/natsjsregistry/registry.go
index 857b4e5198b..feeac744b9f 100644
--- a/ocis-pkg/natsjsregistry/registry.go
+++ b/ocis-pkg/natsjsregistry/registry.go
@@ -5,6 +5,8 @@ import (
 	"context"
 	"encoding/json"
 	"errors"
+	"os"
+	"strings"
 	"time"
 
 	natsjskv "github.com/go-micro/plugins/v4/store/nats-js-kv"
@@ -14,7 +16,12 @@ import (
 	"go-micro.dev/v4/util/cmd"
 )
 
-var _registryName = "nats-js-kv"
+var (
+	_registryName        = "nats-js-kv"
+	_registryAddressEnv  = "MICRO_REGISTRY_ADDRESS"
+	_registryUsernameEnv = "MICRO_REGISTRY_AUTH_USERNAME"
+	_registryPasswordEnv = "MICRO_REGISTRY_AUTH_PASSWORD"
+)
 
 func init() {
 	cmd.DefaultRegistries[_registryName] = NewRegistry
@@ -31,7 +38,7 @@ func NewRegistry(opts ...registry.Option) registry.Registry {
 	exp, _ := options.Context.Value(expiryKey{}).(time.Duration)
 	return &storeregistry{
 		opts:   options,
-		store:  natsjskv.NewStore(append(storeOptions(options), natsjskv.DefaultMemory())...),
+		store:  natsjskv.NewStore(storeOptions(options)...),
 		typ:    _registryName,
 		expiry: exp,
 	}
@@ -127,18 +134,31 @@ func (n *storeregistry) String() string {
 
 func storeOptions(opts registry.Options) []store.Option {
 	storeoptions := []store.Option{
-		store.Nodes(opts.Addrs...),
 		store.Database("service-registry"),
 		store.Table("service-registry"),
+		natsjskv.DefaultMemory(),
 	}
-	if so, ok := opts.Context.Value(storeOptionsKey{}).([]store.Option); ok {
-		storeoptions = append(storeoptions, so...)
+
+	addr := []string{"127.0.0.1:9233"}
+	if len(opts.Addrs) > 0 {
+		addr = opts.Addrs
+	} else if a := strings.Split(os.Getenv(_registryAddressEnv), ","); len(a) > 0 && a[0] != "" {
+		addr = a
 	}
+	storeoptions = append(storeoptions, store.Nodes(addr...))
+
 	natsOptions := nats.GetDefaultOptions()
 	natsOptions.Name = "nats-js-kv-registry"
-	if auth, ok := opts.Context.Value(authKey{}).([]string); ok {
-		natsOptions.User = auth[0]
-		natsOptions.Password = auth[1]
+	natsOptions.User, natsOptions.Password = getAuth()
+	storeoptions = append(storeoptions, natsjskv.NatsOptions(natsOptions))
+
+	if so, ok := opts.Context.Value(storeOptionsKey{}).([]store.Option); ok {
+		storeoptions = append(storeoptions, so...)
 	}
-	return append(storeoptions, natsjskv.NatsOptions(natsOptions))
+
+	return storeoptions
+}
+
+func getAuth() (string, string) {
+	return os.Getenv(_registryUsernameEnv), os.Getenv(_registryPasswordEnv)
 }
diff --git a/ocis-pkg/registry/registry.go b/ocis-pkg/registry/registry.go
index 0b6b3e71f03..1672a1a8e17 100644
--- a/ocis-pkg/registry/registry.go
+++ b/ocis-pkg/registry/registry.go
@@ -20,10 +20,8 @@ import (
 )
 
 const (
-	registryEnv         = "MICRO_REGISTRY"
-	registryAddressEnv  = "MICRO_REGISTRY_ADDRESS"
-	registryUsernameEnv = "MICRO_REGISTRY_AUTH_USERNAME"
-	registryPasswordEnv = "MICRO_REGISTRY_AUTH_PASSWORD"
+	_registryEnv        = "MICRO_REGISTRY"
+	_registryAddressEnv = "MICRO_REGISTRY_ADDRESS"
 )
 
 var (
@@ -64,7 +62,6 @@ func GetRegistry(opts ...Option) mRegistry.Registry {
 		case "natsjs", "nats-js", "nats-js-kv": // for backwards compatibility - we will stick with one of those
 			_reg = natsjsregistry.NewRegistry(
 				mRegistry.Addrs(cfg.Addresses...),
-				natsjsregistry.Authenticate(cfg.Username, cfg.Password),
 			)
 		case "memory":
 			_reg = memr.NewRegistry()
@@ -112,15 +109,13 @@ func getEnvs(opts ...Option) *Config {
 	cfg := &Config{
 		Type:      "nats-js-kv",
 		Addresses: []string{"127.0.0.1:9233"},
-		Username:  os.Getenv(registryUsernameEnv),
-		Password:  os.Getenv(registryPasswordEnv),
 	}
 
-	if s := os.Getenv(registryEnv); s != "" {
+	if s := os.Getenv(_registryEnv); s != "" {
 		cfg.Type = s
 	}
 
-	if s := strings.Split(os.Getenv(registryAddressEnv), ","); len(s) > 0 && s[0] != "" {
+	if s := strings.Split(os.Getenv(_registryAddressEnv), ","); len(s) > 0 && s[0] != "" {
 		cfg.Addresses = s
 	}
 
diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go
index da010478b4f..ea6fc0ad757 100644
--- a/services/graph/pkg/service/v0/driveitems.go
+++ b/services/graph/pkg/service/v0/driveitems.go
@@ -378,6 +378,11 @@ func (g Graph) ListPermissions(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	condition := unifiedrole.UnifiedRoleConditionGrantee
+	if IsSpaceRoot(statResponse.GetInfo().GetId()) {
+		condition = unifiedrole.UnifiedRoleConditionOwner
+	}
+
 	permissionSet := *statResponse.GetInfo().GetPermissionSet()
 	allowedActions := unifiedrole.CS3ResourcePermissionsToLibregraphActions(permissionSet)
 
@@ -386,7 +391,7 @@ func (g Graph) ListPermissions(w http.ResponseWriter, r *http.Request) {
 		LibreGraphPermissionsRolesAllowedValues: conversions.ToValueSlice(
 			unifiedrole.GetApplicableRoleDefinitionsForActions(
 				allowedActions,
-				unifiedrole.UnifiedRoleConditionGrantee,
+				condition,
 				g.config.FilesSharing.EnableResharing,
 				false,
 			),
@@ -452,6 +457,18 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
+	statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: &itemID}})
+	if errCode := errorcode.FromStat(statResponse, err); errCode != nil {
+		g.logger.Warn().Err(errCode).Interface("stat.res", statResponse).Msg("stat failed")
+		errCode.Render(w, r)
+		return
+	}
+
+	condition := unifiedrole.UnifiedRoleConditionGrantee
+	if IsSpaceRoot(statResponse.GetInfo().GetId()) {
+		condition = unifiedrole.UnifiedRoleConditionOwner
+	}
+
 	unifiedRolePermissions := []*libregraph.UnifiedRolePermission{{AllowedResourceActions: driveItemInvite.LibreGraphPermissionsActions}}
 	for _, roleID := range driveItemInvite.GetRoles() {
 		role, err := unifiedrole.NewUnifiedRoleFromID(roleID, g.config.FilesSharing.EnableResharing)
@@ -461,14 +478,13 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 
-		unifiedRolePermissions = append(unifiedRolePermissions, conversions.ToPointerSlice(role.GetRolePermissions())...)
-	}
+		allowedResourceActions := unifiedrole.GetAllowedResourceActions(role, condition)
+		if len(allowedResourceActions) == 0 {
+			errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "role not applicable to this resource")
+			return
+		}
 
-	statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: &itemID}})
-	if errCode := errorcode.FromStat(statResponse, err); errCode != nil {
-		g.logger.Warn().Err(errCode).Interface("stat.res", statResponse).Msg("stat failed")
-		errCode.Render(w, r)
-		return
+		unifiedRolePermissions = append(unifiedRolePermissions, conversions.ToPointerSlice(role.GetRolePermissions())...)
 	}
 
 	driveRecipient := driveItemInvite.GetRecipients()[0]
@@ -486,7 +502,7 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) {
 	}
 
 	permission := &libregraph.Permission{}
-	if role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(*cs3ResourcePermissions, unifiedrole.UnifiedRoleConditionGrantee, g.config.FilesSharing.EnableResharing); role != nil {
+	if role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(*cs3ResourcePermissions, condition, g.config.FilesSharing.EnableResharing); role != nil {
 		permission.Roles = []string{role.GetId()}
 	}
 
diff --git a/services/graph/pkg/unifiedrole/unifiedrole.go b/services/graph/pkg/unifiedrole/unifiedrole.go
index 58890f8e81c..fce338767c1 100644
--- a/services/graph/pkg/unifiedrole/unifiedrole.go
+++ b/services/graph/pkg/unifiedrole/unifiedrole.go
@@ -153,7 +153,7 @@ func NewCoownerUnifiedRole() *libregraph.UnifiedRoleDefinition {
 		RolePermissions: []libregraph.UnifiedRolePermission{
 			{
 				AllowedResourceActions: convert(r),
-				Condition:              proto.String(UnifiedRoleConditionGrantee),
+				Condition:              proto.String(UnifiedRoleConditionOwner),
 			},
 		},
 		LibreGraphWeight: proto.Int32(0),
@@ -185,10 +185,6 @@ func NewManagerUnifiedRole() *libregraph.UnifiedRoleDefinition {
 		Description: proto.String("Grants manager permissions on a resource. Semantically equivalent to co-owner"),
 		DisplayName: displayName(r),
 		RolePermissions: []libregraph.UnifiedRolePermission{
-			{
-				AllowedResourceActions: convert(r),
-				Condition:              proto.String(UnifiedRoleConditionGrantee),
-			},
 			{
 				AllowedResourceActions: convert(r),
 				Condition:              proto.String(UnifiedRoleConditionOwner),


Test patch:
diff --git a/services/graph/pkg/service/v0/driveitems_test.go b/services/graph/pkg/service/v0/driveitems_test.go
index 7513ec290cd..69cacd7e90a 100644
--- a/services/graph/pkg/service/v0/driveitems_test.go
+++ b/services/graph/pkg/service/v0/driveitems_test.go
@@ -685,6 +685,25 @@ var _ = Describe("Driveitems", func() {
 			_, ok := res.GetRolesOk()
 			Expect(ok).To(BeTrue())
 		})
+		It("fails to update the share permissions for a file share when setting a space specific role", func() {
+			updateShareMock := gatewayClient.On("UpdateShare",
+				mock.Anything,
+				mock.MatchedBy(func(req *collaboration.UpdateShareRequest) bool {
+					return req.GetShare().GetId().GetOpaqueId() == "permissionid"
+				}),
+			)
+			updateShareMock.Return(updateShareMockResponse, nil)
+
+			driveItemPermission.SetRoles([]string{unifiedrole.NewSpaceViewerUnifiedRole().GetId()})
+			body, err := driveItemPermission.MarshalJSON()
+			Expect(err).To(BeNil())
+			svc.UpdatePermission(
+				rr,
+				httptest.NewRequest(http.MethodPatch, "/", strings.NewReader(string(body))).
+					WithContext(ctx),
+			)
+			Expect(rr.Code).To(Equal(http.StatusBadRequest))
+		})
 		It("updates the share permissions when changing the resource permission actions", func() {
 			updateShareMock := gatewayClient.On("UpdateShare",
 				mock.Anything,
@@ -1007,6 +1026,17 @@ var _ = Describe("Driveitems", func() {
 			Expect(jsonData.Get("0.roles.0").String()).To(Equal(unifiedrole.NewViewerUnifiedRole(true).GetId()))
 		})
 
+		It("fails with wrong role", func() {
+			driveItemInvite.Roles = []string{unifiedrole.NewCoownerUnifiedRole().GetId()}
+			svc.Invite(
+				rr,
+				httptest.NewRequest(http.MethodPost, "/", toJSONReader(driveItemInvite)).
+					WithContext(ctx),
+			)
+
+			Expect(rr.Code).To(Equal(http.StatusBadRequest))
+		})
+
 		It("with actions (happy path)", func() {
 			driveItemInvite.Roles = nil
 			driveItemInvite.LibreGraphPermissionsActions = []string{unifiedrole.DriveItemContentRead}
diff --git a/services/graph/pkg/unifiedrole/unifiedrole_test.go b/services/graph/pkg/unifiedrole/unifiedrole_test.go
index f11225a5a5e..12248a375b2 100644
--- a/services/graph/pkg/unifiedrole/unifiedrole_test.go
+++ b/services/graph/pkg/unifiedrole/unifiedrole_test.go
@@ -27,8 +27,7 @@ var _ = Describe("unifiedroles", func() {
 		Entry(rConversions.RoleViewer, rConversions.NewViewerRole(true), unifiedrole.NewViewerUnifiedRole(true), unifiedrole.UnifiedRoleConditionGrantee),
 		Entry(rConversions.RoleEditor, rConversions.NewEditorRole(true), unifiedrole.NewEditorUnifiedRole(true), unifiedrole.UnifiedRoleConditionGrantee),
 		Entry(rConversions.RoleFileEditor, rConversions.NewFileEditorRole(true), unifiedrole.NewFileEditorUnifiedRole(true), unifiedrole.UnifiedRoleConditionGrantee),
-		Entry(rConversions.RoleCoowner, rConversions.NewCoownerRole(), unifiedrole.NewCoownerUnifiedRole(), unifiedrole.UnifiedRoleConditionGrantee),
-		Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), unifiedrole.UnifiedRoleConditionGrantee),
+		Entry(rConversions.RoleCoowner, rConversions.NewCoownerRole(), unifiedrole.NewCoownerUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner),
 		Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner),
 		Entry(rConversions.RoleSpaceViewer, rConversions.NewSpaceViewerRole(), unifiedrole.NewSpaceViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner),
 		Entry(rConversions.RoleSpaceEditor, rConversions.NewSpaceEditorRole(), unifiedrole.NewSpaceEditorUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner),
@@ -208,6 +207,17 @@ var _ = Describe("unifiedroles", func() {
 					unifiedrole.NewViewerUnifiedRole(false),
 					unifiedrole.NewFileEditorUnifiedRole(false),
 					unifiedrole.NewEditorUnifiedRole(false),
+				},
+			),
+
+			Entry(
+				"GetBuiltinRoleDefinitionList",
+				rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList(false)...),
+				unifiedrole.UnifiedRoleConditionOwner,
+				false,
+				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSpaceViewerUnifiedRole(),
+					unifiedrole.NewSpaceEditorUnifiedRole(),
 					unifiedrole.NewCoownerUnifiedRole(),
 					unifiedrole.NewManagerUnifiedRole(),
 				},
@@ -223,8 +233,6 @@ var _ = Describe("unifiedroles", func() {
 					unifiedrole.NewViewerUnifiedRole(true),
 					unifiedrole.NewFileEditorUnifiedRole(true),
 					unifiedrole.NewEditorUnifiedRole(true),
-					unifiedrole.NewCoownerUnifiedRole(),
-					unifiedrole.NewManagerUnifiedRole(),
 				},
 			),
 
diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md
index d9b6da351ea..e4ecfd70210 100644
--- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md
+++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md
@@ -45,18 +45,6 @@ The expected failures in this file are from features in the owncloud/ocis repo.
 
 - [apiGraphUserGroup/deleteGroup.feature:67](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature#L67)
 
-#### [CORS headers are not identical with oC10 headers](https://github.com/owncloud/ocis/issues/5195)
-
-- [apiCors/cors.feature:28](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L28)
-- [apiCors/cors.feature:29](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L29)
-- [apiCors/cors.feature:30](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L30)
-- [apiCors/cors.feature:31](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L31)
-
-#### [Requests with invalid credentials do not return CORS headers](https://github.com/owncloud/ocis/issues/5194)
-
-- [apiCors/cors.feature:70](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L70)
-- [apiCors/cors.feature:71](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L71)
-
 #### [A User can get information of another user with Graph API](https://github.com/owncloud/ocis/issues/5125)
 
 - [apiGraphUserGroup/getUser.feature:89](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L89)
@@ -270,10 +258,10 @@ The expected failures in this file are from features in the owncloud/ocis repo.
 - [apiSharingNg/linkShare.feature:453](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L453)
 - [apiSharingNg/linkShare.feature:455](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L455)
 - [apiSharingNg/linkShare.feature:456](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L456)
-- [apiSharingNg/deletePermissions.feature:138](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L138)
-- [apiSharingNg/deletePermissions.feature:155](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L155)
-- [apiSharingNg/deletePermissions.feature:176](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L176)
-- [apiSharingNg/deletePermissions.feature:195](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L195)
+- [apiSharingNg/deletePermissions.feature:130](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L130)
+- [apiSharingNg/deletePermissions.feature:147](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L147)
+- [apiSharingNg/deletePermissions.feature:168](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L168)
+- [apiSharingNg/deletePermissions.feature:187](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L187)
 
 ### [sharee (editor role) MOVE a file by file-id into same shared folder returns 403](https://github.com/owncloud/ocis/issues/7617)
 
diff --git a/tests/acceptance/features/apiCors/cors.feature b/tests/acceptance/features/apiCors/cors.feature
index a0a8da4cde8..28131c8a08f 100644
--- a/tests/acceptance/features/apiCors/cors.feature
+++ b/tests/acceptance/features/apiCors/cors.feature
@@ -18,11 +18,10 @@ Feature: CORS headers
     Then the OCS status code should be "<ocs-code>"
     And the HTTP status code should be "<http-code>"
     And the following headers should be set
-      | header                        | value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
-      | Access-Control-Allow-Headers  | OC-Checksum,OC-Total-Length,OCS-APIREQUEST,X-OC-Mtime,OC-RequestAppPassword,Accept,Authorization,Brief,Content-Length,Content-Range,Content-Type,Date,Depth,Destination,Host,If,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Lock-Token,Overwrite,Prefer,Range,Schedule-Reply,Timeout,User-Agent,X-Expected-Entity-Length,Accept-Language,Access-Control-Request-Method,Access-Control-Allow-Origin,Cache-Control,ETag,OC-Autorename,OC-CalDav-Import,OC-Chunked,OC-Etag,OC-FileId,OC-LazyOps,OC-Total-File-Length,Origin,X-Request-ID,X-Requested-With |
-      | Access-Control-Expose-Headers | Content-Location,DAV,ETag,Link,Lock-Token,OC-ETag,OC-Checksum,OC-FileId,OC-JobStatus-Location,OC-RequestAppPassword,Vary,Webdav-Location,X-Sabre-Status                                                                                                                                                                                                                                                                                                                                                                                                                                   |
-      | Access-Control-Allow-Origin   | https://aphno.badal                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
-      | Access-Control-Allow-Methods  | GET,OPTIONS,POST,PUT,DELETE,MKCOL,PROPFIND,PATCH,PROPPATCH,REPORT                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
+      | header                           | value               |
+      | Access-Control-Expose-Headers    | Location            |
+      | Access-Control-Allow-Origin      | https://aphno.badal |
+      | Access-Control-Allow-Credentials | true                |
     Examples:
       | ocs_api_version | endpoint                          | ocs-code | http-code |
       | 1               | /config                           | 100      | 200       |
@@ -52,20 +51,22 @@ Feature: CORS headers
       | 2               | /apps/files_sharing/api/v1/shares | 200      | 200       |
 
   @issue-5194
-  Scenario Outline: CORS headers should be returned when an invalid password is used
+  Scenario Outline: CORS headers should be returned when an preflight request is sent
     Given using OCS API version "<ocs_api_version>"
-    When user "Alice" sends HTTP method "GET" to OCS API endpoint "<endpoint>" with headers using password "invalid"
-      | header | value               |
-      | Origin | https://aphno.badal |
-    Then the OCS status code should be "997"
-    And the HTTP status code should be "401"
+    When user "Alice" sends HTTP method "OPTIONS" to OCS API endpoint "<endpoint>" with headers
+      | header                         | value                                                                                                                                                                                                                                                                                                                                                 |
+      | Origin                         | https://aphno.badal                                                                                                                                                                                                                                                                                                                                   |
+      | Access-Control-Request-Headers | Origin, Accept, Content-Type, Depth, Authorization, Ocs-Apirequest, If-None-Match, If-Match, Destination, Overwrite, X-Request-Id, X-Requested-With, Tus-Resumable, Tus-Checksum-Algorithm, Upload-Concat, Upload-Length, Upload-Metadata, Upload-Defer-Length, Upload-Expires, Upload-Checksum, Upload-Offset, X-Http-Method-Override, Cache-Control |
+      | Access-Control-Request-Method  | <request_method>                                                                                                                                                                                                                                                                                                                                      |
+    And the HTTP status code should be "204"
     And the following headers should be set
-      | header                        | value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
-      | Access-Control-Allow-Headers  | OC-Checksum,OC-Total-Length,OCS-APIREQUEST,X-OC-Mtime,OC-RequestAppPassword,Accept,Authorization,Brief,Content-Length,Content-Range,Content-Type,Date,Depth,Destination,Host,If,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Lock-Token,Overwrite,Prefer,Range,Schedule-Reply,Timeout,User-Agent,X-Expected-Entity-Length,Accept-Language,Access-Control-Request-Method,Access-Control-Allow-Origin,Cache-Control,ETag,OC-Autorename,OC-CalDav-Import,OC-Chunked,OC-Etag,OC-FileId,OC-LazyOps,OC-Total-File-Length,Origin,X-Request-ID,X-Requested-With |
-      | Access-Control-Expose-Headers | Content-Location,DAV,ETag,Link,Lock-Token,OC-ETag,OC-Checksum,OC-FileId,OC-JobStatus-Location,OC-RequestAppPassword,Vary,Webdav-Location,X-Sabre-Status                                                                                                                                                                                                                                                                                                                                                                                                                                   |
-      | Access-Control-Allow-Origin   | https://aphno.badal                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
-      | Access-Control-Allow-Methods  | GET,OPTIONS,POST,PUT,DELETE,MKCOL,PROPFIND,PATCH,PROPPATCH,REPORT                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
+      | header                       | value                                                                                                                                                                                                                                                                                                                                                 |
+      | Access-Control-Allow-Headers | Origin, Accept, Content-Type, Depth, Authorization, Ocs-Apirequest, If-None-Match, If-Match, Destination, Overwrite, X-Request-Id, X-Requested-With, Tus-Resumable, Tus-Checksum-Algorithm, Upload-Concat, Upload-Length, Upload-Metadata, Upload-Defer-Length, Upload-Expires, Upload-Checksum, Upload-Offset, X-Http-Method-Override, Cache-Control |
+      | Access-Control-Allow-Origin  | https://aphno.badal                                                                                                                                                                                                                                                                                                                                   |
+      | Access-Control-Allow-Methods | <request_method>                                                                                                                                                                                                                                                                                                                                      |
     Examples:
-      | ocs_api_version | endpoint                          |
-      | 1               | /apps/files_sharing/api/v1/shares |
-      | 2               | /apps/files_sharing/api/v1/shares |
+      | ocs_api_version |  | endpoint                          | request_method |
+      | 1               |  | /apps/files_sharing/api/v1/shares | GET            |
+      | 2               |  | /apps/files_sharing/api/v1/shares | PUT            |
+      | 1               |  | /apps/files_sharing/api/v1/shares | DELETE         |
+      | 2               |  | /apps/files_sharing/api/v1/shares | POST           |
diff --git a/tests/acceptance/features/apiSharingNg/deletePermissions.feature b/tests/acceptance/features/apiSharingNg/deletePermissions.feature
index 83053a67184..222514e4c43 100644
--- a/tests/acceptance/features/apiSharingNg/deletePermissions.feature
+++ b/tests/acceptance/features/apiSharingNg/deletePermissions.feature
@@ -29,9 +29,7 @@ Feature: Remove access to a drive item
       | File Editor     | file          | textfile.txt  |
       | Viewer          | folder        | FolderToShare |
       | Editor          | folder        | FolderToShare |
-      | Co Owner        | folder        | FolderToShare |
       | Uploader        | folder        | FolderToShare |
-      | Manager         | folder        | FolderToShare |
 
 
   Scenario Outline: user removes access to resource inside of a project space in the user share
@@ -56,9 +54,7 @@ Feature: Remove access to a drive item
       | File Editor     | file          | textfile.txt  |
       | Viewer          | folder        | FolderToShare |
       | Editor          | folder        | FolderToShare |
-      | Co Owner        | folder        | FolderToShare |
       | Uploader        | folder        | FolderToShare |
-      | Manager         | folder        | FolderToShare |
 
 
   Scenario Outline: user removes access to a resource in a group share
@@ -84,9 +80,7 @@ Feature: Remove access to a drive item
       | File Editor     | file          | textfile.txt  |
       | Viewer          | folder        | FolderToShare |
       | Editor          | folder        | FolderToShare |
-      | Co Owner        | folder        | FolderToShare |
       | Uploader        | folder        | FolderToShare |
-      | Manager         | folder        | FolderToShare |
 
 
   Scenario Outline: user removes access to a resource inside of a project space in group share
@@ -114,9 +108,7 @@ Feature: Remove access to a drive item
       | File Editor     | file          | textfile.txt  |
       | Viewer          | folder        | FolderToShare |
       | Editor          | folder        | FolderToShare |
-      | Co Owner        | folder        | FolderToShare |
       | Uploader        | folder        | FolderToShare |
-      | Manager         | folder        | FolderToShare |
 
 
   Scenario Outline: user removes access to a folder in link share
diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature
index c670ced7eb1..368e34dd9f2 100644
--- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature
+++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature
@@ -93,9 +93,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
 
   Scenario Outline: send share invitation to group with different roles
@@ -187,9 +185,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
 
   Scenario Outline: send share invitation for a file to user with different permissions
@@ -665,9 +661,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
 
   Scenario Outline: send share invitation with expiration date to group with different roles
@@ -763,9 +757,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
   @issue-7962
   Scenario Outline: send share invitation to disabled user
@@ -848,9 +840,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
 
   Scenario Outline: send sharing invitation to a deleted group with different roles
@@ -909,9 +899,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
 
   Scenario Outline: send share invitation to deleted user
@@ -962,9 +950,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
 
   Scenario Outline: try to send sharing invitation to multiple groups
@@ -1090,9 +1076,7 @@ Feature: Send a sharing invitations
       | File Editor      | file          | /textfile1.txt |
       | Viewer           | folder        | FolderToShare  |
       | Editor           | folder        | FolderToShare  |
-      | Co Owner         | folder        | FolderToShare  |
       | Uploader         | folder        | FolderToShare  |
-      | Manager          | folder        | FolderToShare  |
 
 
   Scenario Outline: send sharing invitation to non-existing group