diff --git a/pkg/storage/utils/decomposedfs/options/options.go b/pkg/storage/utils/decomposedfs/options/options.go index 765c0c0c53b..16811837a74 100644 --- a/pkg/storage/utils/decomposedfs/options/options.go +++ b/pkg/storage/utils/decomposedfs/options/options.go @@ -48,6 +48,9 @@ type Options struct { // permissions service to use when checking permissions PermissionsSVC string `mapstructure:"permissionssvc"` + + PersonalSpaceAliasTemplate string `mapstructure:"personalspacealias_template"` + GeneralSpaceAliasTemplate string `mapstructure:"generalspacealias_template"` } // New returns a new Options instance for the given configuration @@ -73,5 +76,13 @@ func New(m map[string]interface{}) (*Options, error) { // c.DataDirectory should never end in / unless it is the root o.Root = filepath.Clean(o.Root) + if o.PersonalSpaceAliasTemplate == "" { + o.PersonalSpaceAliasTemplate = "{{.SpaceType}}/{{.User.Username}}" + } + + if o.GeneralSpaceAliasTemplate == "" { + o.GeneralSpaceAliasTemplate = "{{.SpaceType}}/{{.SpaceName | replace \" \" \"-\" | lower}}" + } + return o, nil } diff --git a/pkg/storage/utils/decomposedfs/spaces.go b/pkg/storage/utils/decomposedfs/spaces.go index 0d1fe84b5ff..2421db8afef 100644 --- a/pkg/storage/utils/decomposedfs/spaces.go +++ b/pkg/storage/utils/decomposedfs/spaces.go @@ -42,6 +42,7 @@ import ( "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/lookup" "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node" "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs" + "github.com/cs3org/reva/v2/pkg/storage/utils/templates" "github.com/cs3org/reva/v2/pkg/utils" "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/google/uuid" @@ -69,11 +70,15 @@ func (fs *Decomposedfs) CreateStorageSpace(ctx context.Context, req *provider.Cr description := utils.ReadPlainFromOpaque(req.Opaque, "description") // allow sending a spaceAlias alias := utils.ReadPlainFromOpaque(req.Opaque, "spaceAlias") + u := ctxpkg.ContextMustGetUser(ctx) + if alias == "" { + alias = templates.WithSpacePropertiesAndUser(u, req.Type, req.Name, fs.o.GeneralSpaceAliasTemplate) + } // TODO enforce a uuid? // TODO clarify if we want to enforce a single personal storage space or if we want to allow sending the spaceid if req.Type == spaceTypePersonal { spaceID = req.GetOwner().GetId().GetOpaqueId() - alias = spaceTypePersonal + "/" + req.GetOwner().GetUsername() + alias = templates.WithSpacePropertiesAndUser(u, req.Type, req.Name, fs.o.PersonalSpaceAliasTemplate) } root, err := node.ReadNode(ctx, fs.lu, spaceID, spaceID) diff --git a/pkg/storage/utils/templates/templates.go b/pkg/storage/utils/templates/templates.go index 2741073cc6a..d8a51900703 100644 --- a/pkg/storage/utils/templates/templates.go +++ b/pkg/storage/utils/templates/templates.go @@ -43,6 +43,12 @@ type UserData struct { Email EmailData } +type SpaceData struct { + *UserData + SpaceType string + SpaceName string +} + // EmailData contains mail data // split into local and domain part. // It is extracted from splitting the username by @. @@ -69,8 +75,30 @@ func WithUser(u *userpb.User, tpl string) string { return b.String() } +// WithSpacePropertiesAndUser generates a layout based on user data and a space type. +func WithSpacePropertiesAndUser(u *userpb.User, spaceType string, spaceName string, tpl string) string { + tpl = clean(tpl) + sd := newSpaceData(u, spaceType, spaceName) + // compile given template tpl + t, err := template.New("tpl").Funcs(sprig.TxtFuncMap()).Parse(tpl) + if err != nil { + err := errors.Wrap(err, fmt.Sprintf("error parsing template: spaceanduser_template:%+v tpl:%s", sd, tpl)) + panic(err) + } + b := bytes.Buffer{} + if err := t.Execute(&b, sd); err != nil { + err := errors.Wrap(err, fmt.Sprintf("error executing template: spaceanduser_template:%+v tpl:%s", sd, tpl)) + panic(err) + } + return b.String() +} + func newUserData(u *userpb.User) *UserData { usernameSplit := strings.Split(u.Username, "@") + if u.Mail != "" { + usernameSplit = strings.Split(u.Mail, "@") + } + if len(usernameSplit) == 1 { usernameSplit = append(usernameSplit, "_unknown") } @@ -88,6 +116,16 @@ func newUserData(u *userpb.User) *UserData { return ut } +func newSpaceData(u *userpb.User, st string, n string) *SpaceData { + userData := newUserData(u) + sd := &SpaceData{ + userData, + st, + n, + } + return sd +} + func clean(a string) string { return path.Clean(a) }