storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/bucket/policy/condition/stringlikefunc.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package condition
    18  
    19  import (
    20  	"fmt"
    21  	"net/http"
    22  	"sort"
    23  
    24  	"github.com/minio/minio-go/v7/pkg/s3utils"
    25  	"github.com/minio/minio-go/v7/pkg/set"
    26  
    27  	"storj.io/minio/pkg/wildcard"
    28  )
    29  
    30  func toStringLikeFuncString(n name, key Key, values set.StringSet) string {
    31  	valueStrings := values.ToSlice()
    32  	sort.Strings(valueStrings)
    33  
    34  	return fmt.Sprintf("%v:%v:%v", n, key, valueStrings)
    35  }
    36  
    37  // stringLikeFunc - String like function. It checks whether value by Key in given
    38  // values map is widcard matching in condition values.
    39  // For example,
    40  //   - if values = ["mybucket/foo*"], at evaluate() it returns whether string
    41  //     in value map for Key is wildcard matching in values.
    42  type stringLikeFunc struct {
    43  	k      Key
    44  	values set.StringSet
    45  }
    46  
    47  // evaluate() - evaluates to check whether value by Key in given values is wildcard
    48  // matching in condition values.
    49  func (f stringLikeFunc) evaluate(values map[string][]string) bool {
    50  	requestValue, ok := values[http.CanonicalHeaderKey(f.k.Name())]
    51  	if !ok {
    52  		requestValue = values[f.k.Name()]
    53  	}
    54  
    55  	fvalues := f.values.ApplyFunc(substFuncFromValues(values))
    56  
    57  	for _, v := range requestValue {
    58  		if !fvalues.FuncMatch(wildcard.Match, v).IsEmpty() {
    59  			return true
    60  		}
    61  	}
    62  
    63  	return false
    64  }
    65  
    66  // key() - returns condition key which is used by this condition function.
    67  func (f stringLikeFunc) key() Key {
    68  	return f.k
    69  }
    70  
    71  // name() - returns "StringLike" function name.
    72  func (f stringLikeFunc) name() name {
    73  	return stringLike
    74  }
    75  
    76  func (f stringLikeFunc) String() string {
    77  	return toStringLikeFuncString(stringLike, f.k, f.values)
    78  }
    79  
    80  // toMap - returns map representation of this function.
    81  func (f stringLikeFunc) toMap() map[Key]ValueSet {
    82  	if !f.k.IsValid() {
    83  		return nil
    84  	}
    85  
    86  	values := NewValueSet()
    87  	for _, value := range f.values.ToSlice() {
    88  		values.Add(NewStringValue(value))
    89  	}
    90  
    91  	return map[Key]ValueSet{
    92  		f.k: values,
    93  	}
    94  }
    95  
    96  // stringNotLikeFunc - String not like function. It checks whether value by Key in given
    97  // values map is NOT widcard matching in condition values.
    98  // For example,
    99  //   - if values = ["mybucket/foo*"], at evaluate() it returns whether string
   100  //     in value map for Key is NOT wildcard matching in values.
   101  type stringNotLikeFunc struct {
   102  	stringLikeFunc
   103  }
   104  
   105  // evaluate() - evaluates to check whether value by Key in given values is NOT wildcard
   106  // matching in condition values.
   107  func (f stringNotLikeFunc) evaluate(values map[string][]string) bool {
   108  	return !f.stringLikeFunc.evaluate(values)
   109  }
   110  
   111  // name() - returns "StringNotLike" function name.
   112  func (f stringNotLikeFunc) name() name {
   113  	return stringNotLike
   114  }
   115  
   116  func (f stringNotLikeFunc) String() string {
   117  	return toStringLikeFuncString(stringNotLike, f.stringLikeFunc.k, f.stringLikeFunc.values)
   118  }
   119  
   120  func validateStringLikeValues(n name, key Key, values set.StringSet) error {
   121  	for _, s := range values.ToSlice() {
   122  		switch key {
   123  		case S3XAmzCopySource:
   124  			bucket, object := path2BucketAndObject(s)
   125  			if object == "" {
   126  				return fmt.Errorf("invalid value '%v' for '%v' for %v condition", s, S3XAmzCopySource, n)
   127  			}
   128  			if err := s3utils.CheckValidBucketName(bucket); err != nil {
   129  				return err
   130  			}
   131  		}
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  // newStringLikeFunc - returns new StringLike function.
   138  func newStringLikeFunc(key Key, values ValueSet) (Function, error) {
   139  	valueStrings, err := valuesToStringSlice(stringLike, values)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	return NewStringLikeFunc(key, valueStrings...)
   145  }
   146  
   147  // NewStringLikeFunc - returns new StringLike function.
   148  func NewStringLikeFunc(key Key, values ...string) (Function, error) {
   149  	sset := set.CreateStringSet(values...)
   150  	if err := validateStringLikeValues(stringLike, key, sset); err != nil {
   151  		return nil, err
   152  	}
   153  
   154  	return &stringLikeFunc{key, sset}, nil
   155  }
   156  
   157  // newStringNotLikeFunc - returns new StringNotLike function.
   158  func newStringNotLikeFunc(key Key, values ValueSet) (Function, error) {
   159  	valueStrings, err := valuesToStringSlice(stringNotLike, values)
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  
   164  	return NewStringNotLikeFunc(key, valueStrings...)
   165  }
   166  
   167  // NewStringNotLikeFunc - returns new StringNotLike function.
   168  func NewStringNotLikeFunc(key Key, values ...string) (Function, error) {
   169  	sset := set.CreateStringSet(values...)
   170  	if err := validateStringLikeValues(stringNotLike, key, sset); err != nil {
   171  		return nil, err
   172  	}
   173  
   174  	return &stringNotLikeFunc{stringLikeFunc{key, sset}}, nil
   175  }