mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-26 15:50:47 -05:00
140 lines
4.1 KiB
Go
140 lines
4.1 KiB
Go
package validate
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
|
|
|
"github.com/opencloud-eu/opencloud/services/graph/pkg/unifiedrole"
|
|
)
|
|
|
|
type contextKey int
|
|
|
|
const (
|
|
ContextKeyRoleIDsValueKey contextKey = iota
|
|
)
|
|
|
|
// initLibregraph initializes libregraph validation
|
|
func initLibregraph(v *validator.Validate) {
|
|
for _, f := range []func(*validator.Validate){
|
|
libregraphDriveItemInvite,
|
|
libregraphDriveRecipient,
|
|
libregraphPermission,
|
|
} {
|
|
f(v)
|
|
}
|
|
}
|
|
|
|
// libregraphDriveItemInvite validates libregraph.DriveItemInvite
|
|
func libregraphDriveItemInvite(v *validator.Validate) {
|
|
s := libregraph.DriveItemInvite{}
|
|
|
|
v.RegisterStructValidationMapRules(map[string]string{
|
|
"Recipients": "len=1,dive",
|
|
"Roles": "max=1",
|
|
"ExpirationDateTime": "omitnil,gt",
|
|
}, s)
|
|
|
|
v.RegisterStructValidationCtx(func(ctx context.Context, sl validator.StructLevel) {
|
|
driveItemInvite := sl.Current().Interface().(libregraph.DriveItemInvite)
|
|
rolesAndActions(ctx, sl, driveItemInvite.Roles, driveItemInvite.LibreGraphPermissionsActions, false)
|
|
}, s)
|
|
}
|
|
|
|
// libregraphDriveRecipient validates libregraph.DriveRecipient
|
|
func libregraphDriveRecipient(v *validator.Validate) {
|
|
v.RegisterStructValidationMapRules(map[string]string{
|
|
"ObjectId": "ne=",
|
|
"LibreGraphRecipientType": "oneof=user group",
|
|
}, libregraph.DriveRecipient{})
|
|
}
|
|
|
|
// libregraphPermission validates libregraph.Permission
|
|
func libregraphPermission(v *validator.Validate) {
|
|
s := libregraph.Permission{}
|
|
|
|
v.RegisterStructValidationMapRules(map[string]string{
|
|
"Roles": "max=1",
|
|
}, s)
|
|
v.RegisterStructValidationCtx(func(ctx context.Context, sl validator.StructLevel) {
|
|
permission := sl.Current().Interface().(libregraph.Permission)
|
|
|
|
if _, ok := permission.GetIdOk(); ok {
|
|
sl.ReportError(permission.Id, "Id", "Id", "readonly", "")
|
|
}
|
|
|
|
if _, ok := permission.GetHasPasswordOk(); ok {
|
|
sl.ReportError(permission.HasPassword, "hasPassword", "HasPassword", "readonly", "")
|
|
}
|
|
|
|
rolesAndActions(ctx, sl, permission.Roles, permission.LibreGraphPermissionsActions, true)
|
|
}, s)
|
|
}
|
|
|
|
func rolesAndActions(ctx context.Context, sl validator.StructLevel, roles, actions []string, allowEmpty bool) {
|
|
totalRoles := len(roles)
|
|
totalActions := len(actions)
|
|
switch {
|
|
case allowEmpty && totalRoles == 0 && totalActions == 0:
|
|
break
|
|
case totalRoles != 0 && totalActions != 0:
|
|
fallthrough
|
|
case totalRoles == totalActions:
|
|
sl.ReportError(roles, "Roles", "Roles", "one_or_another", "")
|
|
sl.ReportError(actions, "LibreGraphPermissionsActions", "LibreGraphPermissionsActions", "one_or_another", "")
|
|
}
|
|
|
|
var availableRoles []string
|
|
var availableActions []string
|
|
var definitions []*libregraph.UnifiedRoleDefinition
|
|
|
|
switch roles, ok := ctx.Value(ContextKeyRoleIDsValueKey).([]string); {
|
|
case ok:
|
|
definitions = unifiedrole.GetRoles(unifiedrole.RoleFilterIDs(roles...))
|
|
default:
|
|
// it the ctx does not contain the allowed role IDs, we need to fall back to all roles
|
|
definitions = unifiedrole.GetRoles(unifiedrole.RoleFilterAll())
|
|
}
|
|
|
|
for _, definition := range definitions {
|
|
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 roles {
|
|
if slices.Contains(availableRoles, role) {
|
|
continue
|
|
}
|
|
|
|
sl.ReportError(roles, "Roles", "Roles", "available_role", "")
|
|
}
|
|
|
|
for _, action := range actions {
|
|
if slices.Contains(availableActions, action) {
|
|
continue
|
|
}
|
|
|
|
sl.ReportError(actions, "LibreGraphPermissionsActions", "LibreGraphPermissionsActions", "available_action", "")
|
|
}
|
|
}
|
|
|
|
// ContextWithAllowedRoleIDs returns a new context which includes the allowed role IDs.
|
|
func ContextWithAllowedRoleIDs(ctx context.Context, rolesIds []string) context.Context {
|
|
return context.WithValue(ctx, ContextKeyRoleIDsValueKey, rolesIds)
|
|
}
|