storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/iam/policy/actionset.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 // ActionSet - set of actions. 28 type ActionSet map[Action]struct{} 29 30 // Clone clones ActionSet structure 31 func (actionSet ActionSet) Clone() ActionSet { 32 return NewActionSet(actionSet.ToSlice()...) 33 } 34 35 // Add - add action to the set. 36 func (actionSet ActionSet) Add(action Action) { 37 actionSet[action] = struct{}{} 38 } 39 40 // IsEmpty - returns if the current action set is empty 41 func (actionSet ActionSet) IsEmpty() bool { 42 return len(actionSet) == 0 43 } 44 45 // Match - matches object name with anyone of action pattern in action set. 46 func (actionSet ActionSet) Match(action Action) bool { 47 for r := range actionSet { 48 if r.Match(action) { 49 return true 50 } 51 52 // This is a special case where GetObjectVersion 53 // means GetObject is enabled implicitly. 54 switch r { 55 case GetObjectVersionAction: 56 if action == GetObjectAction { 57 return true 58 } 59 } 60 } 61 62 return false 63 } 64 65 // Equals - checks whether given action set is equal to current action set or not. 66 func (actionSet ActionSet) Equals(sactionSet ActionSet) bool { 67 // If length of set is not equal to length of given set, the 68 // set is not equal to given set. 69 if len(actionSet) != len(sactionSet) { 70 return false 71 } 72 73 // As both sets are equal in length, check each elements are equal. 74 for k := range actionSet { 75 if _, ok := sactionSet[k]; !ok { 76 return false 77 } 78 } 79 80 return true 81 } 82 83 // Intersection - returns actions available in both ActionSet. 84 func (actionSet ActionSet) Intersection(sset ActionSet) ActionSet { 85 nset := NewActionSet() 86 for k := range actionSet { 87 if _, ok := sset[k]; ok { 88 nset.Add(k) 89 } 90 } 91 92 return nset 93 } 94 95 // MarshalJSON - encodes ActionSet to JSON data. 96 func (actionSet ActionSet) MarshalJSON() ([]byte, error) { 97 if len(actionSet) == 0 { 98 return nil, Errorf("empty action set") 99 } 100 101 return json.Marshal(actionSet.ToSlice()) 102 } 103 104 func (actionSet ActionSet) String() string { 105 actions := []string{} 106 for action := range actionSet { 107 actions = append(actions, string(action)) 108 } 109 sort.Strings(actions) 110 111 return fmt.Sprintf("%v", actions) 112 } 113 114 // ToSlice - returns slice of actions from the action set. 115 func (actionSet ActionSet) ToSlice() []Action { 116 actions := []Action{} 117 for action := range actionSet { 118 actions = append(actions, action) 119 } 120 121 return actions 122 } 123 124 // ToAdminSlice - returns slice of admin actions from the action set. 125 func (actionSet ActionSet) ToAdminSlice() []AdminAction { 126 actions := []AdminAction{} 127 for action := range actionSet { 128 actions = append(actions, AdminAction(action)) 129 } 130 131 return actions 132 } 133 134 // UnmarshalJSON - decodes JSON data to ActionSet. 135 func (actionSet *ActionSet) UnmarshalJSON(data []byte) error { 136 var sset set.StringSet 137 if err := json.Unmarshal(data, &sset); err != nil { 138 return err 139 } 140 141 if len(sset) == 0 { 142 return Errorf("empty action set") 143 } 144 145 *actionSet = make(ActionSet) 146 for _, s := range sset.ToSlice() { 147 actionSet.Add(Action(s)) 148 } 149 150 return nil 151 } 152 153 // ValidateAdmin checks if all actions are valid Admin actions 154 func (actionSet ActionSet) ValidateAdmin() error { 155 for _, action := range actionSet.ToAdminSlice() { 156 if !action.IsValid() { 157 return Errorf("unsupported admin action '%v'", action) 158 } 159 } 160 return nil 161 } 162 163 // Validate checks if all actions are valid 164 func (actionSet ActionSet) Validate() error { 165 for _, action := range actionSet.ToSlice() { 166 if !action.IsValid() { 167 return Errorf("unsupported action '%v'", action) 168 } 169 } 170 return nil 171 } 172 173 // NewActionSet - creates new action set. 174 func NewActionSet(actions ...Action) ActionSet { 175 actionSet := make(ActionSet) 176 for _, action := range actions { 177 actionSet.Add(action) 178 } 179 180 return actionSet 181 }