mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-28 23:48:46 -06:00
Merge pull request #5955 from owncloud/ainmosni/feature/keycloak-pkg
Add keycloak package.
This commit is contained in:
211
ocis-pkg/keycloak/client.go
Normal file
211
ocis-pkg/keycloak/client.go
Normal file
@@ -0,0 +1,211 @@
|
||||
// Package keycloak is a package for keycloak utility functions.
|
||||
package keycloak
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
)
|
||||
|
||||
// Some attribute constants.
|
||||
// TODO: Make these configurable in the future.
|
||||
const (
|
||||
_idAttr = "OWNCLOUD_ID"
|
||||
_userTypeAttr = "OWNCLOUD_USER_TYPE"
|
||||
)
|
||||
|
||||
// ConcreteClient represents a concrete implementation of a keycloak client
|
||||
type ConcreteClient struct {
|
||||
keycloak GoCloak
|
||||
clientID string
|
||||
clientSecret string
|
||||
realm string
|
||||
baseURL string
|
||||
}
|
||||
|
||||
// New instantiates a new keycloak.Backend with a default gocloak client.
|
||||
func New(
|
||||
baseURL, clientID, clientSecret, realm string,
|
||||
insecureSkipVerify bool,
|
||||
) *ConcreteClient {
|
||||
gc := gocloak.NewClient(baseURL)
|
||||
restyClient := gc.RestyClient()
|
||||
restyClient.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: insecureSkipVerify}) //nolint:gosec
|
||||
return NewWithClient(gc, baseURL, clientID, clientSecret, realm)
|
||||
}
|
||||
|
||||
// NewWithClient instantiates a new keycloak.Backend with a custom
|
||||
func NewWithClient(
|
||||
gocloakClient GoCloak,
|
||||
baseURL, clientID, clientSecret, realm string,
|
||||
) *ConcreteClient {
|
||||
return &ConcreteClient{
|
||||
keycloak: gocloakClient,
|
||||
baseURL: baseURL,
|
||||
clientID: clientID,
|
||||
clientSecret: clientSecret,
|
||||
realm: realm,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateUser creates a user from a libregraph user and returns its *keycloak* ID.
|
||||
// TODO: For now we only call this from the invitation service where all the attributes are set correctly.
|
||||
//
|
||||
// For more wider use, do some sanity checking on the user instance.
|
||||
func (c *ConcreteClient) CreateUser(ctx context.Context, realm string, user *libregraph.User, userActions []UserAction) (string, error) {
|
||||
token, err := c.getToken(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
req := gocloak.User{
|
||||
Email: user.Mail,
|
||||
Enabled: user.AccountEnabled,
|
||||
Username: user.OnPremisesSamAccountName,
|
||||
FirstName: user.GivenName,
|
||||
LastName: user.Surname,
|
||||
Attributes: &map[string][]string{
|
||||
_idAttr: {user.GetId()},
|
||||
_userTypeAttr: {user.GetUserType()},
|
||||
},
|
||||
RequiredActions: convertUserActions(userActions),
|
||||
}
|
||||
return c.keycloak.CreateUser(ctx, token.AccessToken, realm, req)
|
||||
}
|
||||
|
||||
// SendActionsMail sends a mail to the user with userID instructing them to do the actions defined in userActions.
|
||||
func (c *ConcreteClient) SendActionsMail(ctx context.Context, realm, userID string, userActions []UserAction) error {
|
||||
token, err := c.getToken(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := gocloak.ExecuteActionsEmail{
|
||||
UserID: &userID,
|
||||
Actions: convertUserActions(userActions),
|
||||
}
|
||||
|
||||
return c.keycloak.ExecuteActionsEmail(ctx, token.AccessToken, realm, params)
|
||||
}
|
||||
|
||||
// GetUserByEmail looks up a user by email.
|
||||
func (c *ConcreteClient) GetUserByEmail(ctx context.Context, realm, mail string) (*libregraph.User, error) {
|
||||
token, err := c.getToken(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users, err := c.keycloak.GetUsers(ctx, token.AccessToken, realm, gocloak.GetUsersParams{
|
||||
Email: &mail,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(users) == 0 {
|
||||
return nil, fmt.Errorf("no users found with mail address %s", mail)
|
||||
}
|
||||
|
||||
if len(users) > 1 {
|
||||
return nil, fmt.Errorf("%d users found with mail address %s, expected 1", len(users), mail)
|
||||
}
|
||||
|
||||
return c.keycloakUserToLibregraph(users[0]), nil
|
||||
}
|
||||
|
||||
// GetPIIReport returns a structure with all the PII for the user.
|
||||
func (c *ConcreteClient) GetPIIReport(ctx context.Context, realm string, user *libregraph.User) (*PIIReport, error) {
|
||||
u, err := c.GetUserByEmail(ctx, realm, *user.Mail)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token, err := c.getToken(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keycloakID, err := c.getKeyCloakID(u)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
creds, err := c.keycloak.GetCredentials(ctx, token.AccessToken, realm, keycloakID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &PIIReport{
|
||||
UserData: u,
|
||||
Credentials: creds,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getToken gets a fresh token for the request.
|
||||
// TODO: set a token on the struct and check if it's still valid before requesting a new one.
|
||||
func (c *ConcreteClient) getToken(ctx context.Context) (*gocloak.JWT, error) {
|
||||
token, err := c.keycloak.LoginClient(ctx, c.clientID, c.clientSecret, c.realm)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get token: %w", err)
|
||||
}
|
||||
|
||||
rRes, err := c.keycloak.RetrospectToken(ctx, token.AccessToken, c.clientID, c.clientSecret, c.realm)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrospect token: %w", err)
|
||||
}
|
||||
|
||||
if !*rRes.Active {
|
||||
return nil, fmt.Errorf("token is not active")
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (c *ConcreteClient) keycloakUserToLibregraph(u *gocloak.User) *libregraph.User {
|
||||
attrs := *u.Attributes
|
||||
ldapID := ""
|
||||
ldapIDs, ok := attrs[_idAttr]
|
||||
if ok {
|
||||
ldapID = ldapIDs[0]
|
||||
}
|
||||
|
||||
var userType *string
|
||||
userTypes, ok := attrs[_userTypeAttr]
|
||||
if ok {
|
||||
userType = &userTypes[0]
|
||||
}
|
||||
|
||||
return &libregraph.User{
|
||||
Id: &ldapID,
|
||||
Mail: u.Email,
|
||||
GivenName: u.FirstName,
|
||||
Surname: u.LastName,
|
||||
AccountEnabled: u.Enabled,
|
||||
UserType: userType,
|
||||
Identities: []libregraph.ObjectIdentity{
|
||||
{
|
||||
Issuer: &c.baseURL,
|
||||
IssuerAssignedId: u.ID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConcreteClient) getKeyCloakID(u *libregraph.User) (string, error) {
|
||||
for _, i := range u.Identities {
|
||||
if *i.Issuer == c.baseURL {
|
||||
return *i.IssuerAssignedId, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("could not find identity for issuer: %s", c.baseURL)
|
||||
}
|
||||
|
||||
func convertUserActions(userActions []UserAction) *[]string {
|
||||
stringActions := make([]string, len(userActions))
|
||||
for i, a := range userActions {
|
||||
stringActions[i] = userActionsToString[a]
|
||||
}
|
||||
return &stringActions
|
||||
}
|
||||
19
ocis-pkg/keycloak/gocloak.go
Normal file
19
ocis-pkg/keycloak/gocloak.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package keycloak
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
)
|
||||
|
||||
// GoCloak represents the parts of gocloak.GoCloak that we use, mainly here for mockery.
|
||||
//
|
||||
//go:generate mockery --name=GoCloak
|
||||
type GoCloak interface {
|
||||
CreateUser(ctx context.Context, token, realm string, user gocloak.User) (string, error)
|
||||
GetUsers(ctx context.Context, token, realm string, params gocloak.GetUsersParams) ([]*gocloak.User, error)
|
||||
ExecuteActionsEmail(ctx context.Context, token, realm string, params gocloak.ExecuteActionsEmail) error
|
||||
LoginClient(ctx context.Context, clientID, clientSecret, realm string) (*gocloak.JWT, error)
|
||||
RetrospectToken(ctx context.Context, accessToken, clientID, clientSecret, realm string) (*gocloak.IntroSpectTokenResult, error)
|
||||
GetCredentials(ctx context.Context, accessToken, realm, userID string) ([]*gocloak.CredentialRepresentation, error)
|
||||
}
|
||||
39
ocis-pkg/keycloak/types.go
Normal file
39
ocis-pkg/keycloak/types.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package keycloak
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
)
|
||||
|
||||
// UserAction defines a type for user actions
|
||||
type UserAction int8
|
||||
|
||||
// An incomplete list of UserActions
|
||||
const (
|
||||
// UserActionUpdatePassword sets it that the user needs to change their password.
|
||||
UserActionUpdatePassword UserAction = iota
|
||||
// UserActionVerifyEmail sets it that the user needs to verify their email address.
|
||||
UserActionVerifyEmail
|
||||
)
|
||||
|
||||
// A lookup table to translate user actions to their string equivalents
|
||||
var userActionsToString = map[UserAction]string{
|
||||
UserActionUpdatePassword: "UPDATE_PASSWORD",
|
||||
UserActionVerifyEmail: "VERIFY_EMAIL",
|
||||
}
|
||||
|
||||
// PIIReport is a structure of all the PersonalIdentifiableInformation contained in keycloak.
|
||||
type PIIReport struct {
|
||||
UserData *libregraph.User
|
||||
Credentials []*gocloak.CredentialRepresentation
|
||||
}
|
||||
|
||||
// Client represents a keycloak client.
|
||||
type Client interface {
|
||||
CreateUser(ctx context.Context, realm string, user *libregraph.User, userActions []UserAction) (string, error)
|
||||
SendActionsMail(ctx context.Context, realm, userID string, userActions []UserAction) error
|
||||
GetUserByEmail(ctx context.Context, realm, email string) (*libregraph.User, error)
|
||||
GetPIIReport(ctx context.Context, realm string, user *libregraph.User) (*PIIReport, error)
|
||||
}
|
||||
@@ -25,7 +25,7 @@ include ../../.make/generate.mk
|
||||
|
||||
.PHONY: ci-go-generate
|
||||
ci-go-generate: $(MOCKERY) # CI runs ci-node-generate automatically before this target
|
||||
$(MOCKERY) --dir pkg/backends/keycloak --output pkg/mocks --case underscore --name GoCloak
|
||||
$(MOCKERY) --output pkg/mocks --case underscore --name Client --srcpkg "github.com/owncloud/ocis/v2/ocis-pkg/keycloak"
|
||||
|
||||
|
||||
.PHONY: ci-node-generate
|
||||
|
||||
@@ -3,31 +3,28 @@ package keycloak
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
"github.com/google/uuid"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/keycloak"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/invitations/pkg/invitations"
|
||||
)
|
||||
|
||||
const (
|
||||
idAttr = "OWNCLOUD_ID"
|
||||
userTypeAttr = "OWNCLOUD_USER_TYPE"
|
||||
userTypeVal = "Guest"
|
||||
userType = "Guest"
|
||||
)
|
||||
|
||||
var userRequiredActions = []string{"UPDATE_PASSWORD", "VERIFY_EMAIL"}
|
||||
var userRequiredActions = []keycloak.UserAction{
|
||||
keycloak.UserActionUpdatePassword,
|
||||
keycloak.UserActionVerifyEmail,
|
||||
}
|
||||
|
||||
// Backend represents the keycloak backend.
|
||||
type Backend struct {
|
||||
logger log.Logger
|
||||
client GoCloak
|
||||
clientID string
|
||||
clientSecret string
|
||||
clientRealm string
|
||||
userRealm string
|
||||
logger log.Logger
|
||||
client keycloak.Client
|
||||
userRealm string
|
||||
}
|
||||
|
||||
// New instantiates a new keycloak.Backend with a default gocloak client.
|
||||
@@ -36,62 +33,50 @@ func New(
|
||||
baseURL, clientID, clientSecret, clientRealm, userRealm string,
|
||||
insecureSkipVerify bool,
|
||||
) *Backend {
|
||||
client := gocloak.NewClient(baseURL)
|
||||
restyClient := client.RestyClient()
|
||||
restyClient.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: insecureSkipVerify}) //nolint:gosec
|
||||
return NewWithClient(logger, client, clientID, clientSecret, clientRealm, userRealm)
|
||||
logger = log.Logger{
|
||||
Logger: logger.With().
|
||||
Str("invitationBackend", "keycloak").
|
||||
Str("clientID", clientID).
|
||||
Str("clientRealm", clientRealm).
|
||||
Str("userRealm", userRealm).
|
||||
Logger(),
|
||||
}
|
||||
client := keycloak.New(baseURL, clientID, clientSecret, clientRealm, insecureSkipVerify)
|
||||
return NewWithClient(logger, client, userRealm)
|
||||
}
|
||||
|
||||
// NewWithClient creates a new backend with the supplied GoCloak client.
|
||||
// NewWithClient creates a new backend with the supplied keycloak client.
|
||||
func NewWithClient(
|
||||
logger log.Logger,
|
||||
client GoCloak,
|
||||
clientID, clientSecret, clientRealm, userRealm string,
|
||||
client keycloak.Client,
|
||||
userRealm string,
|
||||
) *Backend {
|
||||
return &Backend{
|
||||
logger: log.Logger{
|
||||
Logger: logger.With().
|
||||
Str("invitationBackend", "keycloak").
|
||||
Str("clientID", clientID).
|
||||
Str("clientRealm", clientRealm).
|
||||
Str("userRealm", userRealm).
|
||||
Logger(),
|
||||
},
|
||||
client: client,
|
||||
clientID: clientID,
|
||||
clientSecret: clientSecret,
|
||||
clientRealm: clientRealm,
|
||||
userRealm: userRealm,
|
||||
logger: logger,
|
||||
client: client,
|
||||
userRealm: userRealm,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateUser creates a user in the keycloak backend.
|
||||
func (b Backend) CreateUser(ctx context.Context, invitation *invitations.Invitation) (string, error) {
|
||||
token, err := b.getToken(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
u := uuid.New()
|
||||
|
||||
b.logger.Info().
|
||||
Str(idAttr, u.String()).
|
||||
Str("email", invitation.InvitedUserEmailAddress).
|
||||
Msg("Creating new user")
|
||||
user := gocloak.User{
|
||||
Email: &invitation.InvitedUserEmailAddress,
|
||||
Enabled: gocloak.BoolP(true),
|
||||
Username: &invitation.InvitedUserEmailAddress,
|
||||
Attributes: &map[string][]string{
|
||||
idAttr: {u.String()},
|
||||
userTypeAttr: {userTypeVal},
|
||||
},
|
||||
RequiredActions: &userRequiredActions,
|
||||
user := &libregraph.User{
|
||||
Mail: &invitation.InvitedUserEmailAddress,
|
||||
AccountEnabled: boolP(true),
|
||||
OnPremisesSamAccountName: &invitation.InvitedUserEmailAddress,
|
||||
Id: stringP(u.String()),
|
||||
UserType: stringP(userType),
|
||||
}
|
||||
|
||||
id, err := b.client.CreateUser(ctx, token.AccessToken, b.userRealm, user)
|
||||
id, err := b.client.CreateUser(ctx, b.userRealm, user, userRequiredActions)
|
||||
if err != nil {
|
||||
b.logger.Error().
|
||||
Str(idAttr, u.String()).
|
||||
Str("userID", u.String()).
|
||||
Str("email", invitation.InvitedUserEmailAddress).
|
||||
Err(err).
|
||||
Msg("Failed to create user")
|
||||
@@ -106,35 +91,8 @@ func (b Backend) CanSendMail() bool { return true }
|
||||
|
||||
// SendMail sends a mail to the user with details on how to reedeem the invitation.
|
||||
func (b Backend) SendMail(ctx context.Context, id string) error {
|
||||
token, err := b.getToken(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := gocloak.ExecuteActionsEmail{
|
||||
UserID: &id,
|
||||
Actions: &userRequiredActions,
|
||||
}
|
||||
return b.client.ExecuteActionsEmail(ctx, token.AccessToken, b.userRealm, params)
|
||||
return b.client.SendActionsMail(ctx, b.userRealm, id, userRequiredActions)
|
||||
}
|
||||
|
||||
func (b Backend) getToken(ctx context.Context) (*gocloak.JWT, error) {
|
||||
b.logger.Debug().Msg("Logging into keycloak")
|
||||
token, err := b.client.LoginClient(ctx, b.clientID, b.clientSecret, b.clientRealm)
|
||||
if err != nil {
|
||||
b.logger.Error().Err(err).Msg("failed to get token")
|
||||
return nil, fmt.Errorf("failed to get token: %w", err)
|
||||
}
|
||||
|
||||
rRes, err := b.client.RetrospectToken(ctx, token.AccessToken, b.clientID, b.clientSecret, b.clientRealm)
|
||||
if err != nil {
|
||||
b.logger.Error().Err(err).Msg("failed to introspect token")
|
||||
return nil, fmt.Errorf("failed to retrospect token: %w", err)
|
||||
}
|
||||
|
||||
if !*rRes.Active {
|
||||
b.logger.Error().Msg("token not active")
|
||||
return nil, fmt.Errorf("token is not active")
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
func boolP(b bool) *bool { return &b }
|
||||
func stringP(s string) *string { return &s }
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
kcpkg "github.com/owncloud/ocis/v2/ocis-pkg/keycloak"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/invitations/pkg/backends/keycloak"
|
||||
"github.com/owncloud/ocis/v2/services/invitations/pkg/invitations"
|
||||
@@ -34,11 +34,11 @@ func TestBackend_CreateUser(t *testing.T) {
|
||||
returns []interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
keycloakMocks []mockInputs
|
||||
assertion assert.ErrorAssertionFunc
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
clientMocks []mockInputs
|
||||
assertion assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "Test without diplay name",
|
||||
@@ -48,46 +48,17 @@ func TestBackend_CreateUser(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "test-id",
|
||||
keycloakMocks: []mockInputs{
|
||||
{
|
||||
funcName: "LoginClient",
|
||||
args: []interface{}{
|
||||
mock.Anything,
|
||||
clientID,
|
||||
clientSecret,
|
||||
clientRealm,
|
||||
},
|
||||
returns: []interface{}{
|
||||
&gocloak.JWT{
|
||||
AccessToken: jwtToken,
|
||||
},
|
||||
nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "RetrospectToken",
|
||||
args: []interface{}{
|
||||
mock.Anything,
|
||||
jwtToken,
|
||||
clientID,
|
||||
clientSecret,
|
||||
clientRealm,
|
||||
},
|
||||
returns: []interface{}{
|
||||
&gocloak.IntroSpectTokenResult{
|
||||
Active: gocloak.BoolP(true),
|
||||
},
|
||||
nil,
|
||||
},
|
||||
},
|
||||
clientMocks: []mockInputs{
|
||||
{
|
||||
funcName: "CreateUser",
|
||||
args: []interface{}{
|
||||
mock.Anything,
|
||||
jwtToken,
|
||||
userRealm,
|
||||
mock.Anything, // can't match on the user because it generates a UUID internally.
|
||||
// might be worth refactoring the UUID generation to outside of the func
|
||||
[]kcpkg.UserAction{
|
||||
kcpkg.UserActionUpdatePassword,
|
||||
kcpkg.UserActionVerifyEmail,
|
||||
},
|
||||
},
|
||||
returns: []interface{}{
|
||||
"test-id",
|
||||
@@ -103,11 +74,11 @@ func TestBackend_CreateUser(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &mocks.GoCloak{}
|
||||
for _, m := range tt.keycloakMocks {
|
||||
c := &mocks.Client{}
|
||||
for _, m := range tt.clientMocks {
|
||||
c.On(m.funcName, m.args...).Return(m.returns...)
|
||||
}
|
||||
b := keycloak.NewWithClient(log.NopLogger(), c, clientID, clientSecret, clientRealm, userRealm)
|
||||
b := keycloak.NewWithClient(log.NopLogger(), c, userRealm)
|
||||
got, err := b.CreateUser(ctx, tt.args.invitation)
|
||||
tt.assertion(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
@@ -125,57 +96,26 @@ func TestBackend_SendMail(t *testing.T) {
|
||||
returns []interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
keycloakMocks []mockInputs
|
||||
assertion assert.ErrorAssertionFunc
|
||||
name string
|
||||
args args
|
||||
clientMocks []mockInputs
|
||||
assertion assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "Mail successfully sent",
|
||||
args: args{
|
||||
id: "test-id",
|
||||
},
|
||||
keycloakMocks: []mockInputs{
|
||||
clientMocks: []mockInputs{
|
||||
{
|
||||
funcName: "LoginClient",
|
||||
funcName: "SendActionsMail",
|
||||
args: []interface{}{
|
||||
mock.Anything,
|
||||
clientID,
|
||||
clientSecret,
|
||||
clientRealm,
|
||||
},
|
||||
returns: []interface{}{
|
||||
&gocloak.JWT{
|
||||
AccessToken: jwtToken,
|
||||
},
|
||||
nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "RetrospectToken",
|
||||
args: []interface{}{
|
||||
mock.Anything,
|
||||
jwtToken,
|
||||
clientID,
|
||||
clientSecret,
|
||||
clientRealm,
|
||||
},
|
||||
returns: []interface{}{
|
||||
&gocloak.IntroSpectTokenResult{
|
||||
Active: gocloak.BoolP(true),
|
||||
},
|
||||
nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
funcName: "ExecuteActionsEmail",
|
||||
args: []interface{}{
|
||||
mock.Anything,
|
||||
jwtToken,
|
||||
userRealm,
|
||||
gocloak.ExecuteActionsEmail{
|
||||
UserID: gocloak.StringP("test-id"),
|
||||
Actions: &[]string{"UPDATE_PASSWORD", "VERIFY_EMAIL"},
|
||||
"test-id",
|
||||
[]kcpkg.UserAction{
|
||||
kcpkg.UserActionUpdatePassword,
|
||||
kcpkg.UserActionVerifyEmail,
|
||||
},
|
||||
},
|
||||
returns: []interface{}{
|
||||
@@ -191,11 +131,11 @@ func TestBackend_SendMail(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := &mocks.GoCloak{}
|
||||
for _, m := range tt.keycloakMocks {
|
||||
c := &mocks.Client{}
|
||||
for _, m := range tt.clientMocks {
|
||||
c.On(m.funcName, m.args...).Return(m.returns...)
|
||||
}
|
||||
b := keycloak.NewWithClient(log.NopLogger(), c, clientID, clientSecret, clientRealm, userRealm)
|
||||
b := keycloak.NewWithClient(log.NopLogger(), c, userRealm)
|
||||
tt.assertion(t, b.SendMail(ctx, tt.args.id))
|
||||
})
|
||||
}
|
||||
|
||||
122
services/invitations/pkg/mocks/client.go
Normal file
122
services/invitations/pkg/mocks/client.go
Normal file
@@ -0,0 +1,122 @@
|
||||
// Code generated by mockery v2.22.1. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
keycloak "github.com/owncloud/ocis/v2/ocis-pkg/keycloak"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// Client is an autogenerated mock type for the Client type
|
||||
type Client struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// CreateUser provides a mock function with given fields: ctx, realm, user, userActions
|
||||
func (_m *Client) CreateUser(ctx context.Context, realm string, user *libregraph.User, userActions []keycloak.UserAction) (string, error) {
|
||||
ret := _m.Called(ctx, realm, user, userActions)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *libregraph.User, []keycloak.UserAction) (string, error)); ok {
|
||||
return rf(ctx, realm, user, userActions)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *libregraph.User, []keycloak.UserAction) string); ok {
|
||||
r0 = rf(ctx, realm, user, userActions)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, *libregraph.User, []keycloak.UserAction) error); ok {
|
||||
r1 = rf(ctx, realm, user, userActions)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPIIReport provides a mock function with given fields: ctx, realm, user
|
||||
func (_m *Client) GetPIIReport(ctx context.Context, realm string, user *libregraph.User) (*keycloak.PIIReport, error) {
|
||||
ret := _m.Called(ctx, realm, user)
|
||||
|
||||
var r0 *keycloak.PIIReport
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *libregraph.User) (*keycloak.PIIReport, error)); ok {
|
||||
return rf(ctx, realm, user)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, *libregraph.User) *keycloak.PIIReport); ok {
|
||||
r0 = rf(ctx, realm, user)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*keycloak.PIIReport)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, *libregraph.User) error); ok {
|
||||
r1 = rf(ctx, realm, user)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetUserByEmail provides a mock function with given fields: ctx, realm, email
|
||||
func (_m *Client) GetUserByEmail(ctx context.Context, realm string, email string) (*libregraph.User, error) {
|
||||
ret := _m.Called(ctx, realm, email)
|
||||
|
||||
var r0 *libregraph.User
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) (*libregraph.User, error)); ok {
|
||||
return rf(ctx, realm, email)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) *libregraph.User); ok {
|
||||
r0 = rf(ctx, realm, email)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*libregraph.User)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
|
||||
r1 = rf(ctx, realm, email)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SendActionsMail provides a mock function with given fields: ctx, realm, userID, userActions
|
||||
func (_m *Client) SendActionsMail(ctx context.Context, realm string, userID string, userActions []keycloak.UserAction) error {
|
||||
ret := _m.Called(ctx, realm, userID, userActions)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, []keycloak.UserAction) error); ok {
|
||||
r0 = rf(ctx, realm, userID, userActions)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewClient interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewClient(t mockConstructorTestingTNewClient) *Client {
|
||||
mock := &Client{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// Code generated by mockery v2.14.1. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
gocloak "github.com/Nerzal/gocloak/v13"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// GoCloak is an autogenerated mock type for the GoCloak type
|
||||
type GoCloak struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// CreateUser provides a mock function with given fields: ctx, token, realm, user
|
||||
func (_m *GoCloak) CreateUser(ctx context.Context, token string, realm string, user gocloak.User) (string, error) {
|
||||
ret := _m.Called(ctx, token, realm, user)
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, gocloak.User) string); ok {
|
||||
r0 = rf(ctx, token, realm, user)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string, gocloak.User) error); ok {
|
||||
r1 = rf(ctx, token, realm, user)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ExecuteActionsEmail provides a mock function with given fields: ctx, token, realm, params
|
||||
func (_m *GoCloak) ExecuteActionsEmail(ctx context.Context, token string, realm string, params gocloak.ExecuteActionsEmail) error {
|
||||
ret := _m.Called(ctx, token, realm, params)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, gocloak.ExecuteActionsEmail) error); ok {
|
||||
r0 = rf(ctx, token, realm, params)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoginClient provides a mock function with given fields: ctx, clientID, clientSecret, realm
|
||||
func (_m *GoCloak) LoginClient(ctx context.Context, clientID string, clientSecret string, realm string) (*gocloak.JWT, error) {
|
||||
ret := _m.Called(ctx, clientID, clientSecret, realm)
|
||||
|
||||
var r0 *gocloak.JWT
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, string) *gocloak.JWT); ok {
|
||||
r0 = rf(ctx, clientID, clientSecret, realm)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*gocloak.JWT)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok {
|
||||
r1 = rf(ctx, clientID, clientSecret, realm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RetrospectToken provides a mock function with given fields: ctx, accessToken, clientID, clientSecret, realm
|
||||
func (_m *GoCloak) RetrospectToken(ctx context.Context, accessToken string, clientID string, clientSecret string, realm string) (*gocloak.IntroSpectTokenResult, error) {
|
||||
ret := _m.Called(ctx, accessToken, clientID, clientSecret, realm)
|
||||
|
||||
var r0 *gocloak.IntroSpectTokenResult
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string) *gocloak.IntroSpectTokenResult); ok {
|
||||
r0 = rf(ctx, accessToken, clientID, clientSecret, realm)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*gocloak.IntroSpectTokenResult)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string) error); ok {
|
||||
r1 = rf(ctx, accessToken, clientID, clientSecret, realm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewGoCloak interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewGoCloak creates a new instance of GoCloak. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewGoCloak(t mockConstructorTestingTNewGoCloak) *GoCloak {
|
||||
mock := &GoCloak{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
Reference in New Issue
Block a user