github.com/hashicorp/vault/sdk@v0.13.0/physical/physical_view.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package physical
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"strings"
    10  )
    11  
    12  var ErrRelativePath = errors.New("relative paths not supported")
    13  
    14  // View represents a prefixed view of a physical backend
    15  type View struct {
    16  	backend Backend
    17  	prefix  string
    18  }
    19  
    20  // Verify View satisfies the correct interfaces
    21  var _ Backend = (*View)(nil)
    22  
    23  // NewView takes an underlying physical backend and returns
    24  // a view of it that can only operate with the given prefix.
    25  func NewView(backend Backend, prefix string) *View {
    26  	return &View{
    27  		backend: backend,
    28  		prefix:  prefix,
    29  	}
    30  }
    31  
    32  // List the contents of the prefixed view
    33  func (v *View) List(ctx context.Context, prefix string) ([]string, error) {
    34  	if err := v.sanityCheck(prefix); err != nil {
    35  		return nil, err
    36  	}
    37  	return v.backend.List(ctx, v.expandKey(prefix))
    38  }
    39  
    40  // Get the key of the prefixed view
    41  func (v *View) Get(ctx context.Context, key string) (*Entry, error) {
    42  	if err := v.sanityCheck(key); err != nil {
    43  		return nil, err
    44  	}
    45  	entry, err := v.backend.Get(ctx, v.expandKey(key))
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	if entry == nil {
    50  		return nil, nil
    51  	}
    52  	entry.Key = v.truncateKey(entry.Key)
    53  
    54  	return &Entry{
    55  		Key:   entry.Key,
    56  		Value: entry.Value,
    57  	}, nil
    58  }
    59  
    60  // Put the entry into the prefix view
    61  func (v *View) Put(ctx context.Context, entry *Entry) error {
    62  	if err := v.sanityCheck(entry.Key); err != nil {
    63  		return err
    64  	}
    65  
    66  	nested := &Entry{
    67  		Key:   v.expandKey(entry.Key),
    68  		Value: entry.Value,
    69  	}
    70  	return v.backend.Put(ctx, nested)
    71  }
    72  
    73  // Delete the entry from the prefix view
    74  func (v *View) Delete(ctx context.Context, key string) error {
    75  	if err := v.sanityCheck(key); err != nil {
    76  		return err
    77  	}
    78  	return v.backend.Delete(ctx, v.expandKey(key))
    79  }
    80  
    81  // sanityCheck is used to perform a sanity check on a key
    82  func (v *View) sanityCheck(key string) error {
    83  	if strings.Contains(key, "..") {
    84  		return ErrRelativePath
    85  	}
    86  	return nil
    87  }
    88  
    89  // expandKey is used to expand to the full key path with the prefix
    90  func (v *View) expandKey(suffix string) string {
    91  	return v.prefix + suffix
    92  }
    93  
    94  // truncateKey is used to remove the prefix of the key
    95  func (v *View) truncateKey(full string) string {
    96  	return strings.TrimPrefix(full, v.prefix)
    97  }