github.com/cs3org/reva/v2@v2.27.7/pkg/cbox/storage/eoshomewrapper/eoshomewrapper.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  package eoshomewrapper
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"text/template"
    25  
    26  	"github.com/Masterminds/sprig"
    27  	provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    28  	ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
    29  	"github.com/cs3org/reva/v2/pkg/errtypes"
    30  	"github.com/cs3org/reva/v2/pkg/events"
    31  	"github.com/cs3org/reva/v2/pkg/storage"
    32  	"github.com/cs3org/reva/v2/pkg/storage/fs/registry"
    33  	"github.com/cs3org/reva/v2/pkg/storage/utils/eosfs"
    34  	"github.com/mitchellh/mapstructure"
    35  	"github.com/pkg/errors"
    36  	"github.com/rs/zerolog"
    37  )
    38  
    39  func init() {
    40  	registry.Register("eoshomewrapper", New)
    41  }
    42  
    43  type wrapper struct {
    44  	storage.FS
    45  	mountIDTemplate *template.Template
    46  }
    47  
    48  func parseConfig(m map[string]interface{}) (*eosfs.Config, string, error) {
    49  	c := &eosfs.Config{}
    50  	if err := mapstructure.Decode(m, c); err != nil {
    51  		err = errors.Wrap(err, "error decoding conf")
    52  		return nil, "", err
    53  	}
    54  
    55  	// default to version invariance if not configured
    56  	if _, ok := m["version_invariant"]; !ok {
    57  		c.VersionInvariant = true
    58  	}
    59  
    60  	t, ok := m["mount_id_template"].(string)
    61  	if !ok || t == "" {
    62  		t = "eoshome-{{substr 0 1 .Username}}"
    63  	}
    64  
    65  	return c, t, nil
    66  }
    67  
    68  // New returns an implementation of the storage.FS interface that forms a wrapper
    69  // around separate connections to EOS.
    70  func New(m map[string]interface{}, _ events.Stream, _ *zerolog.Logger) (storage.FS, error) {
    71  	c, t, err := parseConfig(m)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	c.EnableHome = true
    76  
    77  	eos, err := eosfs.NewEOSFS(c)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	mountIDTemplate, err := template.New("mountID").Funcs(sprig.TxtFuncMap()).Parse(t)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	return &wrapper{FS: eos, mountIDTemplate: mountIDTemplate}, nil
    88  }
    89  
    90  // We need to override the two methods, GetMD and ListFolder to fill the
    91  // StorageId in the ResourceInfo objects.
    92  
    93  func (w *wrapper) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string, fieldMask []string) (*provider.ResourceInfo, error) {
    94  	res, err := w.FS.GetMD(ctx, ref, mdKeys, fieldMask)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	// We need to extract the mount ID based on the mapping template.
   100  	//
   101  	// Take the first letter of the username of the logged-in user, as the home
   102  	// storage provider restricts requests only to the home namespace.
   103  	res.Id.StorageId = w.getMountID(ctx, res)
   104  	return res, nil
   105  }
   106  
   107  func (w *wrapper) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys, fieldMask []string) ([]*provider.ResourceInfo, error) {
   108  	res, err := w.FS.ListFolder(ctx, ref, mdKeys, fieldMask)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	for _, r := range res {
   113  		r.Id.StorageId = w.getMountID(ctx, r)
   114  	}
   115  	return res, nil
   116  }
   117  
   118  func (w *wrapper) DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error {
   119  	return errtypes.NotSupported("eos: deny grant is only enabled for project spaces")
   120  }
   121  
   122  func (w *wrapper) getMountID(ctx context.Context, r *provider.ResourceInfo) string {
   123  	u := ctxpkg.ContextMustGetUser(ctx)
   124  	b := bytes.Buffer{}
   125  	if err := w.mountIDTemplate.Execute(&b, u); err != nil {
   126  		return ""
   127  	}
   128  	return b.String()
   129  }