github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/oauth20/resolver_test.go (about)

     1  package oauth20_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/internal/model"
     8  
     9  	pkgmodel "github.com/kyma-incubator/compass/components/director/pkg/model"
    10  
    11  	"github.com/kyma-incubator/compass/components/director/pkg/str"
    12  
    13  	"github.com/kyma-incubator/compass/components/director/internal/domain/oauth20"
    14  	"github.com/kyma-incubator/compass/components/director/internal/domain/oauth20/automock"
    15  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    16  	persistenceautomock "github.com/kyma-incubator/compass/components/director/pkg/persistence/automock"
    17  	"github.com/kyma-incubator/compass/components/director/pkg/persistence/txtest"
    18  	"github.com/pkg/errors"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  func TestResolver_CommonRequestClientCredentialsSuccess(t *testing.T) {
    24  	// GIVEN
    25  	id := "foo"
    26  	clientID := "clientid"
    27  	txGen := txtest.NewTransactionContextGenerator(nil)
    28  	expectedResult := fixGQLSystemAuth(clientID)
    29  	credsData := &model.OAuthCredentialDataInput{
    30  		ClientID:     "clientid",
    31  		ClientSecret: "secret",
    32  		URL:          "url",
    33  	}
    34  	authInput := &model.AuthInput{Credential: &model.CredentialDataInput{Oauth: credsData}}
    35  
    36  	testCases := []struct {
    37  		Name                       string
    38  		ObjType                    pkgmodel.SystemAuthReferenceObjectType
    39  		Method                     func(resolver *oauth20.Resolver, ctx context.Context, id string) (graphql.SystemAuth, error)
    40  		RtmID                      *string
    41  		AppID                      *string
    42  		IntSysID                   *string
    43  		RuntimeServiceFn           func() *automock.RuntimeService
    44  		ApplicationServiceFn       func() *automock.ApplicationService
    45  		IntegrationSystemServiceFn func() *automock.IntegrationSystemService
    46  	}{
    47  		{
    48  			Name:    "Runtime",
    49  			RtmID:   &id,
    50  			ObjType: pkgmodel.RuntimeReference,
    51  			RuntimeServiceFn: func() *automock.RuntimeService {
    52  				rtmSvc := &automock.RuntimeService{}
    53  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
    54  				return rtmSvc
    55  			},
    56  			ApplicationServiceFn: func() *automock.ApplicationService {
    57  				appSvc := &automock.ApplicationService{}
    58  				return appSvc
    59  			},
    60  			IntegrationSystemServiceFn: func() *automock.IntegrationSystemService {
    61  				isSvc := &automock.IntegrationSystemService{}
    62  				return isSvc
    63  			},
    64  			Method: func(resolver *oauth20.Resolver, ctx context.Context, id string) (graphql.SystemAuth, error) {
    65  				return resolver.RequestClientCredentialsForRuntime(ctx, id)
    66  			},
    67  		},
    68  		{
    69  			Name:    "Application",
    70  			AppID:   &id,
    71  			ObjType: pkgmodel.ApplicationReference,
    72  			RuntimeServiceFn: func() *automock.RuntimeService {
    73  				rtmSvc := &automock.RuntimeService{}
    74  				return rtmSvc
    75  			},
    76  			ApplicationServiceFn: func() *automock.ApplicationService {
    77  				appSvc := &automock.ApplicationService{}
    78  				appSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
    79  				return appSvc
    80  			},
    81  			IntegrationSystemServiceFn: func() *automock.IntegrationSystemService {
    82  				isSvc := &automock.IntegrationSystemService{}
    83  				return isSvc
    84  			},
    85  			Method: func(resolver *oauth20.Resolver, ctx context.Context, id string) (graphql.SystemAuth, error) {
    86  				return resolver.RequestClientCredentialsForApplication(ctx, id)
    87  			},
    88  		},
    89  		{
    90  			Name:     "Integration System",
    91  			IntSysID: &id,
    92  			ObjType:  pkgmodel.IntegrationSystemReference,
    93  			RuntimeServiceFn: func() *automock.RuntimeService {
    94  				rtmSvc := &automock.RuntimeService{}
    95  				return rtmSvc
    96  			},
    97  			ApplicationServiceFn: func() *automock.ApplicationService {
    98  				appSvc := &automock.ApplicationService{}
    99  				return appSvc
   100  			},
   101  			IntegrationSystemServiceFn: func() *automock.IntegrationSystemService {
   102  				isSvc := &automock.IntegrationSystemService{}
   103  				isSvc.On("Exists", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
   104  				return isSvc
   105  			},
   106  			Method: func(resolver *oauth20.Resolver, ctx context.Context, id string) (graphql.SystemAuth, error) {
   107  				return resolver.RequestClientCredentialsForIntegrationSystem(ctx, id)
   108  			},
   109  		},
   110  	}
   111  
   112  	for _, testCase := range testCases {
   113  		t.Run(testCase.Name, func(t *testing.T) {
   114  			modelSystemAuth := fixModelSystemAuth(clientID, testCase.RtmID, testCase.AppID, testCase.IntSysID)
   115  
   116  			persist, transact := txGen.ThatSucceeds()
   117  			defer persist.AssertExpectations(t)
   118  			defer transact.AssertExpectations(t)
   119  
   120  			svc := &automock.Service{}
   121  			svc.On("CreateClientCredentials", txtest.CtxWithDBMatcher(), testCase.ObjType).Return(credsData, nil).Once()
   122  			defer svc.AssertExpectations(t)
   123  
   124  			rtmSvc := testCase.RuntimeServiceFn()
   125  			defer rtmSvc.AssertExpectations(t)
   126  
   127  			appSvc := testCase.ApplicationServiceFn()
   128  			defer appSvc.AssertExpectations(t)
   129  
   130  			isSvc := testCase.IntegrationSystemServiceFn()
   131  			defer isSvc.AssertExpectations(t)
   132  
   133  			systemAuthSvc := &automock.SystemAuthService{}
   134  			systemAuthSvc.On("CreateWithCustomID", txtest.CtxWithDBMatcher(), clientID, testCase.ObjType, id, authInput).Return(clientID, nil).Once()
   135  			systemAuthSvc.On("GetByIDForObject", txtest.CtxWithDBMatcher(), testCase.ObjType, clientID).Return(modelSystemAuth, nil).Once()
   136  			defer systemAuthSvc.AssertExpectations(t)
   137  
   138  			systemAuthConv := &automock.SystemAuthConverter{}
   139  			systemAuthConv.On("ToGraphQL", modelSystemAuth).Return(expectedResult, nil).Once()
   140  			defer systemAuthConv.AssertExpectations(t)
   141  
   142  			resolver := oauth20.NewResolver(transact, svc, appSvc, rtmSvc, isSvc, systemAuthSvc, systemAuthConv)
   143  
   144  			// When
   145  			result, err := testCase.Method(resolver, context.TODO(), id)
   146  
   147  			// Then
   148  			assert.Equal(t, expectedResult, result)
   149  			assert.Nil(t, err)
   150  		})
   151  	}
   152  }
   153  
   154  func TestResolver_CommonRequestClientCredentialsError(t *testing.T) {
   155  	// GIVEN
   156  	id := "foo"
   157  	objType := pkgmodel.RuntimeReference
   158  	clientID := "clientid"
   159  	testErr := errors.New("test error")
   160  	txGen := txtest.NewTransactionContextGenerator(testErr)
   161  	modelSystemAuth := fixModelSystemAuth(clientID, &id, nil, nil)
   162  	credsData := &model.OAuthCredentialDataInput{
   163  		ClientID:     "clientid",
   164  		ClientSecret: "secret",
   165  		URL:          "url",
   166  	}
   167  	authInput := &model.AuthInput{Credential: &model.CredentialDataInput{Oauth: credsData}}
   168  
   169  	testCases := []struct {
   170  		Name                string
   171  		ExpectedError       error
   172  		RuntimeServiceFn    func() *automock.RuntimeService
   173  		ServiceFn           func() *automock.Service
   174  		SystemAuthServiceFn func() *automock.SystemAuthService
   175  		TransactionerFn     func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
   176  	}{
   177  		{
   178  			Name:            "Error - Transaction Commit",
   179  			ExpectedError:   testErr,
   180  			TransactionerFn: txGen.ThatFailsOnCommit,
   181  			RuntimeServiceFn: func() *automock.RuntimeService {
   182  				rtmSvc := &automock.RuntimeService{}
   183  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
   184  				return rtmSvc
   185  			},
   186  			ServiceFn: func() *automock.Service {
   187  				svc := &automock.Service{}
   188  				svc.On("CreateClientCredentials", txtest.CtxWithDBMatcher(), objType).Return(credsData, nil).Once()
   189  				svc.On("DeleteClientCredentials", txtest.CtxWithDBMatcher(), clientID).Return(nil).Once()
   190  				return svc
   191  			},
   192  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   193  				systemAuthSvc := &automock.SystemAuthService{}
   194  				systemAuthSvc.On("CreateWithCustomID", txtest.CtxWithDBMatcher(), clientID, objType, id, authInput).Return(clientID, nil).Once()
   195  				systemAuthSvc.On("GetByIDForObject", txtest.CtxWithDBMatcher(), objType, clientID).Return(modelSystemAuth, nil).Once()
   196  				return systemAuthSvc
   197  			},
   198  		},
   199  		{
   200  			Name:            "Error - Get System Auth",
   201  			ExpectedError:   testErr,
   202  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   203  			RuntimeServiceFn: func() *automock.RuntimeService {
   204  				rtmSvc := &automock.RuntimeService{}
   205  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
   206  				return rtmSvc
   207  			},
   208  			ServiceFn: func() *automock.Service {
   209  				svc := &automock.Service{}
   210  				svc.On("CreateClientCredentials", txtest.CtxWithDBMatcher(), objType).Return(credsData, nil).Once()
   211  				svc.On("DeleteClientCredentials", txtest.CtxWithDBMatcher(), clientID).Return(nil).Once()
   212  				return svc
   213  			},
   214  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   215  				systemAuthSvc := &automock.SystemAuthService{}
   216  				systemAuthSvc.On("CreateWithCustomID", txtest.CtxWithDBMatcher(), clientID, objType, id, authInput).Return(clientID, nil).Once()
   217  				systemAuthSvc.On("GetByIDForObject", txtest.CtxWithDBMatcher(), objType, clientID).Return(nil, testErr).Once()
   218  				return systemAuthSvc
   219  			},
   220  		},
   221  		{
   222  			Name:            "Error - Create System Auth",
   223  			ExpectedError:   testErr,
   224  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   225  			RuntimeServiceFn: func() *automock.RuntimeService {
   226  				rtmSvc := &automock.RuntimeService{}
   227  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
   228  				return rtmSvc
   229  			},
   230  			ServiceFn: func() *automock.Service {
   231  				svc := &automock.Service{}
   232  				svc.On("CreateClientCredentials", txtest.CtxWithDBMatcher(), objType).Return(credsData, nil).Once()
   233  				svc.On("DeleteClientCredentials", txtest.CtxWithDBMatcher(), clientID).Return(nil).Once()
   234  				return svc
   235  			},
   236  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   237  				systemAuthSvc := &automock.SystemAuthService{}
   238  				systemAuthSvc.On("CreateWithCustomID", txtest.CtxWithDBMatcher(), clientID, objType, id, authInput).Return("", testErr).Once()
   239  				return systemAuthSvc
   240  			},
   241  		},
   242  		{
   243  			Name:            "Error - Multiple: Create System Auth and Delete Client",
   244  			ExpectedError:   errors.New("2 errors occurred:\n\t* test error\n\t* test error"),
   245  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   246  			RuntimeServiceFn: func() *automock.RuntimeService {
   247  				rtmSvc := &automock.RuntimeService{}
   248  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
   249  				return rtmSvc
   250  			},
   251  			ServiceFn: func() *automock.Service {
   252  				svc := &automock.Service{}
   253  				svc.On("CreateClientCredentials", txtest.CtxWithDBMatcher(), objType).Return(credsData, nil).Once()
   254  				svc.On("DeleteClientCredentials", txtest.CtxWithDBMatcher(), clientID).Return(testErr).Once()
   255  				return svc
   256  			},
   257  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   258  				systemAuthSvc := &automock.SystemAuthService{}
   259  				systemAuthSvc.On("CreateWithCustomID", txtest.CtxWithDBMatcher(), clientID, objType, id, authInput).Return("", testErr).Once()
   260  				return systemAuthSvc
   261  			},
   262  		},
   263  		{
   264  			Name:            "Error - Create Client",
   265  			ExpectedError:   testErr,
   266  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   267  			RuntimeServiceFn: func() *automock.RuntimeService {
   268  				rtmSvc := &automock.RuntimeService{}
   269  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
   270  				return rtmSvc
   271  			},
   272  			ServiceFn: func() *automock.Service {
   273  				svc := &automock.Service{}
   274  				svc.On("CreateClientCredentials", txtest.CtxWithDBMatcher(), objType).Return(nil, testErr).Once()
   275  				return svc
   276  			},
   277  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   278  				systemAuthSvc := &automock.SystemAuthService{}
   279  				return systemAuthSvc
   280  			},
   281  		},
   282  		{
   283  			Name:            "Error - Empty Credentials",
   284  			ExpectedError:   errors.New("client credentials cannot be empty"),
   285  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   286  			RuntimeServiceFn: func() *automock.RuntimeService {
   287  				rtmSvc := &automock.RuntimeService{}
   288  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(true, nil).Once()
   289  				return rtmSvc
   290  			},
   291  			ServiceFn: func() *automock.Service {
   292  				svc := &automock.Service{}
   293  				svc.On("CreateClientCredentials", txtest.CtxWithDBMatcher(), objType).Return(nil, nil).Once()
   294  				return svc
   295  			},
   296  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   297  				systemAuthSvc := &automock.SystemAuthService{}
   298  				return systemAuthSvc
   299  			},
   300  		},
   301  		{
   302  			Name:            "Error - Exists",
   303  			ExpectedError:   testErr,
   304  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   305  			RuntimeServiceFn: func() *automock.RuntimeService {
   306  				rtmSvc := &automock.RuntimeService{}
   307  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(false, testErr).Once()
   308  				return rtmSvc
   309  			},
   310  			ServiceFn: func() *automock.Service {
   311  				svc := &automock.Service{}
   312  				return svc
   313  			},
   314  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   315  				systemAuthSvc := &automock.SystemAuthService{}
   316  				return systemAuthSvc
   317  			},
   318  		},
   319  		{
   320  			Name:            "Error - Doesn't Exist",
   321  			ExpectedError:   errors.New("Runtime with ID 'foo' not found"),
   322  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   323  			RuntimeServiceFn: func() *automock.RuntimeService {
   324  				rtmSvc := &automock.RuntimeService{}
   325  				rtmSvc.On("Exist", txtest.CtxWithDBMatcher(), id).Return(false, nil).Once()
   326  				return rtmSvc
   327  			},
   328  			ServiceFn: func() *automock.Service {
   329  				svc := &automock.Service{}
   330  				return svc
   331  			},
   332  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   333  				systemAuthSvc := &automock.SystemAuthService{}
   334  				return systemAuthSvc
   335  			},
   336  		},
   337  		{
   338  			Name:            "Error - Transaction Begin error",
   339  			ExpectedError:   testErr,
   340  			TransactionerFn: txGen.ThatFailsOnBegin,
   341  			RuntimeServiceFn: func() *automock.RuntimeService {
   342  				rtmSvc := &automock.RuntimeService{}
   343  				return rtmSvc
   344  			},
   345  			ServiceFn: func() *automock.Service {
   346  				svc := &automock.Service{}
   347  				return svc
   348  			},
   349  			SystemAuthServiceFn: func() *automock.SystemAuthService {
   350  				systemAuthSvc := &automock.SystemAuthService{}
   351  				return systemAuthSvc
   352  			},
   353  		},
   354  	}
   355  
   356  	for _, testCase := range testCases {
   357  		t.Run(testCase.Name, func(t *testing.T) {
   358  			persist, transact := testCase.TransactionerFn()
   359  			defer persist.AssertExpectations(t)
   360  			defer transact.AssertExpectations(t)
   361  
   362  			svc := testCase.ServiceFn()
   363  			defer svc.AssertExpectations(t)
   364  
   365  			rtmSvc := testCase.RuntimeServiceFn()
   366  			defer rtmSvc.AssertExpectations(t)
   367  
   368  			systemAuthSvc := testCase.SystemAuthServiceFn()
   369  			defer systemAuthSvc.AssertExpectations(t)
   370  
   371  			resolver := oauth20.NewResolver(transact, svc, nil, rtmSvc, nil, systemAuthSvc, nil)
   372  
   373  			// When
   374  			_, err := resolver.RequestClientCredentialsForRuntime(context.TODO(), id)
   375  
   376  			// Then
   377  			require.Error(t, err)
   378  			assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
   379  		})
   380  	}
   381  }
   382  
   383  func fixModelSystemAuth(clientID string, rtmID, appID, isID *string) *pkgmodel.SystemAuth {
   384  	return &pkgmodel.SystemAuth{
   385  		ID:                  clientID,
   386  		TenantID:            str.Ptr(""),
   387  		RuntimeID:           rtmID,
   388  		IntegrationSystemID: isID,
   389  		AppID:               appID,
   390  		Value: &model.Auth{
   391  			Credential: model.CredentialData{
   392  				Oauth: &model.OAuthCredentialData{
   393  					ClientID:     clientID,
   394  					ClientSecret: "secret",
   395  					URL:          "url",
   396  				},
   397  			},
   398  		},
   399  	}
   400  }
   401  
   402  func fixGQLSystemAuth(clientID string) graphql.SystemAuth {
   403  	oauthCredsData := graphql.OAuthCredentialData{
   404  		ClientID:     clientID,
   405  		ClientSecret: "secret",
   406  		URL:          "url",
   407  	}
   408  	return &graphql.IntSysSystemAuth{
   409  		ID: "sysauth-id",
   410  		Auth: &graphql.Auth{
   411  			Credential: oauthCredsData,
   412  		},
   413  	}
   414  }