enhancement: make use of unifiedrole from the graph invitation endpoint, applying multiple roles works and result in a merged cs3 permission set (#7751)

This commit is contained in:
Florian Schade
2023-11-23 14:18:03 +01:00
committed by GitHub
parent 74f1b2c56d
commit 40d356c56b
9 changed files with 377 additions and 52 deletions
+81
View File
@@ -0,0 +1,81 @@
package validate
import (
"github.com/go-playground/validator/v10"
libregraph "github.com/owncloud/libre-graph-api-go"
"golang.org/x/exp/slices"
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
)
// initLibregraph initializes libregraph validation
func initLibregraph(v *validator.Validate) {
driveItemInvite(v)
}
// driveItemInvite validates libregraph.DriveItemInvite
func driveItemInvite(v *validator.Validate) {
s := libregraph.DriveItemInvite{}
v.RegisterStructValidationMapRules(map[string]string{
"Recipients": "min=1",
"Roles": "max=1",
"ExpirationDateTime": "omitnil,gt",
}, s)
v.RegisterStructValidation(func(sl validator.StructLevel) {
driveItemInvite := sl.Current().Interface().(libregraph.DriveItemInvite)
totalRoles := len(driveItemInvite.Roles)
totalActions := len(driveItemInvite.LibreGraphPermissionsActions)
switch {
case totalRoles != 0 && totalActions != 0:
fallthrough
case totalRoles == totalActions:
sl.ReportError(driveItemInvite.Roles, "Roles", "Roles", "one_or_another", "")
sl.ReportError(driveItemInvite.LibreGraphPermissionsActions, "LibreGraphPermissionsActions", "LibreGraphPermissionsActions", "one_or_another", "")
}
var availableRoles []string
var availableActions []string
for _, definition := range append(
unifiedrole.GetBuiltinRoleDefinitionList(true),
unifiedrole.GetBuiltinRoleDefinitionList(false)...,
) {
if slices.Contains(availableRoles, definition.GetId()) {
continue
}
availableRoles = append(availableRoles, definition.GetId())
for _, permission := range definition.GetRolePermissions() {
for _, action := range permission.GetAllowedResourceActions() {
if slices.Contains(availableActions, action) {
continue
}
availableActions = append(availableActions, action)
}
}
}
for _, role := range driveItemInvite.Roles {
if slices.Contains(availableRoles, role) {
continue
}
sl.ReportError(driveItemInvite.Roles, "Roles", "Roles", "available_role", "")
}
for _, role := range driveItemInvite.LibreGraphPermissionsActions {
if slices.Contains(availableActions, role) {
continue
}
sl.ReportError(driveItemInvite.LibreGraphPermissionsActions, "LibreGraphPermissionsActions", "LibreGraphPermissionsActions", "available_action", "")
}
}, s)
}
@@ -0,0 +1,93 @@
package validate_test
import (
"context"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
"github.com/owncloud/ocis/v2/services/graph/pkg/validate"
)
var _ = Describe("libregraph", func() {
var driveItemInvite libregraph.DriveItemInvite
BeforeEach(func() {
driveItemInvite = libregraph.DriveItemInvite{
Recipients: []libregraph.DriveRecipient{{ObjectId: libregraph.PtrString("1")}},
Roles: []string{unifiedrole.UnifiedRoleEditorID},
LibreGraphPermissionsActions: []string{unifiedrole.DriveItemVersionsUpdate},
ExpirationDateTime: libregraph.PtrTime(time.Now().Add(time.Hour)),
}
})
DescribeTable("DriveItemInvite",
func(factory func() libregraph.DriveItemInvite, expectError bool) {
f := factory()
switch err := validate.StructCtx(context.Background(), f); expectError {
case true:
Expect(err).To(HaveOccurred())
default:
Expect(err).ToNot(HaveOccurred())
}
},
Entry("succeed: roles", func() libregraph.DriveItemInvite {
driveItemInvite.LibreGraphPermissionsActions = nil
return driveItemInvite
}, false),
Entry("succeed: permission actions", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = nil
return driveItemInvite
}, false),
Entry("succeed: without ExpirationDateTime", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = nil
driveItemInvite.ExpirationDateTime = nil
return driveItemInvite
}, false),
Entry("fail: multiple role assignment", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = []string{
unifiedrole.UnifiedRoleEditorID,
unifiedrole.UnifiedRoleManagerID,
}
driveItemInvite.LibreGraphPermissionsActions = nil
return driveItemInvite
}, true),
Entry("fail: unknown role", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = []string{"foo"}
driveItemInvite.LibreGraphPermissionsActions = nil
return driveItemInvite
}, true),
Entry("fail: unknown action", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = nil
driveItemInvite.LibreGraphPermissionsActions = []string{"foo"}
return driveItemInvite
}, true),
Entry("fail: missing roles or permission actions", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = nil
driveItemInvite.LibreGraphPermissionsActions = nil
return driveItemInvite
}, true),
Entry("fail: different number of roles and actions", func() libregraph.DriveItemInvite {
driveItemInvite.LibreGraphPermissionsActions = []string{
unifiedrole.DriveItemVersionsUpdate,
unifiedrole.DriveItemChildrenCreate,
}
return driveItemInvite
}, true),
Entry("fail: missing recipients", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = nil
driveItemInvite.Recipients = nil
return driveItemInvite
}, true),
Entry("fail: expirationDateTime in the past", func() libregraph.DriveItemInvite {
driveItemInvite.Roles = nil
driveItemInvite.ExpirationDateTime = libregraph.PtrTime(time.Now().Add(-time.Hour))
return driveItemInvite
}, true),
)
})
+1 -11
View File
@@ -5,24 +5,14 @@ import (
"sync/atomic"
"github.com/go-playground/validator/v10"
libregraph "github.com/owncloud/libre-graph-api-go"
)
var defaultValidator atomic.Value
var structMapValidations = map[any]map[string]string{
&libregraph.DriveItemInvite{}: {
"Recipients": "min=1",
"Roles": "len=1", // currently it is not possible to set more than one role
"ExpirationDateTime": "omitnil,gt",
},
}
func init() {
v := validator.New()
for s, rules := range structMapValidations {
v.RegisterStructValidationMapRules(rules, s)
}
initLibregraph(v)
defaultValidator.Store(v)
}
@@ -0,0 +1,13 @@
package validate_test
import (
"testing"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func TestGraph(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Validate Suite")
}