diff --git a/core/utils.go b/core/utils.go index ac2cddd..d5c8aa4 100644 --- a/core/utils.go +++ b/core/utils.go @@ -20,10 +20,16 @@ import ( v1 "github.com/retailcrm/mg-transport-api-client-go/v1" ) -var DefaultScopes = []string{ - "integration_read", - "integration_write", -} +var ( + DefaultScopes = []string{ + "integration_read", + "integration_write", + } + DefaultCredentials = []string{ + "/api/integration-modules/{code}", + "/api/integration-modules/{code}/edit", + } +) var defaultCurrencies = map[string]string{ "rub": "₽", @@ -112,7 +118,9 @@ func (u *Utils) GenerateToken() string { } // GetAPIClient will initialize RetailCRM api client from url and key. -func (u *Utils) GetAPIClient(url, key string, scopes []string) (*retailcrm.Client, int, error) { +// Scopes will be used to determine if client is valid. If there are no scopes - credentials will be used instead. +func (u *Utils) GetAPIClient( + url, key string, scopes []string, credentials ...[]string) (*retailcrm.Client, int, error) { client := retailcrm.New(url, key). WithLogger(retailcrm.DebugLoggerAdapter(u.Logger)) client.Debug = u.IsDebug @@ -123,8 +131,15 @@ func (u *Utils) GetAPIClient(url, key string, scopes []string) (*retailcrm.Clien } if res := u.checkScopes(cr.Scopes, scopes); len(res) != 0 { - u.Logger.Error(url, status, res) - return nil, http.StatusBadRequest, NewInsufficientScopesErr(res) + if len(credentials) == 0 || len(cr.Scopes) > 0 { + u.Logger.Error(url, status, res) + return nil, http.StatusBadRequest, NewInsufficientScopesErr(res) + } + + if res := u.checkScopes(cr.Credentials, credentials[0]); len(res) != 0 { + u.Logger.Error(url, status, res) + return nil, http.StatusBadRequest, NewInsufficientScopesErr(res) + } } return client, 0, nil diff --git a/core/utils_test.go b/core/utils_test.go index d77c122..1250488 100644 --- a/core/utils_test.go +++ b/core/utils_test.go @@ -91,7 +91,7 @@ func (u *UtilsTest) Test_GetAPIClient_FailAPI() { } } -func (u *UtilsTest) Test_GetAPIClient_FailAPICredentials() { +func (u *UtilsTest) Test_GetAPIClient_FailAPIScopes() { resp := retailcrm.CredentialResponse{ Success: true, Scopes: []string{}, @@ -114,6 +114,29 @@ func (u *UtilsTest) Test_GetAPIClient_FailAPICredentials() { } } +func (u *UtilsTest) Test_GetAPIClient_FailAPICredentials() { + resp := retailcrm.CredentialResponse{ + Success: true, + Credentials: []string{DefaultCredentials[0]}, + SiteAccess: "all", + SitesAvailable: []string{}, + } + + data, _ := json.Marshal(resp) + + defer gock.Off() + gock.New(testCRMURL). + Get("/credentials"). + Reply(http.StatusOK). + BodyString(string(data)) + + _, status, err := u.utils.GetAPIClient(testCRMURL, "key", DefaultScopes, DefaultCredentials) + assert.Equal(u.T(), http.StatusBadRequest, status) + if assert.NotNil(u.T(), err) { + assert.True(u.T(), errors.Is(err, ErrInsufficientScopes)) + } +} + func (u *UtilsTest) Test_GetAPIClient_Success() { resp := retailcrm.CredentialResponse{ Success: true, @@ -135,6 +158,27 @@ func (u *UtilsTest) Test_GetAPIClient_Success() { assert.Equal(u.T(), 0, status) } +func (u *UtilsTest) Test_GetAPIClient_SuccessCredentials() { + resp := retailcrm.CredentialResponse{ + Success: true, + Credentials: DefaultCredentials, + SiteAccess: "all", + SitesAvailable: []string{"site"}, + } + + data, _ := json.Marshal(resp) + + defer gock.Off() + gock.New(testCRMURL). + Get("/credentials"). + Reply(http.StatusOK). + BodyString(string(data)) + + _, status, err := u.utils.GetAPIClient(testCRMURL, "key", DefaultScopes, DefaultCredentials) + require.NoError(u.T(), err) + assert.Equal(u.T(), 0, status) +} + func (u *UtilsTest) Test_UploadUserAvatar_FailGet() { defer gock.Off() gock.New("https://example.com")