github.com/cs3org/reva/v2@v2.27.7/pkg/user/manager/memory/memory.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 memory 20 21 import ( 22 "context" 23 "strconv" 24 "strings" 25 26 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 27 typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" 28 "github.com/cs3org/reva/v2/pkg/errtypes" 29 "github.com/cs3org/reva/v2/pkg/user" 30 "github.com/cs3org/reva/v2/pkg/user/manager/registry" 31 "github.com/mitchellh/mapstructure" 32 "github.com/pkg/errors" 33 ) 34 35 func init() { 36 registry.Register("memory", New) 37 } 38 39 type config struct { 40 // Users holds a map with userid and user 41 Users map[string]*User `mapstructure:"users"` 42 } 43 44 // User holds a user but uses _ in mapstructure names 45 type User struct { 46 ID *userpb.UserId `mapstructure:"id" json:"id"` 47 Username string `mapstructure:"username" json:"username"` 48 Mail string `mapstructure:"mail" json:"mail"` 49 MailVerified bool `mapstructure:"mail_verified" json:"mail_verified"` 50 DisplayName string `mapstructure:"display_name" json:"display_name"` 51 Groups []string `mapstructure:"groups" json:"groups"` 52 UIDNumber int64 `mapstructure:"uid_number" json:"uid_number"` 53 GIDNumber int64 `mapstructure:"gid_number" json:"gid_number"` 54 Opaque *typespb.Opaque `mapstructure:"opaque" json:"opaque"` 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 return c, nil 64 } 65 66 type manager struct { 67 catalog map[string]*User 68 } 69 70 // New returns a new user manager. 71 func New(m map[string]interface{}) (user.Manager, error) { 72 mgr := &manager{} 73 err := mgr.Configure(m) 74 return mgr, err 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 m.catalog = c.Users 83 return nil 84 } 85 86 func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) { 87 if user, ok := m.catalog[uid.OpaqueId]; ok { 88 if uid.Idp == "" || user.ID.Idp == uid.Idp { 89 u := *user 90 if skipFetchingGroups { 91 u.Groups = nil 92 } 93 return &userpb.User{ 94 Id: u.ID, 95 Username: u.Username, 96 Mail: u.Mail, 97 DisplayName: u.DisplayName, 98 MailVerified: u.MailVerified, 99 Groups: u.Groups, 100 Opaque: u.Opaque, 101 UidNumber: u.UIDNumber, 102 GidNumber: u.GIDNumber, 103 }, nil 104 } 105 } 106 return nil, errtypes.NotFound(uid.OpaqueId) 107 } 108 109 func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) { 110 for _, u := range m.catalog { 111 if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim { 112 user := &userpb.User{ 113 Id: u.ID, 114 Username: u.Username, 115 Mail: u.Mail, 116 DisplayName: u.DisplayName, 117 MailVerified: u.MailVerified, 118 Groups: u.Groups, 119 Opaque: u.Opaque, 120 UidNumber: u.UIDNumber, 121 GidNumber: u.GIDNumber, 122 } 123 if skipFetchingGroups { 124 user.Groups = nil 125 } 126 return user, nil 127 } 128 } 129 return nil, errtypes.NotFound(value) 130 } 131 132 func extractClaim(u *User, claim string) (string, error) { 133 switch claim { 134 case "mail": 135 return u.Mail, nil 136 case "username": 137 return u.Username, nil 138 case "userid": 139 return u.ID.OpaqueId, nil 140 case "uid": 141 if u.UIDNumber != 0 { 142 return strconv.FormatInt(u.UIDNumber, 10), nil 143 } 144 } 145 return "", errors.New("memory: invalid field") 146 } 147 148 // TODO(jfd) compare sub? 149 func userContains(u *User, query string) bool { 150 return strings.Contains(u.Username, query) || strings.Contains(u.DisplayName, query) || strings.Contains(u.Mail, query) || strings.Contains(u.ID.OpaqueId, query) 151 } 152 153 func (m *manager) FindUsers(ctx context.Context, query string, skipFetchingGroups bool) ([]*userpb.User, error) { 154 users := []*userpb.User{} 155 for _, u := range m.catalog { 156 if userContains(u, query) { 157 user := &userpb.User{ 158 Id: u.ID, 159 Username: u.Username, 160 Mail: u.Mail, 161 DisplayName: u.DisplayName, 162 MailVerified: u.MailVerified, 163 Groups: u.Groups, 164 Opaque: u.Opaque, 165 UidNumber: u.UIDNumber, 166 GidNumber: u.GIDNumber, 167 } 168 if skipFetchingGroups { 169 user.Groups = nil 170 } 171 users = append(users, user) 172 } 173 } 174 return users, nil 175 } 176 177 func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) { 178 user, err := m.GetUser(ctx, uid, false) 179 if err != nil { 180 return nil, err 181 } 182 return user.Groups, nil 183 }