github.com/cs3org/reva/v2@v2.27.7/pkg/storage/utils/templates/templates.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  /*
    20  Package templates contains data-driven templates for path layouts.
    21  
    22  Templates can use functions from the github.com/Masterminds/sprig library.
    23  All templates are cleaned with path.Clean().
    24  */
    25  package templates
    26  
    27  import (
    28  	"bytes"
    29  	"fmt"
    30  	"path"
    31  	"strings"
    32  	"text/template"
    33  
    34  	"github.com/Masterminds/sprig"
    35  	userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
    36  	providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    37  	"github.com/cs3org/reva/v2/pkg/storagespace"
    38  	"github.com/pkg/errors"
    39  )
    40  
    41  // UserData contains the template placeholders for a user.
    42  // For example {{.Username}} or {{.Id.Idp}}
    43  type (
    44  	UserData struct {
    45  		*userpb.User
    46  		Email EmailData
    47  	}
    48  
    49  	// SpaceData contains the templace placeholders for a space.
    50  	// For example {{.SpaceName}} {{.SpaceType}} or {{.User.Id.OpaqueId}}
    51  	SpaceData struct {
    52  		*UserData
    53  		SpaceType string
    54  		SpaceName string
    55  		SpaceId   string
    56  	}
    57  
    58  	// EmailData contains mail data
    59  	// split into local and domain part.
    60  	// It is extracted from splitting the username by @.
    61  	EmailData struct {
    62  		Local  string
    63  		Domain string
    64  	}
    65  
    66  	// ResourceData contains the ResourceInfo
    67  	// ResourceData.ResourceID is a stringified form of ResourceInfo.Id
    68  	ResourceData struct {
    69  		ResourceInfo *providerv1beta1.ResourceInfo
    70  		ResourceID   string
    71  	}
    72  )
    73  
    74  // WithUser generates a layout based on user data.
    75  func WithUser(u *userpb.User, tpl string) string {
    76  	tpl = clean(tpl)
    77  	ut := newUserData(u)
    78  	// compile given template tpl
    79  	t, err := template.New("tpl").Funcs(sprig.TxtFuncMap()).Parse(tpl)
    80  	if err != nil {
    81  		err := errors.Wrap(err, fmt.Sprintf("error parsing template: user_template:%+v tpl:%s", ut, tpl))
    82  		panic(err)
    83  	}
    84  	b := bytes.Buffer{}
    85  	if err := t.Execute(&b, ut); err != nil {
    86  		err := errors.Wrap(err, fmt.Sprintf("error executing template: user_template:%+v tpl:%s", ut, tpl))
    87  		panic(err)
    88  	}
    89  	return b.String()
    90  }
    91  
    92  // WithSpacePropertiesAndUser generates a layout based on user data and a space type.
    93  func WithSpacePropertiesAndUser(u *userpb.User, spaceType string, spaceName string, spaceID string, tpl string) string {
    94  	tpl = clean(tpl)
    95  	sd := newSpaceData(u, spaceType, spaceName, spaceID)
    96  	// compile given template tpl
    97  	t, err := template.New("tpl").Funcs(sprig.TxtFuncMap()).Parse(tpl)
    98  	if err != nil {
    99  		err := errors.Wrap(err, fmt.Sprintf("error parsing template: spaceanduser_template:%+v tpl:%s", sd, tpl))
   100  		panic(err)
   101  	}
   102  	b := bytes.Buffer{}
   103  	if err := t.Execute(&b, sd); err != nil {
   104  		err := errors.Wrap(err, fmt.Sprintf("error executing template: spaceanduser_template:%+v tpl:%s", sd, tpl))
   105  		panic(err)
   106  	}
   107  	return b.String()
   108  }
   109  
   110  // WithResourceInfo renders template stings with ResourceInfo variables
   111  func WithResourceInfo(i *providerv1beta1.ResourceInfo, tpl string) string {
   112  	tpl = clean(tpl)
   113  	data := newResourceData(i)
   114  	// compile given template tpl
   115  	t, err := template.New("tpl").Funcs(sprig.TxtFuncMap()).Parse(tpl)
   116  	if err != nil {
   117  		err := errors.Wrap(err, fmt.Sprintf("error parsing template: fileinfoandresourceid_template:%+v tpl:%s", data, tpl))
   118  		panic(err)
   119  	}
   120  	b := bytes.Buffer{}
   121  	if err := t.Execute(&b, data); err != nil {
   122  		err := errors.Wrap(err, fmt.Sprintf("error executing template: fileinfoandresourceid_template:%+v tpl:%s", data, tpl))
   123  		panic(err)
   124  	}
   125  	return b.String()
   126  }
   127  
   128  func newUserData(u *userpb.User) *UserData {
   129  	usernameSplit := strings.Split(u.Username, "@")
   130  	if u.Mail != "" {
   131  		usernameSplit = strings.Split(u.Mail, "@")
   132  	}
   133  
   134  	if len(usernameSplit) == 1 {
   135  		usernameSplit = append(usernameSplit, "_unknown")
   136  	}
   137  	if usernameSplit[1] == "" {
   138  		usernameSplit[1] = "_unknown"
   139  	}
   140  
   141  	ut := &UserData{
   142  		User: u,
   143  		Email: EmailData{
   144  			Local:  strings.ToLower(usernameSplit[0]),
   145  			Domain: strings.ToLower(usernameSplit[1]),
   146  		},
   147  	}
   148  	return ut
   149  }
   150  
   151  func newSpaceData(u *userpb.User, st, n, id string) *SpaceData {
   152  	userData := newUserData(u)
   153  	sd := &SpaceData{
   154  		userData,
   155  		st,
   156  		n,
   157  		id,
   158  	}
   159  	return sd
   160  }
   161  
   162  func newResourceData(i *providerv1beta1.ResourceInfo) *ResourceData {
   163  	rd := &ResourceData{
   164  		ResourceInfo: i,
   165  		ResourceID:   storagespace.FormatResourceID(i.Id),
   166  	}
   167  	return rd
   168  }
   169  
   170  func clean(a string) string {
   171  	return path.Clean(a)
   172  }