github.com/cs3org/reva/v2@v2.27.7/examples/plugin/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 main 20 21 import ( 22 "context" 23 "encoding/json" 24 "errors" 25 "os" 26 "strings" 27 28 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 29 "github.com/cs3org/reva/v2/pkg/errtypes" 30 "github.com/cs3org/reva/v2/pkg/user" 31 "github.com/hashicorp/go-plugin" 32 "github.com/mitchellh/mapstructure" 33 ) 34 35 // Manager is a real implementation of Manager interface. 36 type Manager struct { 37 users []*userpb.User 38 } 39 40 type config struct { 41 Users string `mapstructure:"users"` 42 } 43 44 func (c *config) init() { 45 if c.Users == "" { 46 c.Users = "/etc/revad/users.json" 47 } 48 } 49 50 func parseConfig(m map[string]interface{}) (*config, error) { 51 c := &config{} 52 if err := mapstructure.Decode(m, c); err != nil { 53 return nil, err 54 } 55 c.init() 56 return c, nil 57 } 58 59 // Configure initializes the manager struct based on the configurations. 60 func (m *Manager) Configure(ml map[string]interface{}) error { 61 c, err := parseConfig(ml) 62 if err != nil { 63 return err 64 } 65 66 f, err := os.ReadFile(c.Users) 67 if err != nil { 68 return err 69 } 70 71 users := []*userpb.User{} 72 73 err = json.Unmarshal(f, &users) 74 if err != nil { 75 return err 76 } 77 78 m.users = users 79 80 return nil 81 } 82 83 // GetUser returns the user based on the uid. 84 func (m *Manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) { 85 for _, u := range m.users { 86 if (u.Id.GetOpaqueId() == uid.OpaqueId || u.Username == uid.OpaqueId) && (uid.Idp == "" || uid.Idp == u.Id.GetIdp()) { 87 user := *u 88 if skipFetchingGroups { 89 user.Groups = nil 90 } 91 return &user, nil 92 } 93 } 94 return nil, nil 95 } 96 97 // GetUserByClaim returns user based on the claim 98 func (m *Manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) { 99 for _, u := range m.users { 100 if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim { 101 user := *u 102 if skipFetchingGroups { 103 user.Groups = nil 104 } 105 return &user, nil 106 } 107 } 108 return nil, errtypes.NotFound(value) 109 } 110 111 func extractClaim(u *userpb.User, claim string) (string, error) { 112 switch claim { 113 case "mail": 114 return u.Mail, nil 115 case "username": 116 return u.Username, nil 117 case "uid": 118 if u.Opaque != nil && u.Opaque.Map != nil { 119 if uidObj, ok := u.Opaque.Map["uid"]; ok { 120 if uidObj.Decoder == "plain" { 121 return string(uidObj.Value), nil 122 } 123 } 124 } 125 } 126 return "", errors.New("json: invalid field") 127 } 128 129 // TODO(jfd) search Opaque? compare sub? 130 func userContains(u *userpb.User, query string) bool { 131 query = strings.ToLower(query) 132 return strings.Contains(strings.ToLower(u.Username), query) || strings.Contains(strings.ToLower(u.DisplayName), query) || 133 strings.Contains(strings.ToLower(u.Mail), query) || strings.Contains(strings.ToLower(u.Id.OpaqueId), query) 134 } 135 136 // FindUsers returns the user based on the query 137 func (m *Manager) FindUsers(ctx context.Context, query string, skipFetchingGroups bool) ([]*userpb.User, error) { 138 users := []*userpb.User{} 139 for _, u := range m.users { 140 if userContains(u, query) { 141 user := *u 142 if skipFetchingGroups { 143 user.Groups = nil 144 } 145 users = append(users, &user) 146 } 147 } 148 return users, nil 149 } 150 151 // GetUserGroups returns the user groups 152 func (m *Manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) { 153 user, err := m.GetUser(ctx, uid, false) 154 if err != nil { 155 return nil, err 156 } 157 return user.Groups, nil 158 } 159 160 // Handshake hashicorp go-plugin handshake 161 var Handshake = plugin.HandshakeConfig{ 162 ProtocolVersion: 1, 163 MagicCookieKey: "BASIC_PLUGIN", 164 MagicCookieValue: "hello", 165 } 166 167 func main() { 168 plugin.Serve(&plugin.ServeConfig{ 169 HandshakeConfig: Handshake, 170 Plugins: map[string]plugin.Plugin{ 171 "userprovider": &user.ProviderPlugin{Impl: &Manager{}}, 172 }, 173 }) 174 }