storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/iam/policy/resourceset.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 iampolicy
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"sort"
    23  
    24  	"github.com/minio/minio-go/v7/pkg/set"
    25  )
    26  
    27  // ResourceSet - set of resources in policy statement.
    28  type ResourceSet map[Resource]struct{}
    29  
    30  // bucketResourceExists - checks if at least one bucket resource exists in the set.
    31  func (resourceSet ResourceSet) bucketResourceExists() bool {
    32  	for resource := range resourceSet {
    33  		if resource.isBucketPattern() {
    34  			return true
    35  		}
    36  	}
    37  
    38  	return false
    39  }
    40  
    41  // objectResourceExists - checks if at least one object resource exists in the set.
    42  func (resourceSet ResourceSet) objectResourceExists() bool {
    43  	for resource := range resourceSet {
    44  		if resource.isObjectPattern() {
    45  			return true
    46  		}
    47  	}
    48  
    49  	return false
    50  }
    51  
    52  // Add - adds resource to resource set.
    53  func (resourceSet ResourceSet) Add(resource Resource) {
    54  	resourceSet[resource] = struct{}{}
    55  }
    56  
    57  // Equals - checks whether given resource set is equal to current resource set or not.
    58  func (resourceSet ResourceSet) Equals(sresourceSet ResourceSet) bool {
    59  	// If length of set is not equal to length of given set, the
    60  	// set is not equal to given set.
    61  	if len(resourceSet) != len(sresourceSet) {
    62  		return false
    63  	}
    64  
    65  	// As both sets are equal in length, check each elements are equal.
    66  	for k := range resourceSet {
    67  		if _, ok := sresourceSet[k]; !ok {
    68  			return false
    69  		}
    70  	}
    71  
    72  	return true
    73  }
    74  
    75  // Intersection - returns resources available in both ResourceSet.
    76  func (resourceSet ResourceSet) Intersection(sset ResourceSet) ResourceSet {
    77  	nset := NewResourceSet()
    78  	for k := range resourceSet {
    79  		if _, ok := sset[k]; ok {
    80  			nset.Add(k)
    81  		}
    82  	}
    83  
    84  	return nset
    85  }
    86  
    87  // MarshalJSON - encodes ResourceSet to JSON data.
    88  func (resourceSet ResourceSet) MarshalJSON() ([]byte, error) {
    89  	if len(resourceSet) == 0 {
    90  		return nil, Errorf("empty resource set")
    91  	}
    92  
    93  	resources := []Resource{}
    94  	for resource := range resourceSet {
    95  		resources = append(resources, resource)
    96  	}
    97  
    98  	return json.Marshal(resources)
    99  }
   100  
   101  // Match - matches object name with anyone of resource pattern in resource set.
   102  func (resourceSet ResourceSet) Match(resource string, conditionValues map[string][]string) bool {
   103  	for r := range resourceSet {
   104  		if r.Match(resource, conditionValues) {
   105  			return true
   106  		}
   107  	}
   108  
   109  	return false
   110  }
   111  
   112  func (resourceSet ResourceSet) String() string {
   113  	resources := []string{}
   114  	for resource := range resourceSet {
   115  		resources = append(resources, resource.String())
   116  	}
   117  	sort.Strings(resources)
   118  
   119  	return fmt.Sprintf("%v", resources)
   120  }
   121  
   122  // UnmarshalJSON - decodes JSON data to ResourceSet.
   123  func (resourceSet *ResourceSet) UnmarshalJSON(data []byte) error {
   124  	var sset set.StringSet
   125  	if err := json.Unmarshal(data, &sset); err != nil {
   126  		return err
   127  	}
   128  
   129  	*resourceSet = make(ResourceSet)
   130  	for _, s := range sset.ToSlice() {
   131  		resource, err := parseResource(s)
   132  		if err != nil {
   133  			return err
   134  		}
   135  
   136  		if _, found := (*resourceSet)[resource]; found {
   137  			return Errorf("duplicate resource '%v' found", s)
   138  		}
   139  
   140  		resourceSet.Add(resource)
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  // Validate - validates ResourceSet.
   147  func (resourceSet ResourceSet) Validate() error {
   148  	for resource := range resourceSet {
   149  		if err := resource.Validate(); err != nil {
   150  			return err
   151  		}
   152  	}
   153  
   154  	return nil
   155  }
   156  
   157  // ToSlice - returns slice of resources from the resource set.
   158  func (resourceSet ResourceSet) ToSlice() []Resource {
   159  	resources := []Resource{}
   160  	for resource := range resourceSet {
   161  		resources = append(resources, resource)
   162  	}
   163  
   164  	return resources
   165  }
   166  
   167  // Clone clones ResourceSet structure
   168  func (resourceSet ResourceSet) Clone() ResourceSet {
   169  	return NewResourceSet(resourceSet.ToSlice()...)
   170  }
   171  
   172  // NewResourceSet - creates new resource set.
   173  func NewResourceSet(resources ...Resource) ResourceSet {
   174  	resourceSet := make(ResourceSet)
   175  	for _, resource := range resources {
   176  		resourceSet.Add(resource)
   177  	}
   178  
   179  	return resourceSet
   180  }