github.com/cs3org/reva/v2@v2.27.7/pkg/user/manager/json/json.go (about) 1 // Copyright 2018-2021 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 "github.com/cs3org/reva/v2/pkg/user" 29 "github.com/cs3org/reva/v2/pkg/user/manager/registry" 30 "github.com/mitchellh/mapstructure" 31 "github.com/pkg/errors" 32 "google.golang.org/protobuf/proto" 33 34 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 35 "github.com/cs3org/reva/v2/pkg/errtypes" 36 ) 37 38 func init() { 39 registry.Register("json", New) 40 } 41 42 type manager struct { 43 users []*userpb.User 44 } 45 46 type config struct { 47 // Users holds a path to a file containing json conforming to the Users struct 48 Users string `mapstructure:"users"` 49 } 50 51 func (c *config) init() { 52 if c.Users == "" { 53 c.Users = "/etc/revad/users.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 user manager implementation that reads a json file to provide user metadata. 68 func New(m map[string]interface{}) (user.Manager, error) { 69 mgr := &manager{} 70 err := mgr.Configure(m) 71 if err != nil { 72 return nil, err 73 } 74 return mgr, nil 75 } 76 77 func (m *manager) Configure(ml map[string]interface{}) error { 78 c, err := parseConfig(ml) 79 if err != nil { 80 return err 81 } 82 83 f, err := os.ReadFile(c.Users) 84 if err != nil { 85 return err 86 } 87 88 users := []*userpb.User{} 89 90 err = json.Unmarshal(f, &users) 91 if err != nil { 92 return err 93 } 94 m.users = users 95 return nil 96 } 97 98 func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) { 99 for _, u := range m.users { 100 if (u.Id.GetOpaqueId() == uid.OpaqueId || u.Username == uid.OpaqueId) && (uid.Idp == "" || uid.Idp == u.Id.GetIdp()) { 101 user := proto.Clone(u).(*userpb.User) 102 if skipFetchingGroups { 103 user.Groups = nil 104 } 105 return user, nil 106 } 107 } 108 return nil, errtypes.NotFound(uid.OpaqueId) 109 } 110 111 func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) { 112 for _, u := range m.users { 113 if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim { 114 user := proto.Clone(u).(*userpb.User) 115 if skipFetchingGroups { 116 user.Groups = nil 117 } 118 return user, nil 119 } 120 } 121 return nil, errtypes.NotFound(value) 122 } 123 124 func extractClaim(u *userpb.User, claim string) (string, error) { 125 switch claim { 126 case "mail": 127 return u.Mail, nil 128 case "username": 129 return u.Username, nil 130 case "userid": 131 return u.Id.OpaqueId, nil 132 case "uid": 133 if u.UidNumber != 0 { 134 return strconv.FormatInt(u.UidNumber, 10), nil 135 } 136 } 137 return "", errors.New("json: invalid field") 138 } 139 140 // TODO(jfd) search Opaque? compare sub? 141 func userContains(u *userpb.User, query string) bool { 142 query = strings.ToLower(query) 143 return strings.Contains(strings.ToLower(u.Username), query) || strings.Contains(strings.ToLower(u.DisplayName), query) || 144 strings.Contains(strings.ToLower(u.Mail), query) || strings.Contains(strings.ToLower(u.Id.OpaqueId), query) 145 } 146 147 func (m *manager) FindUsers(ctx context.Context, query string, skipFetchingGroups bool) ([]*userpb.User, error) { 148 users := []*userpb.User{} 149 for _, u := range m.users { 150 if userContains(u, query) { 151 user := proto.Clone(u).(*userpb.User) 152 if skipFetchingGroups { 153 user.Groups = nil 154 } 155 users = append(users, user) 156 } 157 } 158 return users, nil 159 } 160 161 func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) { 162 user, err := m.GetUser(ctx, uid, false) 163 if err != nil { 164 return nil, err 165 } 166 return user.Groups, nil 167 }