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  }