github.com/cs3org/reva/v2@v2.27.7/internal/grpc/services/userprovider/userprovider.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 userprovider
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"path/filepath"
    25  	"sort"
    26  
    27  	userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
    28  	"github.com/cs3org/reva/v2/pkg/appctx"
    29  	"github.com/cs3org/reva/v2/pkg/errtypes"
    30  	"github.com/cs3org/reva/v2/pkg/plugin"
    31  	"github.com/cs3org/reva/v2/pkg/rgrpc"
    32  	"github.com/cs3org/reva/v2/pkg/rgrpc/status"
    33  	"github.com/cs3org/reva/v2/pkg/user"
    34  	"github.com/cs3org/reva/v2/pkg/user/manager/registry"
    35  	"github.com/mitchellh/mapstructure"
    36  	"github.com/pkg/errors"
    37  	"github.com/rs/zerolog"
    38  	"google.golang.org/grpc"
    39  )
    40  
    41  func init() {
    42  	rgrpc.Register("userprovider", New)
    43  }
    44  
    45  type config struct {
    46  	Driver  string                            `mapstructure:"driver"`
    47  	Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
    48  }
    49  
    50  func (c *config) init() {
    51  	if c.Driver == "" {
    52  		c.Driver = "json"
    53  	}
    54  }
    55  
    56  func parseConfig(m map[string]interface{}) (*config, error) {
    57  	c := &config{}
    58  	if err := mapstructure.Decode(m, c); err != nil {
    59  		err = errors.Wrap(err, "error decoding conf")
    60  		return nil, err
    61  	}
    62  	c.init()
    63  	return c, nil
    64  }
    65  
    66  func getDriver(c *config) (user.Manager, *plugin.RevaPlugin, error) {
    67  	p, err := plugin.Load("userprovider", c.Driver)
    68  	if err == nil {
    69  		manager, ok := p.Plugin.(user.Manager)
    70  		if !ok {
    71  			return nil, nil, fmt.Errorf("could not assert the loaded plugin")
    72  		}
    73  		pluginConfig := filepath.Base(c.Driver)
    74  		err = manager.Configure(c.Drivers[pluginConfig])
    75  		if err != nil {
    76  			return nil, nil, err
    77  		}
    78  		return manager, p, nil
    79  	} else if _, ok := err.(errtypes.NotFound); ok {
    80  		// plugin not found, fetch the driver from the in-memory registry
    81  		if f, ok := registry.NewFuncs[c.Driver]; ok {
    82  			mgr, err := f(c.Drivers[c.Driver])
    83  			return mgr, nil, err
    84  		}
    85  	} else {
    86  		return nil, nil, err
    87  	}
    88  	return nil, nil, errtypes.NotFound(fmt.Sprintf("driver %s not found for user manager", c.Driver))
    89  }
    90  
    91  // New returns a new UserProviderServiceServer.
    92  func New(m map[string]interface{}, ss *grpc.Server, _ *zerolog.Logger) (rgrpc.Service, error) {
    93  	c, err := parseConfig(m)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  	userManager, plug, err := getDriver(c)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	svc := &service{
   102  		usermgr: userManager,
   103  		plugin:  plug,
   104  	}
   105  
   106  	return svc, nil
   107  }
   108  
   109  type service struct {
   110  	usermgr user.Manager
   111  	plugin  *plugin.RevaPlugin
   112  }
   113  
   114  func (s *service) Close() error {
   115  	if s.plugin != nil {
   116  		s.plugin.Kill()
   117  	}
   118  	return nil
   119  }
   120  
   121  func (s *service) UnprotectedEndpoints() []string {
   122  	return []string{"/cs3.identity.user.v1beta1.UserAPI/GetUser", "/cs3.identity.user.v1beta1.UserAPI/GetUserByClaim", "/cs3.identity.user.v1beta1.UserAPI/GetUserGroups"}
   123  }
   124  
   125  func (s *service) Register(ss *grpc.Server) {
   126  	userpb.RegisterUserAPIServer(ss, s)
   127  }
   128  
   129  func (s *service) GetUser(ctx context.Context, req *userpb.GetUserRequest) (*userpb.GetUserResponse, error) {
   130  	if req.UserId == nil {
   131  		res := &userpb.GetUserResponse{
   132  			Status: status.NewInvalid(ctx, "userid missing"),
   133  		}
   134  		return res, nil
   135  	}
   136  
   137  	user, err := s.usermgr.GetUser(ctx, req.UserId, req.SkipFetchingUserGroups)
   138  	if err != nil {
   139  		res := &userpb.GetUserResponse{}
   140  		if _, ok := err.(errtypes.NotFound); ok {
   141  			res.Status = status.NewNotFound(ctx, "user not found")
   142  		} else {
   143  			res.Status = status.NewInternal(ctx, "error getting user")
   144  		}
   145  		return res, nil
   146  	}
   147  
   148  	res := &userpb.GetUserResponse{
   149  		Status: status.NewOK(ctx),
   150  		User:   user,
   151  	}
   152  	return res, nil
   153  }
   154  
   155  func (s *service) GetUserByClaim(ctx context.Context, req *userpb.GetUserByClaimRequest) (*userpb.GetUserByClaimResponse, error) {
   156  	user, err := s.usermgr.GetUserByClaim(ctx, req.Claim, req.Value, req.SkipFetchingUserGroups)
   157  	if err != nil {
   158  		res := &userpb.GetUserByClaimResponse{}
   159  		if _, ok := err.(errtypes.NotFound); ok {
   160  			res.Status = status.NewNotFound(ctx, fmt.Sprintf("user not found %s %s", req.Claim, req.Value))
   161  		} else {
   162  			res.Status = status.NewInternal(ctx, "error getting user by claim")
   163  		}
   164  		return res, nil
   165  	}
   166  
   167  	res := &userpb.GetUserByClaimResponse{
   168  		Status: status.NewOK(ctx),
   169  		User:   user,
   170  	}
   171  	return res, nil
   172  }
   173  
   174  func (s *service) FindUsers(ctx context.Context, req *userpb.FindUsersRequest) (*userpb.FindUsersResponse, error) {
   175  	users, err := s.usermgr.FindUsers(ctx, req.Filter, req.SkipFetchingUserGroups)
   176  	if err != nil {
   177  		res := &userpb.FindUsersResponse{
   178  			Status: status.NewInternal(ctx, "error finding users"),
   179  		}
   180  		return res, nil
   181  	}
   182  
   183  	// sort users by username
   184  	sort.Slice(users, func(i, j int) bool {
   185  		return users[i].Username <= users[j].Username
   186  	})
   187  
   188  	res := &userpb.FindUsersResponse{
   189  		Status: status.NewOK(ctx),
   190  		Users:  users,
   191  	}
   192  	return res, nil
   193  }
   194  
   195  func (s *service) GetUserGroups(ctx context.Context, req *userpb.GetUserGroupsRequest) (*userpb.GetUserGroupsResponse, error) {
   196  	log := appctx.GetLogger(ctx)
   197  	if req.UserId == nil {
   198  		res := &userpb.GetUserGroupsResponse{
   199  			Status: status.NewInvalid(ctx, "userid missing"),
   200  		}
   201  		return res, nil
   202  	}
   203  	groups, err := s.usermgr.GetUserGroups(ctx, req.UserId)
   204  	if err != nil {
   205  		log.Warn().Err(err).Interface("userid", req.UserId).Msg("error getting user groups")
   206  		res := &userpb.GetUserGroupsResponse{
   207  			Status: status.NewInternal(ctx, "error getting user groups"),
   208  		}
   209  		return res, nil
   210  	}
   211  
   212  	res := &userpb.GetUserGroupsResponse{
   213  		Status: status.NewOK(ctx),
   214  		Groups: groups,
   215  	}
   216  	return res, nil
   217  }