Initial QSfera import
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAccountNotFound account not found
|
||||
ErrAccountNotFound = errors.New("user not found")
|
||||
// ErrAccountDisabled account disabled
|
||||
ErrAccountDisabled = errors.New("account disabled")
|
||||
// ErrNotSupported operation not supported by user-backend
|
||||
ErrNotSupported = errors.New("operation not supported")
|
||||
)
|
||||
|
||||
// UserBackend allows the proxy to retrieve users from different user-backends (accounts-service, CS3)
|
||||
type UserBackend interface {
|
||||
GetUserByClaims(ctx context.Context, claim, value string) (*cs3.User, string, error)
|
||||
Authenticate(ctx context.Context, username string, password string) (*cs3.User, string, error)
|
||||
CreateUserFromClaims(ctx context.Context, claims map[string]any) (*cs3.User, error)
|
||||
UpdateUserIfNeeded(ctx context.Context, user *cs3.User, claims map[string]any) error
|
||||
SyncGroupMemberships(ctx context.Context, user *cs3.User, claims map[string]any) error
|
||||
}
|
||||
@@ -0,0 +1,517 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"github.com/qsfera/server/pkg/log"
|
||||
"github.com/qsfera/server/pkg/oidc"
|
||||
"github.com/qsfera/server/services/graph/pkg/errorcode"
|
||||
"github.com/qsfera/server/services/proxy/pkg/config"
|
||||
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
|
||||
utils "github.com/opencloud-eu/reva/v2/pkg/utils"
|
||||
"go-micro.dev/v4/selector"
|
||||
)
|
||||
|
||||
type cs3backend struct {
|
||||
graphSelector selector.Selector
|
||||
Options
|
||||
}
|
||||
|
||||
// Option defines a single option function.
|
||||
type Option func(o *Options)
|
||||
|
||||
// Options defines the available options for this package.
|
||||
type Options struct {
|
||||
logger log.Logger
|
||||
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
|
||||
selector selector.Selector
|
||||
machineAuthAPIKey string
|
||||
oidcISS string
|
||||
serviceAccount config.ServiceAccount
|
||||
autoProvisionClaims config.AutoProvisionClaims
|
||||
}
|
||||
|
||||
var (
|
||||
errGroupNotFound = errors.New("group not found")
|
||||
)
|
||||
|
||||
// WithLogger sets the logger option
|
||||
func WithLogger(l log.Logger) Option {
|
||||
return func(o *Options) {
|
||||
o.logger = l
|
||||
}
|
||||
}
|
||||
|
||||
// WithRevaGatewaySelector set the gatewaySelector option
|
||||
func WithRevaGatewaySelector(selectable pool.Selectable[gateway.GatewayAPIClient]) Option {
|
||||
return func(o *Options) {
|
||||
o.gatewaySelector = selectable
|
||||
}
|
||||
}
|
||||
|
||||
// WithSelector set the Selector option
|
||||
func WithSelector(selector selector.Selector) Option {
|
||||
return func(o *Options) {
|
||||
o.selector = selector
|
||||
}
|
||||
}
|
||||
|
||||
// WithMachineAuthAPIKey configures the machine auth API key
|
||||
func WithMachineAuthAPIKey(ma string) Option {
|
||||
return func(o *Options) {
|
||||
o.machineAuthAPIKey = ma
|
||||
}
|
||||
}
|
||||
|
||||
// WithOIDCissuer set the OIDC issuer URL
|
||||
func WithOIDCissuer(oidcISS string) Option {
|
||||
return func(o *Options) {
|
||||
o.oidcISS = oidcISS
|
||||
}
|
||||
}
|
||||
|
||||
// WithServiceAccount configures the service account creator to use
|
||||
func WithServiceAccount(c config.ServiceAccount) Option {
|
||||
return func(o *Options) {
|
||||
o.serviceAccount = c
|
||||
}
|
||||
}
|
||||
|
||||
func WithAutoProvisionClaims(claims config.AutoProvisionClaims) Option {
|
||||
return func(o *Options) {
|
||||
o.autoProvisionClaims = claims
|
||||
}
|
||||
}
|
||||
|
||||
// NewCS3UserBackend creates a user-provider which fetches users from a CS3 UserBackend
|
||||
func NewCS3UserBackend(opts ...Option) UserBackend {
|
||||
opt := Options{}
|
||||
for _, o := range opts {
|
||||
o(&opt)
|
||||
}
|
||||
|
||||
b := cs3backend{
|
||||
Options: opt,
|
||||
graphSelector: opt.selector,
|
||||
}
|
||||
|
||||
return &b
|
||||
}
|
||||
|
||||
func (c *cs3backend) GetUserByClaims(ctx context.Context, claim, value string) (*cs3.User, string, error) {
|
||||
gatewayClient, err := c.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("could not obtain gatewayClient: %s", err)
|
||||
}
|
||||
|
||||
res, err := gatewayClient.Authenticate(ctx, &gateway.AuthenticateRequest{
|
||||
Type: "machine",
|
||||
ClientId: claim + ":" + value,
|
||||
ClientSecret: c.machineAuthAPIKey,
|
||||
})
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, "", fmt.Errorf("could not get user by claim %v with value %v: %w", claim, value, err)
|
||||
case res.Status.Code != rpcv1beta1.Code_CODE_OK:
|
||||
if res.Status.Code == rpcv1beta1.Code_CODE_NOT_FOUND {
|
||||
return nil, "", ErrAccountNotFound
|
||||
}
|
||||
return nil, "", fmt.Errorf("could not get user by claim %v with value %v : %s ", claim, value, res.GetStatus().GetMessage())
|
||||
}
|
||||
|
||||
user := res.User
|
||||
|
||||
return user, res.GetToken(), nil
|
||||
}
|
||||
|
||||
func (c *cs3backend) Authenticate(ctx context.Context, username string, password string) (*cs3.User, string, error) {
|
||||
gatewayClient, err := c.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("could not obtain gatewayClient: %s", err)
|
||||
}
|
||||
|
||||
res, err := gatewayClient.Authenticate(ctx, &gateway.AuthenticateRequest{
|
||||
Type: "basic",
|
||||
ClientId: username,
|
||||
ClientSecret: password,
|
||||
})
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, "", fmt.Errorf("could not authenticate with username and password user: %s, %w", username, err)
|
||||
case res.Status.Code != rpcv1beta1.Code_CODE_OK:
|
||||
return nil, "", fmt.Errorf("could not authenticate with username and password user: %s, got code: %d", username, res.GetStatus().GetCode())
|
||||
}
|
||||
|
||||
return res.User, res.Token, nil
|
||||
}
|
||||
|
||||
// CreateUserFromClaims creates a new user via libregraph users API, taking the
|
||||
// attributes from the provided `claims` map. On success it returns the new
|
||||
// user. If the user already exist this is not considered an error and the
|
||||
// function will just return the existing user.
|
||||
func (c *cs3backend) CreateUserFromClaims(ctx context.Context, claims map[string]any) (*cs3.User, error) {
|
||||
gatewayClient, err := c.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("could not select next gateway client")
|
||||
return nil, err
|
||||
}
|
||||
newctx := context.Background()
|
||||
authRes, err := gatewayClient.Authenticate(newctx, &gateway.AuthenticateRequest{
|
||||
Type: "serviceaccounts",
|
||||
ClientId: c.serviceAccount.ServiceAccountID,
|
||||
ClientSecret: c.serviceAccount.ServiceAccountSecret,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if authRes.GetStatus().GetCode() != rpcv1beta1.Code_CODE_OK {
|
||||
return nil, fmt.Errorf("error authenticating service user: %s", authRes.GetStatus().GetMessage())
|
||||
}
|
||||
|
||||
lgClient, err := c.setupLibregraphClient(newctx, authRes.GetToken())
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Error setting up libregraph client.")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newUser, err := c.libregraphUserFromClaims(claims)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Interface("claims", claims).Msg("Error creating user from claims")
|
||||
return nil, fmt.Errorf("error creating user from claims: %w", err)
|
||||
}
|
||||
|
||||
req := lgClient.UsersApi.CreateUser(newctx).User(newUser)
|
||||
|
||||
created, resp, err := req.Execute()
|
||||
defer resp.Body.Close()
|
||||
|
||||
var reread bool
|
||||
if err != nil {
|
||||
if resp == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the user already exists here, some other request did already create it in parallel.
|
||||
// So just issue a Debug message and ignore the libregraph error otherwise
|
||||
var lerr error
|
||||
if reread, lerr = c.isAlreadyExists(resp); lerr != nil {
|
||||
c.logger.Error().Err(lerr).Msg("extracting error from ibregraph response body failed.")
|
||||
return nil, err
|
||||
}
|
||||
if !reread {
|
||||
c.logger.Error().Err(err).Msg("Error creating user")
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// User has been created meanwhile, re-read it to get the user id
|
||||
if reread {
|
||||
c.logger.Debug().Msg("User already exist, re-reading via libregraph")
|
||||
gureq := lgClient.UserApi.GetUser(newctx, newUser.GetOnPremisesSamAccountName())
|
||||
created, resp, err = gureq.Execute()
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Error trying to re-read user from graphAPI")
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
cs3UserCreated := c.cs3UserFromLibregraph(newctx, created)
|
||||
|
||||
return &cs3UserCreated, nil
|
||||
}
|
||||
|
||||
func (c cs3backend) UpdateUserIfNeeded(ctx context.Context, user *cs3.User, claims map[string]any) error {
|
||||
newUser, err := c.libregraphUserFromClaims(claims)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Interface("claims", claims).Msg("Error converting claims to user")
|
||||
return fmt.Errorf("error converting claims to updated user: %w", err)
|
||||
}
|
||||
|
||||
// Check if the user needs to be updated, only updates of "displayName" and "mail" are supported
|
||||
// currently.
|
||||
userupdate := libregraph.NewUserUpdate()
|
||||
switch {
|
||||
case newUser.GetDisplayName() != user.GetDisplayName():
|
||||
userupdate.SetDisplayName(newUser.GetDisplayName())
|
||||
case newUser.GetMail() != user.GetMail():
|
||||
userupdate.SetMail(newUser.GetMail())
|
||||
}
|
||||
|
||||
if userupdate.HasDisplayName() || userupdate.HasMail() {
|
||||
return c.updateLibregraphUser(user.GetId().GetOpaqueId(), *userupdate)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncGroupMemberships maintains a users group memberships based on an OIDC claim
|
||||
func (c cs3backend) SyncGroupMemberships(ctx context.Context, user *cs3.User, claims map[string]any) error {
|
||||
gatewayClient, err := c.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("could not select next gateway client")
|
||||
return err
|
||||
}
|
||||
newctx := context.Background()
|
||||
token, err := utils.GetServiceUserToken(newctx, gatewayClient, c.serviceAccount.ServiceAccountID, c.serviceAccount.ServiceAccountSecret)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Error getting token for service user")
|
||||
return err
|
||||
}
|
||||
|
||||
lgClient, err := c.setupLibregraphClient(newctx, token)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Error setting up libregraph client")
|
||||
return err
|
||||
}
|
||||
|
||||
lgUser, resp, err := lgClient.UserApi.GetUser(newctx, user.GetId().GetOpaqueId()).Expand([]string{"memberOf"}).Execute()
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Failed to lookup user via libregraph")
|
||||
return err
|
||||
}
|
||||
|
||||
currentGroups := lgUser.GetMemberOf()
|
||||
currentGroupSet := make(map[string]struct{})
|
||||
for _, group := range currentGroups {
|
||||
currentGroupSet[group.GetDisplayName()] = struct{}{}
|
||||
}
|
||||
|
||||
newGroupSet := make(map[string]struct{})
|
||||
if groups, ok := claims[c.autoProvisionClaims.Groups].([]any); ok {
|
||||
for _, g := range groups {
|
||||
if group, ok := g.(string); ok {
|
||||
newGroupSet[group] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for group := range newGroupSet {
|
||||
if _, exists := currentGroupSet[group]; !exists {
|
||||
c.logger.Debug().Str("group", group).Msg("adding user to group")
|
||||
// Check if group exists
|
||||
lgGroup, err := c.getLibregraphGroup(newctx, lgClient, group)
|
||||
switch {
|
||||
case errors.Is(err, errGroupNotFound):
|
||||
newGroup := libregraph.Group{}
|
||||
newGroup.SetDisplayName(group)
|
||||
req := lgClient.GroupsApi.CreateGroup(newctx).Group(newGroup)
|
||||
var resp *http.Response
|
||||
lgGroup, resp, err = req.Execute()
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
switch {
|
||||
case err == nil:
|
||||
// all good
|
||||
case resp == nil:
|
||||
return err
|
||||
default:
|
||||
// Ignore error if group already exists
|
||||
exists, lerr := c.isAlreadyExists(resp)
|
||||
switch {
|
||||
case lerr != nil:
|
||||
c.logger.Error().Err(lerr).Msg("extracting error from ibregraph response body failed.")
|
||||
return err
|
||||
case !exists:
|
||||
c.logger.Error().Err(err).Msg("Failed to create group via libregraph")
|
||||
return err
|
||||
default:
|
||||
// group has been created meanwhile, re-read it to get the group id
|
||||
lgGroup, err = c.getLibregraphGroup(newctx, lgClient, group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
|
||||
memberref := "https://localhost/graph/v1.0/users/" + user.GetId().GetOpaqueId()
|
||||
resp, err := lgClient.GroupApi.AddMember(newctx, lgGroup.GetId()).MemberReference(
|
||||
libregraph.MemberReference{
|
||||
OdataId: &memberref,
|
||||
},
|
||||
).Execute()
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Failed to add user to group via libregraph")
|
||||
}
|
||||
}
|
||||
}
|
||||
for current := range currentGroupSet {
|
||||
if _, exists := newGroupSet[current]; !exists {
|
||||
c.logger.Debug().Str("group", current).Msg("deleting user from group")
|
||||
lgGroup, err := c.getLibregraphGroup(newctx, lgClient, current)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := lgClient.GroupApi.DeleteMember(newctx, lgGroup.GetId(), user.GetId().GetOpaqueId()).Execute()
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c cs3backend) getLibregraphGroup(ctx context.Context, client *libregraph.APIClient, group string) (*libregraph.Group, error) {
|
||||
lgGroup, resp, err := client.GroupApi.GetGroup(ctx, group).Execute()
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
switch {
|
||||
case resp == nil:
|
||||
return nil, err
|
||||
case resp.StatusCode == http.StatusNotFound:
|
||||
return nil, errGroupNotFound
|
||||
case resp.StatusCode != http.StatusOK:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return lgGroup, nil
|
||||
}
|
||||
|
||||
func (c cs3backend) updateLibregraphUser(userid string, user libregraph.UserUpdate) error {
|
||||
gatewayClient, err := c.gatewaySelector.Next()
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("could not select next gateway client")
|
||||
return err
|
||||
}
|
||||
newctx := context.Background()
|
||||
token, err := utils.GetServiceUserToken(newctx, gatewayClient, c.serviceAccount.ServiceAccountID, c.serviceAccount.ServiceAccountSecret)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Error getting token for service user")
|
||||
return err
|
||||
}
|
||||
|
||||
lgClient, err := c.setupLibregraphClient(newctx, token)
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Error setting up libregraph client")
|
||||
return err
|
||||
}
|
||||
|
||||
req := lgClient.UserApi.UpdateUser(newctx, userid).UserUpdate(user)
|
||||
|
||||
_, resp, err := req.Execute()
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
c.logger.Error().Err(err).Msg("Failed to update user via libregraph")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c cs3backend) setupLibregraphClient(_ context.Context, cs3token string) (*libregraph.APIClient, error) {
|
||||
// Use micro registry to resolve next graph service endpoint
|
||||
next, err := c.graphSelector.Select("qsfera.web.graph")
|
||||
if err != nil {
|
||||
c.logger.Debug().Err(err).Msg("setupLibregraphClient: error during Select")
|
||||
return nil, err
|
||||
}
|
||||
node, err := next()
|
||||
if err != nil {
|
||||
c.logger.Debug().Err(err).Msg("setupLibregraphClient: error getting next Node")
|
||||
return nil, err
|
||||
}
|
||||
lgconf := libregraph.NewConfiguration()
|
||||
lgconf.Servers = libregraph.ServerConfigurations{
|
||||
{
|
||||
URL: fmt.Sprintf("%s://%s/graph", node.Metadata["protocol"], node.Address),
|
||||
},
|
||||
}
|
||||
|
||||
lgconf.DefaultHeader = map[string]string{revactx.TokenHeader: cs3token}
|
||||
return libregraph.NewAPIClient(lgconf), nil
|
||||
}
|
||||
|
||||
func (c cs3backend) isAlreadyExists(resp *http.Response) (bool, error) {
|
||||
oDataErr := libregraph.NewOdataErrorWithDefaults()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
c.logger.Debug().Err(err).Msg("Error trying to read libregraph response")
|
||||
return false, err
|
||||
}
|
||||
err = json.Unmarshal(body, oDataErr)
|
||||
if err != nil {
|
||||
c.logger.Debug().Err(err).Msg("Error unmarshalling libregraph response")
|
||||
return false, err
|
||||
}
|
||||
|
||||
c.logger.Warn().Str("OData Error", oDataErr.Error.Message).Msg("Error Response")
|
||||
|
||||
if oDataErr.Error.Code == errorcode.NameAlreadyExists.String() {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c cs3backend) libregraphUserFromClaims(claims map[string]any) (libregraph.User, error) {
|
||||
user := libregraph.User{}
|
||||
if dn, ok := claims[c.autoProvisionClaims.DisplayName].(string); ok {
|
||||
user.SetDisplayName(dn)
|
||||
} else {
|
||||
return user, fmt.Errorf("missing claim '%s' (displayName)", c.autoProvisionClaims.DisplayName)
|
||||
}
|
||||
if username, ok := claims[c.autoProvisionClaims.Username].(string); ok {
|
||||
user.SetOnPremisesSamAccountName(username)
|
||||
} else {
|
||||
return user, fmt.Errorf("missing claim '%s' (username)", c.autoProvisionClaims.Username)
|
||||
}
|
||||
// Email is optional so we don't need an 'else' here
|
||||
if mail, ok := claims[c.autoProvisionClaims.Email].(string); ok {
|
||||
user.SetMail(mail)
|
||||
}
|
||||
|
||||
sub, subExists := claims[oidc.Sub].(string)
|
||||
iss, issExists := claims[oidc.Iss].(string)
|
||||
|
||||
if subExists && issExists {
|
||||
var objectIdentity libregraph.ObjectIdentity
|
||||
objectIdentity.SetIssuer(iss)
|
||||
objectIdentity.SetIssuerAssignedId(sub)
|
||||
user.Identities = append(user.Identities, objectIdentity)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (c cs3backend) cs3UserFromLibregraph(_ context.Context, lu *libregraph.User) cs3.User {
|
||||
cs3id := cs3.UserId{
|
||||
Type: cs3.UserType_USER_TYPE_PRIMARY,
|
||||
Idp: c.oidcISS,
|
||||
}
|
||||
|
||||
cs3id.OpaqueId = lu.GetId()
|
||||
|
||||
cs3user := cs3.User{
|
||||
Id: &cs3id,
|
||||
}
|
||||
cs3user.Username = lu.GetOnPremisesSamAccountName()
|
||||
cs3user.DisplayName = lu.GetDisplayName()
|
||||
cs3user.Mail = lu.GetMail()
|
||||
return cs3user
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
// Code generated by mockery; DO NOT EDIT.
|
||||
// github.com/vektra/mockery
|
||||
// template: testify
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// NewUserBackend creates a new instance of UserBackend. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewUserBackend(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *UserBackend {
|
||||
mock := &UserBackend{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
// UserBackend is an autogenerated mock type for the UserBackend type
|
||||
type UserBackend struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type UserBackend_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *UserBackend) EXPECT() *UserBackend_Expecter {
|
||||
return &UserBackend_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Authenticate provides a mock function for the type UserBackend
|
||||
func (_mock *UserBackend) Authenticate(ctx context.Context, username string, password string) (*userv1beta1.User, string, error) {
|
||||
ret := _mock.Called(ctx, username, password)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Authenticate")
|
||||
}
|
||||
|
||||
var r0 *userv1beta1.User
|
||||
var r1 string
|
||||
var r2 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) (*userv1beta1.User, string, error)); ok {
|
||||
return returnFunc(ctx, username, password)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) *userv1beta1.User); ok {
|
||||
r0 = returnFunc(ctx, username, password)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*userv1beta1.User)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, string, string) string); ok {
|
||||
r1 = returnFunc(ctx, username, password)
|
||||
} else {
|
||||
r1 = ret.Get(1).(string)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(2).(func(context.Context, string, string) error); ok {
|
||||
r2 = returnFunc(ctx, username, password)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// UserBackend_Authenticate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Authenticate'
|
||||
type UserBackend_Authenticate_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Authenticate is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - username string
|
||||
// - password string
|
||||
func (_e *UserBackend_Expecter) Authenticate(ctx interface{}, username interface{}, password interface{}) *UserBackend_Authenticate_Call {
|
||||
return &UserBackend_Authenticate_Call{Call: _e.mock.On("Authenticate", ctx, username, password)}
|
||||
}
|
||||
|
||||
func (_c *UserBackend_Authenticate_Call) Run(run func(ctx context.Context, username string, password string)) *UserBackend_Authenticate_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 string
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(string)
|
||||
}
|
||||
var arg2 string
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(string)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_Authenticate_Call) Return(user *userv1beta1.User, s string, err error) *UserBackend_Authenticate_Call {
|
||||
_c.Call.Return(user, s, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_Authenticate_Call) RunAndReturn(run func(ctx context.Context, username string, password string) (*userv1beta1.User, string, error)) *UserBackend_Authenticate_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateUserFromClaims provides a mock function for the type UserBackend
|
||||
func (_mock *UserBackend) CreateUserFromClaims(ctx context.Context, claims map[string]any) (*userv1beta1.User, error) {
|
||||
ret := _mock.Called(ctx, claims)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateUserFromClaims")
|
||||
}
|
||||
|
||||
var r0 *userv1beta1.User
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, map[string]any) (*userv1beta1.User, error)); ok {
|
||||
return returnFunc(ctx, claims)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, map[string]any) *userv1beta1.User); ok {
|
||||
r0 = returnFunc(ctx, claims)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*userv1beta1.User)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, map[string]any) error); ok {
|
||||
r1 = returnFunc(ctx, claims)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UserBackend_CreateUserFromClaims_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateUserFromClaims'
|
||||
type UserBackend_CreateUserFromClaims_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateUserFromClaims is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - claims map[string]any
|
||||
func (_e *UserBackend_Expecter) CreateUserFromClaims(ctx interface{}, claims interface{}) *UserBackend_CreateUserFromClaims_Call {
|
||||
return &UserBackend_CreateUserFromClaims_Call{Call: _e.mock.On("CreateUserFromClaims", ctx, claims)}
|
||||
}
|
||||
|
||||
func (_c *UserBackend_CreateUserFromClaims_Call) Run(run func(ctx context.Context, claims map[string]any)) *UserBackend_CreateUserFromClaims_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 map[string]any
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(map[string]any)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_CreateUserFromClaims_Call) Return(user *userv1beta1.User, err error) *UserBackend_CreateUserFromClaims_Call {
|
||||
_c.Call.Return(user, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_CreateUserFromClaims_Call) RunAndReturn(run func(ctx context.Context, claims map[string]any) (*userv1beta1.User, error)) *UserBackend_CreateUserFromClaims_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetUserByClaims provides a mock function for the type UserBackend
|
||||
func (_mock *UserBackend) GetUserByClaims(ctx context.Context, claim string, value string) (*userv1beta1.User, string, error) {
|
||||
ret := _mock.Called(ctx, claim, value)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetUserByClaims")
|
||||
}
|
||||
|
||||
var r0 *userv1beta1.User
|
||||
var r1 string
|
||||
var r2 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) (*userv1beta1.User, string, error)); ok {
|
||||
return returnFunc(ctx, claim, value)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) *userv1beta1.User); ok {
|
||||
r0 = returnFunc(ctx, claim, value)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*userv1beta1.User)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, string, string) string); ok {
|
||||
r1 = returnFunc(ctx, claim, value)
|
||||
} else {
|
||||
r1 = ret.Get(1).(string)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(2).(func(context.Context, string, string) error); ok {
|
||||
r2 = returnFunc(ctx, claim, value)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// UserBackend_GetUserByClaims_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUserByClaims'
|
||||
type UserBackend_GetUserByClaims_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetUserByClaims is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - claim string
|
||||
// - value string
|
||||
func (_e *UserBackend_Expecter) GetUserByClaims(ctx interface{}, claim interface{}, value interface{}) *UserBackend_GetUserByClaims_Call {
|
||||
return &UserBackend_GetUserByClaims_Call{Call: _e.mock.On("GetUserByClaims", ctx, claim, value)}
|
||||
}
|
||||
|
||||
func (_c *UserBackend_GetUserByClaims_Call) Run(run func(ctx context.Context, claim string, value string)) *UserBackend_GetUserByClaims_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 string
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(string)
|
||||
}
|
||||
var arg2 string
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(string)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_GetUserByClaims_Call) Return(user *userv1beta1.User, s string, err error) *UserBackend_GetUserByClaims_Call {
|
||||
_c.Call.Return(user, s, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_GetUserByClaims_Call) RunAndReturn(run func(ctx context.Context, claim string, value string) (*userv1beta1.User, string, error)) *UserBackend_GetUserByClaims_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// SyncGroupMemberships provides a mock function for the type UserBackend
|
||||
func (_mock *UserBackend) SyncGroupMemberships(ctx context.Context, user *userv1beta1.User, claims map[string]any) error {
|
||||
ret := _mock.Called(ctx, user, claims)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SyncGroupMemberships")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, map[string]any) error); ok {
|
||||
r0 = returnFunc(ctx, user, claims)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// UserBackend_SyncGroupMemberships_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SyncGroupMemberships'
|
||||
type UserBackend_SyncGroupMemberships_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// SyncGroupMemberships is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - user *userv1beta1.User
|
||||
// - claims map[string]any
|
||||
func (_e *UserBackend_Expecter) SyncGroupMemberships(ctx interface{}, user interface{}, claims interface{}) *UserBackend_SyncGroupMemberships_Call {
|
||||
return &UserBackend_SyncGroupMemberships_Call{Call: _e.mock.On("SyncGroupMemberships", ctx, user, claims)}
|
||||
}
|
||||
|
||||
func (_c *UserBackend_SyncGroupMemberships_Call) Run(run func(ctx context.Context, user *userv1beta1.User, claims map[string]any)) *UserBackend_SyncGroupMemberships_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *userv1beta1.User
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*userv1beta1.User)
|
||||
}
|
||||
var arg2 map[string]any
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(map[string]any)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_SyncGroupMemberships_Call) Return(err error) *UserBackend_SyncGroupMemberships_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_SyncGroupMemberships_Call) RunAndReturn(run func(ctx context.Context, user *userv1beta1.User, claims map[string]any) error) *UserBackend_SyncGroupMemberships_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// UpdateUserIfNeeded provides a mock function for the type UserBackend
|
||||
func (_mock *UserBackend) UpdateUserIfNeeded(ctx context.Context, user *userv1beta1.User, claims map[string]any) error {
|
||||
ret := _mock.Called(ctx, user, claims)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateUserIfNeeded")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, map[string]any) error); ok {
|
||||
r0 = returnFunc(ctx, user, claims)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
return r0
|
||||
}
|
||||
|
||||
// UserBackend_UpdateUserIfNeeded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateUserIfNeeded'
|
||||
type UserBackend_UpdateUserIfNeeded_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// UpdateUserIfNeeded is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - user *userv1beta1.User
|
||||
// - claims map[string]any
|
||||
func (_e *UserBackend_Expecter) UpdateUserIfNeeded(ctx interface{}, user interface{}, claims interface{}) *UserBackend_UpdateUserIfNeeded_Call {
|
||||
return &UserBackend_UpdateUserIfNeeded_Call{Call: _e.mock.On("UpdateUserIfNeeded", ctx, user, claims)}
|
||||
}
|
||||
|
||||
func (_c *UserBackend_UpdateUserIfNeeded_Call) Run(run func(ctx context.Context, user *userv1beta1.User, claims map[string]any)) *UserBackend_UpdateUserIfNeeded_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *userv1beta1.User
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*userv1beta1.User)
|
||||
}
|
||||
var arg2 map[string]any
|
||||
if args[2] != nil {
|
||||
arg2 = args[2].(map[string]any)
|
||||
}
|
||||
run(
|
||||
arg0,
|
||||
arg1,
|
||||
arg2,
|
||||
)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_UpdateUserIfNeeded_Call) Return(err error) *UserBackend_UpdateUserIfNeeded_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *UserBackend_UpdateUserIfNeeded_Call) RunAndReturn(run func(ctx context.Context, user *userv1beta1.User, claims map[string]any) error) *UserBackend_UpdateUserIfNeeded_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
Reference in New Issue
Block a user