github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/usergroup.go (about) 1 /* 2 Copyright 2023 Gravitational, 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 types 18 19 import ( 20 "fmt" 21 "sort" 22 "strings" 23 24 "github.com/gravitational/trace" 25 26 "github.com/gravitational/teleport/api/types/compare" 27 "github.com/gravitational/teleport/api/utils" 28 ) 29 30 var _ compare.IsEqual[UserGroup] = (*UserGroupV1)(nil) 31 32 // UserGroup specifies an externally sourced group. 33 type UserGroup interface { 34 ResourceWithLabels 35 36 // GetApplications will return a list of application IDs associated with the user group. 37 GetApplications() []string 38 // SetApplications will set the list of application IDs associated with the user group. 39 SetApplications([]string) 40 } 41 42 var _ ResourceWithLabels = (*UserGroupV1)(nil) 43 44 // NewUserGroup returns a new UserGroup. 45 func NewUserGroup(metadata Metadata, spec UserGroupSpecV1) (UserGroup, error) { 46 g := &UserGroupV1{ 47 ResourceHeader: ResourceHeader{ 48 Metadata: metadata, 49 }, 50 Spec: spec, 51 } 52 if err := g.CheckAndSetDefaults(); err != nil { 53 return nil, trace.Wrap(err) 54 } 55 return g, nil 56 } 57 58 // GetApplications will return a list of application IDs associated with the user group. 59 func (g *UserGroupV1) GetApplications() []string { 60 return g.Spec.Applications 61 } 62 63 // SetApplications will set the list of application IDs associated with the user group. 64 func (g *UserGroupV1) SetApplications(applications []string) { 65 g.Spec.Applications = applications 66 } 67 68 // String returns the user group string representation. 69 func (g *UserGroupV1) String() string { 70 return fmt.Sprintf("UserGroupV1(Name=%v, Labels=%v)", 71 g.GetName(), g.GetAllLabels()) 72 } 73 74 // MatchSearch goes through select field values and tries to 75 // match against the list of search values. 76 func (g *UserGroupV1) MatchSearch(values []string) bool { 77 fieldVals := append(utils.MapToStrings(g.GetAllLabels()), g.GetName(), g.GetMetadata().Description) 78 return MatchSearch(fieldVals, values, nil) 79 } 80 81 // setStaticFields sets static resource header and metadata fields. 82 func (g *UserGroupV1) setStaticFields() { 83 g.Kind = KindUserGroup 84 g.Version = V1 85 } 86 87 // CheckAndSetDefaults checks and sets default values 88 func (g *UserGroupV1) CheckAndSetDefaults() error { 89 g.setStaticFields() 90 if err := g.ResourceHeader.CheckAndSetDefaults(); err != nil { 91 return trace.Wrap(err) 92 } 93 94 return nil 95 } 96 97 // IsEqual determines if two user group resources are equivalent to one another. 98 func (g *UserGroupV1) IsEqual(i UserGroup) bool { 99 if other, ok := i.(*UserGroupV1); ok { 100 return deriveTeleportEqualUserGroupV1(g, other) 101 } 102 return false 103 } 104 105 // UserGroups is a list of UserGroup resources. 106 type UserGroups []UserGroup 107 108 // AsResources returns these groups as resources with labels. 109 func (g UserGroups) AsResources() []ResourceWithLabels { 110 resources := make([]ResourceWithLabels, len(g)) 111 for i, group := range g { 112 resources[i] = group 113 } 114 return resources 115 } 116 117 // SortByCustom custom sorts by given sort criteria. 118 func (g UserGroups) SortByCustom(sortBy SortBy) error { 119 if sortBy.Field == "" { 120 return nil 121 } 122 123 isDesc := sortBy.IsDesc 124 switch sortBy.Field { 125 case ResourceMetadataName: 126 sort.SliceStable(g, func(i, j int) bool { 127 groupA := g[i] 128 groupB := g[j] 129 130 groupAName := FriendlyName(groupA) 131 groupBName := FriendlyName(groupB) 132 133 if groupAName == "" { 134 groupAName = groupA.GetName() 135 } 136 if groupBName == "" { 137 groupBName = groupB.GetName() 138 } 139 140 return stringCompare(strings.ToLower(groupAName), strings.ToLower(groupBName), isDesc) 141 }) 142 case ResourceSpecDescription: 143 sort.SliceStable(g, func(i, j int) bool { 144 groupA := g[i] 145 groupB := g[j] 146 147 groupADescription := groupA.GetMetadata().Description 148 groupBDescription := groupB.GetMetadata().Description 149 150 if oktaDescription, ok := groupA.GetLabel(OktaGroupDescriptionLabel); ok { 151 groupADescription = oktaDescription 152 } 153 if oktaDescription, ok := groupB.GetLabel(OktaGroupDescriptionLabel); ok { 154 groupBDescription = oktaDescription 155 } 156 157 return stringCompare(strings.ToLower(groupADescription), strings.ToLower(groupBDescription), isDesc) 158 }) 159 160 default: 161 return trace.NotImplemented("sorting by field %q for resource %q is not supported", sortBy.Field, KindKubeServer) 162 } 163 164 return nil 165 } 166 167 // Len returns the slice length. 168 func (g UserGroups) Len() int { return len(g) } 169 170 // Less compares user groups by name. 171 func (g UserGroups) Less(i, j int) bool { return g[i].GetName() < g[j].GetName() } 172 173 // Swap swaps two user groups. 174 func (g UserGroups) Swap(i, j int) { g[i], g[j] = g[j], g[i] }