github.com/cs3org/reva/v2@v2.27.7/pkg/group/manager/json/json.go (about) 1 // Copyright 2018-2020 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package json 20 21 import ( 22 "context" 23 "encoding/json" 24 "os" 25 "strconv" 26 "strings" 27 28 grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" 29 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 30 "github.com/cs3org/reva/v2/pkg/errtypes" 31 "github.com/cs3org/reva/v2/pkg/group" 32 "github.com/cs3org/reva/v2/pkg/group/manager/registry" 33 "github.com/mitchellh/mapstructure" 34 "github.com/pkg/errors" 35 "google.golang.org/protobuf/proto" 36 ) 37 38 func init() { 39 registry.Register("json", New) 40 } 41 42 type manager struct { 43 groups []*grouppb.Group 44 } 45 46 type config struct { 47 // Groups holds a path to a file containing json conforming to the Groups struct 48 Groups string `mapstructure:"groups"` 49 } 50 51 func (c *config) init() { 52 if c.Groups == "" { 53 c.Groups = "/etc/revad/groups.json" 54 } 55 } 56 57 func parseConfig(m map[string]interface{}) (*config, error) { 58 c := &config{} 59 if err := mapstructure.Decode(m, c); err != nil { 60 err = errors.Wrap(err, "error decoding conf") 61 return nil, err 62 } 63 c.init() 64 return c, nil 65 } 66 67 // New returns a group manager implementation that reads a json file to provide group metadata. 68 func New(m map[string]interface{}) (group.Manager, error) { 69 c, err := parseConfig(m) 70 if err != nil { 71 return nil, err 72 } 73 74 f, err := os.ReadFile(c.Groups) 75 if err != nil { 76 return nil, err 77 } 78 79 groups := []*grouppb.Group{} 80 81 err = json.Unmarshal(f, &groups) 82 if err != nil { 83 return nil, err 84 } 85 86 return &manager{ 87 groups: groups, 88 }, nil 89 } 90 91 func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId, skipFetchingMembers bool) (*grouppb.Group, error) { 92 for _, g := range m.groups { 93 if (g.Id.GetOpaqueId() == gid.OpaqueId || g.GroupName == gid.OpaqueId) && (gid.Idp == "" || gid.Idp == g.Id.GetIdp()) { 94 group := proto.Clone(g).(*grouppb.Group) 95 if skipFetchingMembers { 96 group.Members = nil 97 } 98 return group, nil 99 } 100 } 101 return nil, errtypes.NotFound(gid.OpaqueId) 102 } 103 104 func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string, skipFetchingMembers bool) (*grouppb.Group, error) { 105 for _, g := range m.groups { 106 if groupClaim, err := extractClaim(g, claim); err == nil && value == groupClaim { 107 group := proto.Clone(g).(*grouppb.Group) 108 if skipFetchingMembers { 109 group.Members = nil 110 } 111 return group, nil 112 } 113 } 114 return nil, errtypes.NotFound(value) 115 } 116 117 func extractClaim(g *grouppb.Group, claim string) (string, error) { 118 switch claim { 119 case "group_name": 120 return g.GroupName, nil 121 case "gid_number": 122 return strconv.FormatInt(g.GidNumber, 10), nil 123 case "display_name": 124 return g.DisplayName, nil 125 case "mail": 126 return g.Mail, nil 127 } 128 return "", errors.New("json: invalid field") 129 } 130 131 func (m *manager) FindGroups(ctx context.Context, query string, skipFetchingMembers bool) ([]*grouppb.Group, error) { 132 groups := []*grouppb.Group{} 133 for _, g := range m.groups { 134 if groupContains(g, query) { 135 group := proto.Clone(g).(*grouppb.Group) 136 if skipFetchingMembers { 137 group.Members = nil 138 } 139 groups = append(groups, group) 140 } 141 } 142 return groups, nil 143 } 144 145 func groupContains(g *grouppb.Group, query string) bool { 146 query = strings.ToLower(query) 147 return strings.Contains(strings.ToLower(g.GroupName), query) || strings.Contains(strings.ToLower(g.DisplayName), query) || 148 strings.Contains(strings.ToLower(g.Mail), query) || strings.Contains(strings.ToLower(g.Id.OpaqueId), query) 149 } 150 151 func (m *manager) GetMembers(ctx context.Context, gid *grouppb.GroupId) ([]*userpb.UserId, error) { 152 for _, g := range m.groups { 153 if g.Id.GetOpaqueId() == gid.OpaqueId || g.GroupName == gid.OpaqueId { 154 return g.Members, nil 155 } 156 } 157 return nil, errtypes.NotFound(gid.OpaqueId) 158 } 159 160 func (m *manager) HasMember(ctx context.Context, gid *grouppb.GroupId, uid *userpb.UserId) (bool, error) { 161 members, err := m.GetMembers(ctx, gid) 162 if err != nil { 163 return false, err 164 } 165 166 for _, u := range members { 167 if u.OpaqueId == uid.OpaqueId && u.Idp == uid.Idp { 168 return true, nil 169 } 170 } 171 return false, nil 172 }