diff --git a/.github/create-cli-pr.sh b/.github/create-cli-pr.sh index d9ed13853..7c64b0d21 100755 --- a/.github/create-cli-pr.sh +++ b/.github/create-cli-pr.sh @@ -28,7 +28,8 @@ BODY=$(printf "## Changes since last integration of Language Server\n\n\`\`\`\n% BRANCH=feat/automatic-upgrade-of-ls pushd $CLI_DIR - git checkout $BRANCH || git checkout -b $BRANCH + git checkout -B $BRANCH + git rebase --ignore-whitespace main UPGRADE=$(go run scripts/upgrade-snyk-go-dependencies.go --name=snyk-ls) LS_VERSION=$(echo $UPGRADE | sed 's/.*Sha: \(.*\) URL.*/\1/') diff --git a/README.md b/README.md index de1c454cf..70a10d700 100644 --- a/README.md +++ b/README.md @@ -339,7 +339,7 @@ within `initializationOptions?: LSPAny;` we support the following settings: "cliPath": "/a/patch/snyk-cli", // The path where the CLI can be found, or where it should be downloaded to "token": "secret-token", - // The Snyk token, e.g.: snyk config get api or a token from oauth flow + // The Snyk token, e.g.: snyk config get api or a token from authentication flow "automaticAuthentication": "true", // Whether LS will automatically authenticate on scan start (default: true) "enableTrustedFoldersFeature": "true", @@ -369,7 +369,7 @@ within `initializationOptions?: LSPAny;` we support the following settings: "scanningMode": "auto", // Specifies the mode for scans: "auto" for background scans or "manual" for scans on command "authenticationMethod": "token", - // Specifies the authentication method to use: "token" for Snyk API token or "oauth" for Snyk OAuth flow. Default is token. + // Specifies the authentication method to use: "token" for Snyk API token or "authentication" for Snyk OAuth flow. Default is token. "snykCodeApi": "https://deeproxy.snyk.io", // Specifies the Snyk Code API endpoint to use. Default is https://deeproxy.snyk.io "requiredProtocolVersion": "11" diff --git a/application/codeaction/codeaction.go b/application/codeaction/codeaction.go index 520390045..11c32e568 100644 --- a/application/codeaction/codeaction.go +++ b/application/codeaction/codeaction.go @@ -13,10 +13,11 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/command" "github.com/snyk/snyk-ls/domain/ide/converter" - noti "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/code" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" ) @@ -116,7 +117,7 @@ func (c *CodeActionsService) ResolveCodeAction(action lsp.CodeAction, server lsp func (c *CodeActionsService) handleCommand(action lsp.CodeAction, server lsp.Server) (lsp.CodeAction, error) { c.logger.Info().Str("method", "codeaction.handleCommand").Msgf("handling command %s", action.Command.Command) - cmd := snyk.CommandData{ + cmd := types.CommandData{ Title: action.Command.Title, CommandId: action.Command.Command, Arguments: action.Command.Arguments, diff --git a/application/codeaction/codeaction_test.go b/application/codeaction/codeaction_test.go index 7f5accfae..02ca505a7 100644 --- a/application/codeaction/codeaction_test.go +++ b/application/codeaction/codeaction_test.go @@ -34,6 +34,7 @@ import ( "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" ) @@ -246,11 +247,11 @@ func Test_ResolveCodeAction_CommandIsExecuted(t *testing.T) { service := setupService() id := lsp.CodeActionData(uuid.New()) - command.SetService(snyk.NewCommandServiceMock()) + command.SetService(types.NewCommandServiceMock()) c := &sglsp.Command{ - Title: snyk.LoginCommand, - Command: snyk.LoginCommand, + Title: types.LoginCommand, + Command: types.LoginCommand, } ca := lsp.CodeAction{ Title: "Made up CA", @@ -262,7 +263,7 @@ func Test_ResolveCodeAction_CommandIsExecuted(t *testing.T) { _, err := service.ResolveCodeAction(ca, nil) assert.NoError(t, err, "command should be called without error") - serviceMock := command.Service().(*snyk.CommandServiceMock) + serviceMock := command.Service().(*types.CommandServiceMock) assert.Len(t, serviceMock.ExecutedCommands(), 1) assert.Equal(t, serviceMock.ExecutedCommands()[0].CommandId, c.Command) } diff --git a/application/config/config.go b/application/config/config.go index f9016d11c..f5bb0393a 100644 --- a/application/config/config.go +++ b/application/config/config.go @@ -33,6 +33,7 @@ import ( "github.com/snyk/go-application-framework/pkg/runtimeinfo" "github.com/snyk/snyk-ls/infrastructure/cli/cli_constants" "github.com/snyk/snyk-ls/internal/logging" + storage2 "github.com/snyk/snyk-ls/internal/storage" "github.com/adrg/xdg" "github.com/denisbrodbeck/machineid" @@ -190,7 +191,7 @@ type Config struct { enableSnykLearnCodeActions bool enableSnykOSSQuickFixCodeActions bool logger *zerolog.Logger - storage StorageWithCallbacks + storage storage2.StorageWithCallbacks m sync.Mutex clientProtocolVersion string } @@ -250,7 +251,7 @@ func New() *Config { func initWorkFlowEngine(c *Config) { conf := configuration.NewInMemory() c.engine = app.CreateAppEngineWithOptions(app.WithConfiguration(conf), app.WithZeroLogger(c.logger)) - c.storage = NewStorage() + c.storage = storage2.NewStorage() conf.SetStorage(c.storage) conf.Set(configuration.FF_OAUTH_AUTH_FLOW_ENABLED, true) conf.Set(cli_constants.EXECUTION_MODE_KEY, cli_constants.EXECUTION_MODE_VALUE_STANDALONE) @@ -486,7 +487,7 @@ func (c *Config) SetToken(token string) { } if isOauthToken && conf.GetString(auth.CONFIG_KEY_OAUTH_TOKEN) != token { - c.Logger().Info().Err(err).Msg("setting oauth authentication in GAF") + c.Logger().Info().Err(err).Msg("setting oauth2 authentication in GAF") conf.Set(auth.CONFIG_KEY_OAUTH_TOKEN, token) } @@ -850,14 +851,6 @@ func (c *Config) IsAutoScanEnabled() bool { return c.automaticScanning } -func (c *Config) SetAuthenticationMethod(method lsp.AuthenticationMethod) { - c.authenticationMethod = method -} - -func (c *Config) AuthenticationMethod() lsp.AuthenticationMethod { - return c.authenticationMethod -} - func (c *Config) Engine() workflow.Engine { return c.engine } @@ -906,19 +899,19 @@ func (c *Config) Logger() *zerolog.Logger { func (c *Config) TokenAsOAuthToken() (oauth2.Token, error) { var oauthToken oauth2.Token if _, err := uuid.Parse(c.Token()); err == nil { - msg := "creds are legacy, not oauth" + msg := "creds are legacy, not oauth2" c.Logger().Trace().Msgf(msg) return oauthToken, fmt.Errorf(msg) } err := json.Unmarshal([]byte(c.Token()), &oauthToken) if err != nil { - c.Logger().Trace().Err(err).Msg("unable to unmarshal oauth creds") + c.Logger().Trace().Err(err).Msg("unable to unmarshal creds to oauth2 token") return oauthToken, err } return oauthToken, nil } -func (c *Config) Storage() StorageWithCallbacks { +func (c *Config) Storage() storage2.StorageWithCallbacks { return c.storage } @@ -951,3 +944,11 @@ func (c *Config) IsAnalyticsPermitted() bool { func (c *Config) SetClientProtocolVersion(requiredProtocolVersion string) { c.clientProtocolVersion = requiredProtocolVersion } + +func (c *Config) AuthenticationMethod() lsp.AuthenticationMethod { + return c.authenticationMethod +} + +func (c *Config) SetAuthenticationMethod(authMethod lsp.AuthenticationMethod) { + c.authenticationMethod = authMethod +} diff --git a/application/di/init.go b/application/di/init.go index 8f4886ba8..1f1c19bc3 100644 --- a/application/di/init.go +++ b/application/di/init.go @@ -26,7 +26,6 @@ import ( codeClient "github.com/snyk/code-client-go" codeClientHTTP "github.com/snyk/code-client-go/http" codeClientObservability "github.com/snyk/code-client-go/observability" - "github.com/snyk/snyk-ls/application/codeaction" "github.com/snyk/snyk-ls/application/config" appNotification "github.com/snyk/snyk-ls/application/server/notification" @@ -34,15 +33,11 @@ import ( "github.com/snyk/snyk-ls/domain/ide/command" "github.com/snyk/snyk-ls/domain/ide/hover" "github.com/snyk/snyk-ls/domain/ide/initialize" - "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/ide/workspace" - er "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/amplitude" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/cli" - cliauth "github.com/snyk/snyk-ls/infrastructure/cli/auth" "github.com/snyk/snyk-ls/infrastructure/cli/cli_constants" "github.com/snyk/snyk-ls/infrastructure/cli/install" "github.com/snyk/snyk-ls/infrastructure/code" @@ -51,7 +46,11 @@ import ( "github.com/snyk/snyk-ls/infrastructure/oss" "github.com/snyk/snyk-ls/infrastructure/sentry" "github.com/snyk/snyk-ls/infrastructure/snyk_api" + "github.com/snyk/snyk-ls/internal/notification" domainNotify "github.com/snyk/snyk-ls/internal/notification" + er "github.com/snyk/snyk-ls/internal/observability/error_reporting" + performance2 "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" ) var snykApiClient snyk_api.SnykApiClient @@ -61,9 +60,9 @@ var snykCodeScanner *code.Scanner var infrastructureAsCodeScanner *iac.Scanner var openSourceScanner snyk.ProductScanner var scanInitializer initialize.Initializer -var authenticationService snyk.AuthenticationService +var authenticationService authentication.AuthenticationService var learnService learn.Service -var instrumentor performance.Instrumentor +var instrumentor performance2.Instrumentor var errorReporter er.ErrorReporter var installer install.Installer var analytics ux.Analytics @@ -132,14 +131,20 @@ func initInfrastructure(c *config.Config) { errorReporter = sentry.NewSentryErrorReporter(c, notifier) installer = install.NewInstaller(errorReporter, networkAccess.GetUnauthorizedHttpClient) learnService = learn.New(c, networkAccess.GetUnauthorizedHttpClient, errorReporter) - instrumentor = performance.NewInstrumentor() + instrumentor = performance2.NewInstrumentor() snykApiClient = snyk_api.NewSnykApiClient(c, networkAccess.GetHttpClient) - analytics = amplitude.NewAmplitudeClient(c, snyk.AuthenticationCheck, errorReporter) - authProvider := cliauth.NewCliAuthenticationProvider(c, errorReporter) - authenticationService = snyk.NewAuthenticationService(c, authProvider, analytics, errorReporter, notifier) - snykCli := cli.NewExecutor(c, authenticationService, errorReporter, analytics, notifier) + analytics = amplitude.NewAmplitudeClient(c, authentication.AuthenticationCheck, errorReporter) + gafConfiguration := c.Engine().GetConfiguration() + + // we initialize the service without providers + authenticationService = authentication.NewAuthenticationService(c, nil, analytics, errorReporter, notifier) + // after having an instance, we pass it into the default configuration method + // so that the oauth2 provider can use it for its callback + authenticationService.ConfigureProviders(c) + + snykCli := cli.NewExecutor(c, errorReporter, analytics, notifier) - if c.Engine().GetConfiguration().GetString(cli_constants.EXECUTION_MODE_KEY) == cli_constants.EXECUTION_MODE_VALUE_EXTENSION { + if gafConfiguration.GetString(cli_constants.EXECUTION_MODE_KEY) == cli_constants.EXECUTION_MODE_VALUE_EXTENSION { snykCli = cli.NewExtensionExecutor(c) } @@ -171,7 +176,7 @@ func initInfrastructure(c *config.Config) { snykCodeScanner = code.New(snykCodeBundleUploader, snykApiClient, codeErrorReporter, analytics, learnService, notifier, codeClientScanner) cliInitializer = cli.NewInitializer(errorReporter, installer, notifier, snykCli) - authInitializer := cliauth.NewInitializer(c, authenticationService, errorReporter, analytics, notifier) + authInitializer := authentication.NewInitializer(c, authenticationService, errorReporter, analytics, notifier) scanInitializer = initialize.NewDelegatingInitializer( cliInitializer, authInitializer, @@ -210,7 +215,7 @@ func ErrorReporter() er.ErrorReporter { return errorReporter } -func AuthenticationService() snyk.AuthenticationService { +func AuthenticationService() authentication.AuthenticationService { initMutex.Lock() defer initMutex.Unlock() return authenticationService diff --git a/application/di/test_init.go b/application/di/test_init.go index d21548ac7..8485b276d 100644 --- a/application/di/test_init.go +++ b/application/di/test_init.go @@ -29,12 +29,9 @@ import ( "github.com/snyk/snyk-ls/domain/ide/hover" "github.com/snyk/snyk-ls/domain/ide/initialize" "github.com/snyk/snyk-ls/domain/ide/workspace" - er "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/cli" - cliauth "github.com/snyk/snyk-ls/infrastructure/cli/auth" "github.com/snyk/snyk-ls/infrastructure/cli/install" "github.com/snyk/snyk-ls/infrastructure/code" "github.com/snyk/snyk-ls/infrastructure/iac" @@ -43,6 +40,10 @@ import ( "github.com/snyk/snyk-ls/infrastructure/oss" "github.com/snyk/snyk-ls/infrastructure/snyk_api" domainNotify "github.com/snyk/snyk-ls/internal/notification" + er "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" + "github.com/snyk/snyk-ls/internal/types" ) // TODO this is becoming a hot mess we need to unify integ. test strategies @@ -52,18 +53,18 @@ func TestInit(t *testing.T) { t.Helper() c := config.CurrentConfig() // we don't want to open browsers when testing - snyk.DefaultOpenBrowserFunc = func(url string) {} + types.DefaultOpenBrowserFunc = func(url string) {} notifier = domainNotify.NewNotifier() analytics = ux.NewTestAnalytics(c) instrumentor = performance.NewInstrumentor() errorReporter = er.NewTestErrorReporter() installer = install.NewFakeInstaller() - authProvider := snyk.NewFakeCliAuthenticationProvider(c) + authProvider := authentication.NewFakeCliAuthenticationProvider(c) snykApiClient = &snyk_api.FakeApiClient{CodeEnabled: true} - authenticationService = snyk.NewAuthenticationService(c, authProvider, analytics, errorReporter, notifier) - snykCli := cli.NewExecutor(c, authenticationService, errorReporter, analytics, notifier) + authenticationService = authentication.NewAuthenticationService(c, []authentication.AuthenticationProvider{authProvider}, analytics, errorReporter, notifier) + snykCli := cli.NewExecutor(c, errorReporter, analytics, notifier) cliInitializer = cli.NewInitializer(errorReporter, installer, notifier, snykCli) - authInitializer := cliauth.NewInitializer(c, authenticationService, errorReporter, analytics, notifier) + authInitializer := authentication.NewInitializer(c, authenticationService, errorReporter, analytics, notifier) scanInitializer = initialize.NewDelegatingInitializer( cliInitializer, authInitializer, @@ -100,7 +101,7 @@ func TestInit(t *testing.T) { openSourceScanner, ) hoverService = hover.NewDefaultService(c, analytics) - command.SetService(&snyk.CommandServiceMock{}) + command.SetService(&types.CommandServiceMock{}) // don't use getters or it'll deadlock w := workspace.New(c, instrumentor, scanner, hoverService, scanNotifier, notifier) workspace.Set(w) diff --git a/application/server/configuration.go b/application/server/configuration.go index 9606bf518..31696a7f5 100644 --- a/application/server/configuration.go +++ b/application/server/configuration.go @@ -18,8 +18,6 @@ package server import ( "context" - "errors" - "fmt" "os" "reflect" "strconv" @@ -27,19 +25,13 @@ import ( "github.com/creachadair/jrpc2" "github.com/creachadair/jrpc2/handler" - "golang.org/x/oauth2" - "github.com/snyk/go-application-framework/pkg/auth" "github.com/snyk/go-application-framework/pkg/configuration" - "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/application/di" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/observability/ux" - "github.com/snyk/snyk-ls/domain/snyk" - auth2 "github.com/snyk/snyk-ls/infrastructure/cli/auth" - "github.com/snyk/snyk-ls/infrastructure/oauth" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/observability/ux" ) var cachedOriginalPath = "" @@ -126,15 +118,9 @@ func writeSettings(c *config.Config, settings lsp.Settings, initialize bool) { updateSeverityFilter(c, settings.FilterSeverity) updateProductEnablement(c, settings) updateCliConfig(c, settings) - - // updateApiEndpoints overwrites the authentication method in certain cases (oauth2) - // this is why it needs to be called after updateAuthenticationMethod updateAuthenticationMethod(c, settings) updateApiEndpoints(c, settings, initialize) - - // setting the token requires to know the authentication method updateToken(settings.Token) - updateEnvironment(c, settings) updatePathFromSettings(c, settings) updateTelemetry(c, settings) @@ -150,56 +136,12 @@ func writeSettings(c *config.Config, settings lsp.Settings, initialize bool) { } func updateAuthenticationMethod(c *config.Config, settings lsp.Settings) { - if settings.AuthenticationMethod == "" { - return - } - c.SetAuthenticationMethod(settings.AuthenticationMethod) - if c.AuthenticationMethod() == lsp.OAuthAuthentication { - configureOAuth(c, auth.RefreshToken) - } else { - cliAuthenticationProvider := auth2.NewCliAuthenticationProvider(c, di.ErrorReporter()) - di.AuthenticationService().SetProvider(cliAuthenticationProvider) - } -} - -func credentialsUpdateCallback(_ string, value any) { - newToken, ok := value.(string) - if !ok { - msg := fmt.Sprintf("Failed to cast creds of type %T to string", value) - di.ErrorReporter().CaptureError(errors.New(msg)) + if lsp.EmptyAuthenticationMethod == settings.AuthenticationMethod { return } - go di.AuthenticationService().UpdateCredentials(newToken, true) -} - -func configureOAuth( - c *config.Config, - customTokenRefresherFunc func( - ctx context.Context, - oauthConfig *oauth2.Config, - token *oauth2.Token, - ) (*oauth2.Token, error), -) { - engine := c.Engine() - conf := engine.GetConfiguration() - - authenticationService := di.AuthenticationService() - - openBrowserFunc := func(url string) { - authenticationService.Provider().SetAuthURL(url) - snyk.DefaultOpenBrowserFunc(url) - } - conf.Set(configuration.FF_OAUTH_AUTH_FLOW_ENABLED, true) - c.Storage().RegisterCallback(auth.CONFIG_KEY_OAUTH_TOKEN, credentialsUpdateCallback) - - authenticator := auth.NewOAuth2AuthenticatorWithOpts( - conf, - auth.WithOpenBrowserFunc(openBrowserFunc), - auth.WithTokenRefresherFunc(customTokenRefresherFunc), - ) - oAuthProvider := oauth.NewOAuthProvider(conf, authenticator, c.Logger()) - authenticationService.SetProvider(oAuthProvider) + c.SetAuthenticationMethod(settings.AuthenticationMethod) + di.AuthenticationService().ConfigureProviders(c) } func updateRuntimeInfo(c *config.Config, settings lsp.Settings) { @@ -282,12 +224,6 @@ func updateApiEndpoints(c *config.Config, settings lsp.Settings, initialization workspace.Get().Clear() } - // overwrite authentication method if gov domain - if c.IsFedramp() { - settings.AuthenticationMethod = lsp.OAuthAuthentication - updateAuthenticationMethod(c, settings) - } - // a custom set snyk code api (e.g. for testing) always overwrites automatic config if settings.SnykCodeApi != "" { c.SetSnykCodeApi(settings.SnykCodeApi) diff --git a/application/server/configuration_test.go b/application/server/configuration_test.go index 34d22d85a..f7e5f3d1f 100644 --- a/application/server/configuration_test.go +++ b/application/server/configuration_test.go @@ -18,10 +18,7 @@ package server import ( "context" - "encoding/json" "fmt" - "net/http" - "net/http/httptest" "os" "strconv" "strings" @@ -31,16 +28,13 @@ import ( "github.com/creachadair/jrpc2" "github.com/google/uuid" "github.com/stretchr/testify/assert" - "golang.org/x/oauth2" - "github.com/snyk/go-application-framework/pkg/auth" "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/application/di" - "github.com/snyk/snyk-ls/domain/observability/ux" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/testutil" ) @@ -73,80 +67,6 @@ func keyFoundInEnv(key string) bool { return found } -func Test_configureOauth_registersStorageCallback(t *testing.T) { - c := testutil.UnitTest(t) - di.TestInit(t) - c.SetAuthenticationMethod(lsp.OAuthAuthentication) - - // a token that's set into the configuration - token := oauth2.Token{ - AccessToken: t.Name(), - RefreshToken: t.Name(), - Expiry: time.Now().Add(1 * time.Hour), - } - - configureOAuth(c, auth.RefreshToken) - - tokenReceived := make(chan bool, 1) - di.Notifier().CreateListener(func(params any) { - msg, ok := params.(lsp.AuthenticationParams) - assert.True(t, ok, "Received unexpected message type %v", params) - assert.Contains(t, msg.Token, token.AccessToken) - tokenReceived <- true - }) - marshal, err := json.Marshal(token) - assert.NoError(t, err) - err = c.Storage().Set(auth.CONFIG_KEY_OAUTH_TOKEN, string(marshal)) - assert.NoError(t, err) - assert.Eventuallyf(t, func() bool { - return <-tokenReceived - }, 5*time.Second, 100*time.Millisecond, "token should have been received") -} - -func Test_configureOauth_oauthProvider_created_with_injected_refreshMethod(t *testing.T) { - c := testutil.UnitTest(t) - di.TestInit(t) - c.SetAuthenticationMethod(lsp.OAuthAuthentication) - - // an expired token that's set into the configuration - token := oauth2.Token{ - AccessToken: t.Name(), - RefreshToken: t.Name(), - Expiry: time.Now().Add(-1 * time.Hour), - } - - tokenBytes, err := json.Marshal(token) - assert.NoError(t, err) - - c.SetToken(string(tokenBytes)) - - // refresh func is replaced with func that sends true into a channel when called - triggeredChan := make(chan bool, 1) - testFunc := func(ctx context.Context, oauthConfig *oauth2.Config, token *oauth2.Token) (*oauth2.Token, error) { - triggeredChan <- true - token.Expiry = time.Now().Add(1 * time.Hour) - return token, nil - } - - // test interface to be able to access the Authenticator (oauthProvider implements it) - type providerWithAccessibleAuthenticator interface { - snyk.AuthenticationProvider - Authenticator() auth.Authenticator - } - - configureOAuth(c, testFunc) - - provider, ok := di.AuthenticationService().Provider().(providerWithAccessibleAuthenticator) - assert.True(t, ok, "provider should be of type providerWithAccessibleAuthenticator") - - // AddAuthenticationHeader will trigger the refresh method - _ = provider.Authenticator().AddAuthenticationHeader(httptest.NewRequest(http.MethodGet, "/", nil)) - - assert.Eventuallyf(t, func() bool { - return <-triggeredChan - }, 5*time.Second, 100*time.Millisecond, "refresh should have been triggered") -} - func Test_WorkspaceDidChangeConfiguration_Push(t *testing.T) { di.TestInit(t) loc, _ := setupServer(t) @@ -242,18 +162,11 @@ func Test_WorkspaceDidChangeConfiguration_PullNoCapability(t *testing.T) { } func Test_UpdateSettings(t *testing.T) { - c := testutil.UnitTest(t) di.TestInit(t) orgUuid, _ := uuid.NewRandom() expectedOrgId := orgUuid.String() - t.Run("snykgov.io substring endpoint enables oauth authentication in init", func(t *testing.T) { - endpoint := "https://app.fedramp.snykgov.io/api/v1" - updateApiEndpoints(c, lsp.Settings{Endpoint: endpoint}, true) - assert.Equal(t, lsp.OAuthAuthentication, config.CurrentConfig().AuthenticationMethod()) - }) - t.Run("All settings are updated", func(t *testing.T) { c := testutil.UnitTest(t) @@ -307,7 +220,6 @@ func Test_UpdateSettings(t *testing.T) { assert.Equal(t, settings.RuntimeName, c.RuntimeName()) assert.Equal(t, settings.RuntimeVersion, c.RuntimeVersion()) assert.False(t, c.IsAutoScanEnabled()) - assert.Equal(t, lsp.OAuthAuthentication, c.AuthenticationMethod()) assert.Equal(t, sampleSettings.SnykCodeApi, c.SnykCodeApi()) }) @@ -529,16 +441,6 @@ func Test_InitializeSettings(t *testing.T) { assert.Equal(t, true, c.IsSnykCodeQualityEnabled()) }) - t.Run("authenticationMethod is passed", func(t *testing.T) { - c := testutil.UnitTest(t) - di.TestInit(t) - assert.Equal(t, lsp.TokenAuthentication, c.AuthenticationMethod()) - - InitializeSettings(c, lsp.Settings{AuthenticationMethod: lsp.OAuthAuthentication}) - - assert.Equal(t, lsp.OAuthAuthentication, c.AuthenticationMethod()) - }) - t.Run("custom path configuration", func(t *testing.T) { c := testutil.UnitTest(t) diff --git a/application/server/execute_command.go b/application/server/execute_command.go index 62f17db89..275577679 100644 --- a/application/server/execute_command.go +++ b/application/server/execute_command.go @@ -26,7 +26,7 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/command" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/types" ) func executeCommandHandler(srv *jrpc2.Server) jrpc2.Handler { @@ -39,7 +39,7 @@ func executeCommandHandler(srv *jrpc2.Server) jrpc2.Handler { c.Logger().Info().Str("method", method).Interface("command", params).Msg("RECEIVING") defer c.Logger().Info().Str("method", method).Interface("command", params).Msg("SENDING") - commandData := snyk.CommandData{CommandId: params.Command, Arguments: params.Arguments, Title: params.Command} + commandData := types.CommandData{CommandId: params.Command, Arguments: params.Arguments, Title: params.Command} result, err := command.Service().ExecuteCommandData(bgCtx, commandData, srv) logError(c.Logger(), err, fmt.Sprintf("Error executing command %v", commandData)) diff --git a/application/server/execute_command_test.go b/application/server/execute_command_test.go index 18910921b..ef0af390c 100644 --- a/application/server/execute_command_test.go +++ b/application/server/execute_command_test.go @@ -29,6 +29,8 @@ import ( "github.com/snyk/snyk-ls/domain/ide/command" "github.com/snyk/snyk-ls/domain/ide/workspace" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" + "github.com/snyk/snyk-ls/internal/types" ) func Test_executeWorkspaceScanCommand_shouldStartWorkspaceScanOnCommandReceipt(t *testing.T) { @@ -38,7 +40,7 @@ func Test_executeWorkspaceScanCommand_shouldStartWorkspaceScanOnCommandReceipt(t scanner := &snyk.TestScanner{} workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", scanner, di.HoverService(), di.ScanNotifier(), di.Notifier())) - params := lsp.ExecuteCommandParams{Command: snyk.WorkspaceScanCommand} + params := lsp.ExecuteCommandParams{Command: types.WorkspaceScanCommand} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) if err != nil { t.Fatal(err) @@ -55,7 +57,7 @@ func Test_executeWorkspaceFolderScanCommand_shouldStartFolderScanOnCommandReceip scanner := &snyk.TestScanner{} workspace.Get().AddFolder(workspace.NewFolder(c, "dummy", "dummy", scanner, di.HoverService(), di.ScanNotifier(), di.Notifier())) - params := lsp.ExecuteCommandParams{Command: snyk.WorkspaceFolderScanCommand, Arguments: []any{"dummy"}} + params := lsp.ExecuteCommandParams{Command: types.WorkspaceFolderScanCommand, Arguments: []any{"dummy"}} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) if err != nil { t.Fatal(err) @@ -85,7 +87,7 @@ func Test_executeWorkspaceFolderScanCommand_shouldNotClearOtherFoldersDiagnostic folder.ScanFolder(context.Background()) dontClear.ScanFolder(context.Background()) - params := lsp.ExecuteCommandParams{Command: snyk.WorkspaceFolderScanCommand, Arguments: []any{"dummy"}} + params := lsp.ExecuteCommandParams{Command: types.WorkspaceFolderScanCommand, Arguments: []any{"dummy"}} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) if err != nil { t.Fatal(err) @@ -107,7 +109,7 @@ func Test_executeWorkspaceScanCommand_shouldAskForTrust(t *testing.T) { // explicitly enable folder trust which is disabled by default in tests config.CurrentConfig().SetTrustedFolderFeatureEnabled(true) - params := lsp.ExecuteCommandParams{Command: snyk.WorkspaceScanCommand} + params := lsp.ExecuteCommandParams{Command: types.WorkspaceScanCommand} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) if err != nil { t.Fatal(err) @@ -136,9 +138,9 @@ func Test_loginCommand_StartsAuthentication(t *testing.T) { if err != nil { t.Fatal(err) } - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = false - params := lsp.ExecuteCommandParams{Command: snyk.LoginCommand} + params := lsp.ExecuteCommandParams{Command: types.LoginCommand} // Act _, err = loc.Client.Call(ctx, "workspace/executeCommand", params) @@ -159,7 +161,7 @@ func Test_TrustWorkspaceFolders(t *testing.T) { workspace.Get().AddFolder(workspace.NewFolder(c, "/path/to/folder1", "dummy", nil, di.HoverService(), di.ScanNotifier(), di.Notifier())) - params := lsp.ExecuteCommandParams{Command: snyk.TrustWorkspaceFoldersCommand} + params := lsp.ExecuteCommandParams{Command: types.TrustWorkspaceFoldersCommand} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) if err != nil { t.Fatal(err) @@ -176,7 +178,7 @@ func Test_TrustWorkspaceFolders(t *testing.T) { workspace.Get().AddFolder(workspace.NewFolder(c, "/path/to/folder2", "dummy", nil, di.HoverService(), di.ScanNotifier(), di.Notifier())) config.CurrentConfig().SetTrustedFolderFeatureEnabled(true) - params := lsp.ExecuteCommandParams{Command: snyk.TrustWorkspaceFoldersCommand} + params := lsp.ExecuteCommandParams{Command: types.TrustWorkspaceFoldersCommand} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) if err != nil { t.Fatal(err) @@ -194,7 +196,7 @@ func Test_TrustWorkspaceFolders(t *testing.T) { config.CurrentConfig().SetTrustedFolderFeatureEnabled(true) config.CurrentConfig().SetTrustedFolders([]string{"/path/to/folder2"}) - params := lsp.ExecuteCommandParams{Command: snyk.TrustWorkspaceFoldersCommand} + params := lsp.ExecuteCommandParams{Command: types.TrustWorkspaceFoldersCommand} _, err := loc.Client.Call(ctx, "workspace/executeCommand", params) if err != nil { t.Fatal(err) diff --git a/application/server/notification.go b/application/server/notification.go index dc3d529b6..be58fc8ca 100644 --- a/application/server/notification.go +++ b/application/server/notification.go @@ -25,9 +25,9 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/application/di" "github.com/snyk/snyk-ls/domain/ide/command" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/progress" + "github.com/snyk/snyk-ls/internal/types" ) func notifier(c *config.Config, srv lsp.Server, method string, params any) { @@ -121,7 +121,7 @@ func registerNotifier(c *config.Config, srv lsp.Server) { Interface("product", params.Product). Interface("status", params.Status). Msg("sending scan data to client") - case snyk.ShowMessageRequest: + case types.ShowMessageRequest: // Function blocks on callback, so we need to run it in a separate goroutine go handleShowMessageRequest(srv, params, &logger) logger.Info().Msg("sending show message request to client") @@ -205,7 +205,7 @@ func handleApplyWorkspaceEdit(srv lsp.Server, params lsp.ApplyWorkspaceEditParam Msgf("Workspace edit applied %t. %s", editResult.Applied, editResult.FailureReason) } -func handleShowMessageRequest(srv lsp.Server, params snyk.ShowMessageRequest, logger *zerolog.Logger) { +func handleShowMessageRequest(srv lsp.Server, params types.ShowMessageRequest, logger *zerolog.Logger) { // convert our internal message request to LSP message request requestParams := lsp.ShowMessageRequestParams{ Type: lsp.MessageType(params.Type), @@ -240,7 +240,7 @@ func handleShowMessageRequest(srv lsp.Server, params snyk.ShowMessageRequest, lo return } - selectedCommand, ok := params.Actions.Get(snyk.MessageAction(actionItem.Title)) + selectedCommand, ok := params.Actions.Get(types.MessageAction(actionItem.Title)) if !ok { logger.Info().Str("method", "registerNotifier").Msg("Action map key not found") return diff --git a/application/server/notification/scan_notifier.go b/application/server/notification/scan_notifier.go index 662929d5b..bd6994c80 100644 --- a/application/server/notification/scan_notifier.go +++ b/application/server/notification/scan_notifier.go @@ -23,9 +23,9 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/converter" - "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/uri" ) diff --git a/application/server/notification/scan_notifier_test.go b/application/server/notification/scan_notifier_test.go index fd9763ab8..8eb5a46c9 100644 --- a/application/server/notification/scan_notifier_test.go +++ b/application/server/notification/scan_notifier_test.go @@ -30,6 +30,7 @@ import ( "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) type sendMessageTestCase struct { @@ -167,7 +168,7 @@ func Test_SendSuccess_SendsForAllEnabledProducts(t *testing.T) { References: []snyk.Reference{}, IssueDescriptionURL: &url.URL{}, CodeActions: []snyk.CodeAction{}, - CodelensCommands: []snyk.CommandData{}, + CodelensCommands: []types.CommandData{}, AdditionalData: snyk.IaCIssueData{ Key: "098f6bcd4621d373cade4e832627b4f6", Title: "iacTitle", @@ -191,7 +192,7 @@ func Test_SendSuccess_SendsForAllEnabledProducts(t *testing.T) { References: []snyk.Reference{}, IssueDescriptionURL: &url.URL{}, CodeActions: []snyk.CodeAction{}, - CodelensCommands: []snyk.CommandData{}, + CodelensCommands: []types.CommandData{}, AdditionalData: snyk.CodeIssueData{ Key: "5a105e8b9d40e1329780d62ea2265d8a", Message: "codeMessage", @@ -305,7 +306,7 @@ func Test_SendSuccess_SendsForOpenSource(t *testing.T) { References: []snyk.Reference{}, IssueDescriptionURL: &url.URL{}, CodeActions: []snyk.CodeAction{}, - CodelensCommands: []snyk.CommandData{}, + CodelensCommands: []types.CommandData{}, Ecosystem: "OSS Ecosystem", CWEs: []string{"CWE-184"}, CVEs: []string{"CVE-2023-45133"}, @@ -412,7 +413,7 @@ func Test_SendSuccess_SendsForSnykCode(t *testing.T) { References: []snyk.Reference{}, IssueDescriptionURL: &url.URL{}, CodeActions: []snyk.CodeAction{}, - CodelensCommands: []snyk.CommandData{}, + CodelensCommands: []types.CommandData{}, AdditionalData: snyk.CodeIssueData{ Key: "5a105e8b9d40e1329780d62ea2265d8a", Message: "codeMessage", @@ -519,7 +520,7 @@ func Test_SendSuccess_SendsForSnykCode_WithIgnores(t *testing.T) { References: []snyk.Reference{}, IssueDescriptionURL: &url.URL{}, CodeActions: []snyk.CodeAction{}, - CodelensCommands: []snyk.CommandData{}, + CodelensCommands: []types.CommandData{}, AdditionalData: snyk.CodeIssueData{ Key: "5a105e8b9d40e1329780d62ea2265d8a", Message: "codeMessage", @@ -603,7 +604,7 @@ func Test_SendSuccess_SendsForAllSnykIac(t *testing.T) { References: []snyk.Reference{}, IssueDescriptionURL: &url.URL{}, CodeActions: []snyk.CodeAction{}, - CodelensCommands: []snyk.CommandData{}, + CodelensCommands: []types.CommandData{}, AdditionalData: snyk.IaCIssueData{ Key: "098f6bcd4621d373cade4e832627b4f6", Title: "iacTitle", diff --git a/application/server/notification_test.go b/application/server/notification_test.go index 9093cf026..fe1565b1b 100644 --- a/application/server/notification_test.go +++ b/application/server/notification_test.go @@ -27,12 +27,12 @@ import ( "github.com/snyk/snyk-ls/application/di" "github.com/snyk/snyk-ls/domain/ide/command" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/concurrency" "github.com/snyk/snyk-ls/internal/data_structure" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/progress" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) type ServerImplMock struct{} @@ -209,23 +209,23 @@ func TestShowMessageRequest(t *testing.T) { t.Fatal(err) } - actionCommandMap := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() + actionCommandMap := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() expectedTitle := "test title" // data, err := command.CreateFromCommandData(snyk.CommandData{ // CommandId: snyk.OpenBrowserCommand, // Arguments: []any{"https://snyk.io"}, // }, loc.Server, di.AuthenticationService(), di.LearnService(), di.Notifier(), nil, nil) - data := snyk.CommandData{ - CommandId: snyk.OpenBrowserCommand, + data := types.CommandData{ + CommandId: types.OpenBrowserCommand, Arguments: []any{"https://snyk.io"}, } assert.NoError(t, err) actionCommandMap.Add( - snyk.MessageAction(expectedTitle), + types.MessageAction(expectedTitle), data, ) - expected := snyk.ShowMessageRequest{Message: "message", Type: snyk.Info, Actions: actionCommandMap} + expected := types.ShowMessageRequest{Message: "message", Type: types.Info, Actions: actionCommandMap} di.Notifier().Send(expected) @@ -238,7 +238,7 @@ func TestShowMessageRequest(t *testing.T) { } var actual lsp.ShowMessageRequestParams _ = callbacks[0].UnmarshalParams(&actual) - _, ok := expected.Actions.Get(snyk.MessageAction(expectedTitle)) + _, ok := expected.Actions.Get(types.MessageAction(expectedTitle)) return ok && expected.Message == actual.Message && int(expected.Type) == int(actual.Type) @@ -259,12 +259,12 @@ func TestShowMessageRequest(t *testing.T) { if err != nil { t.Fatal(err) } - command.SetService(snyk.NewCommandServiceMock()) - actionCommandMap := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() + command.SetService(types.NewCommandServiceMock()) + actionCommandMap := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() - actionCommandMap.Add(snyk.MessageAction(selectedAction), snyk.CommandData{CommandId: snyk.OpenBrowserCommand, Arguments: []any{"https://snyk.io"}}) + actionCommandMap.Add(types.MessageAction(selectedAction), types.CommandData{CommandId: types.OpenBrowserCommand, Arguments: []any{"https://snyk.io"}}) - request := snyk.ShowMessageRequest{Message: "message", Type: snyk.Info, Actions: actionCommandMap} + request := types.ShowMessageRequest{Message: "message", Type: types.Info, Actions: actionCommandMap} di.Notifier().Send(request) @@ -273,8 +273,8 @@ func TestShowMessageRequest(t *testing.T) { func() bool { // verify that passed command is eventually executed commandService := command.Service() - commandServiceMock := commandService.(*snyk.CommandServiceMock) - return commandServiceMock.ExecutedCommands()[0].CommandId == snyk.OpenBrowserCommand + commandServiceMock := commandService.(*types.CommandServiceMock) + return commandServiceMock.ExecutedCommands()[0].CommandId == types.OpenBrowserCommand }, 2*time.Second, 10*time.Millisecond, diff --git a/application/server/server.go b/application/server/server.go index c55940343..cd420e2d1 100644 --- a/application/server/server.go +++ b/application/server/server.go @@ -38,7 +38,6 @@ import ( "github.com/snyk/snyk-ls/domain/ide/command" "github.com/snyk/snyk-ls/domain/ide/converter" "github.com/snyk/snyk-ls/domain/ide/hover" - noti "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/ide/workspace" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" @@ -46,7 +45,9 @@ import ( "github.com/snyk/snyk-ls/infrastructure/cli/install" "github.com/snyk/snyk-ls/internal/data_structure" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/progress" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" "github.com/snyk/snyk-ls/internal/util" ) @@ -159,7 +160,7 @@ func codeLensHandler() jrpc2.Handler { func filterCodeFixCodelens(lenses []sglsp.CodeLens) []sglsp.CodeLens { var filteredLenses []sglsp.CodeLens for _, lense := range lenses { - if lense.Command.Command == snyk.CodeFixCommand { + if lense.Command.Command == types.CodeFixCommand { continue } @@ -257,22 +258,22 @@ func initializeHandler(srv *jrpc2.Server) handler.Func { InlineValueProvider: true, ExecuteCommandProvider: &sglsp.ExecuteCommandOptions{ Commands: []string{ - snyk.NavigateToRangeCommand, - snyk.WorkspaceScanCommand, - snyk.WorkspaceFolderScanCommand, - snyk.OpenBrowserCommand, - snyk.LoginCommand, - snyk.CopyAuthLinkCommand, - snyk.LogoutCommand, - snyk.TrustWorkspaceFoldersCommand, - snyk.OpenLearnLesson, - snyk.GetLearnLesson, - snyk.GetSettingsSastEnabled, - snyk.GetFeatureFlagStatus, - snyk.GetActiveUserCommand, - snyk.CodeFixCommand, - snyk.CodeSubmitFixFeedback, - snyk.CodeFixDiffsCommand, + types.NavigateToRangeCommand, + types.WorkspaceScanCommand, + types.WorkspaceFolderScanCommand, + types.OpenBrowserCommand, + types.LoginCommand, + types.CopyAuthLinkCommand, + types.LogoutCommand, + types.TrustWorkspaceFoldersCommand, + types.OpenLearnLesson, + types.GetLearnLesson, + types.GetSettingsSastEnabled, + types.GetFeatureFlagStatus, + types.GetActiveUserCommand, + types.CodeFixCommand, + types.CodeSubmitFixFeedback, + types.CodeFixDiffsCommand, }, }, }, @@ -304,22 +305,22 @@ func handleProtocolVersion(c *config.Config, noti noti.Notifier, ourProtocolVers ourProtocolVersion, ) logger.Error().Msg(m) - actions := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() + actions := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() - openBrowserCommandData := snyk.CommandData{ + openBrowserCommandData := types.CommandData{ Title: "Download manually in browser", - CommandId: snyk.OpenBrowserCommand, + CommandId: types.OpenBrowserCommand, Arguments: []any{getDownloadURL(c)}, } - actions.Add(snyk.MessageAction(openBrowserCommandData.Title), openBrowserCommandData) + actions.Add(types.MessageAction(openBrowserCommandData.Title), openBrowserCommandData) doNothingKey := "Cancel" // if we don't provide a commandId, nothing is done - actions.Add(snyk.MessageAction(doNothingKey), snyk.CommandData{Title: doNothingKey}) + actions.Add(types.MessageAction(doNothingKey), types.CommandData{Title: doNothingKey}) - msg := snyk.ShowMessageRequest{ + msg := types.ShowMessageRequest{ Message: m, - Type: snyk.Error, + Type: types.Error, Actions: actions, } noti.Send(msg) @@ -358,35 +359,27 @@ func initializedHandler(srv *jrpc2.Server) handler.Func { handleProtocolVersion(c, di.Notifier(), config.LsProtocolVersion, c.ClientProtocolVersion()) - // CLI & Authentication initialization + // CLI & Authentication initialization - returns error if not authenticated err := di.Scanner().Init() if err != nil { logger.Error().Err(err).Msg("Scan initialization error, canceling scan") return nil, err } - authenticated, err := di.AuthenticationService().IsAuthenticated() - if err != nil { - logger.Error().Err(err).Msg("Not authenticated, or error checking authentication status") - } - autoScanEnabled := c.IsAutoScanEnabled() - if autoScanEnabled && authenticated { + if autoScanEnabled { logger.Info().Msg("triggering workspace scan after successful initialization") workspace.Get().ScanWorkspace(context.Background()) } else { msg := fmt.Sprintf( - "No automatic workspace scan on initialization: autoScanEnabled=%v, authenticated=%v", + "No automatic workspace scan on initialization: autoScanEnabled=%v", autoScanEnabled, - authenticated, ) logger.Info().Msg(msg) } - if c.AutomaticAuthentication() || c.NonEmptyToken() { - logger.Debug().Msg("trying to get trusted status for untrusted folders") - go command.HandleUntrustedFolders(context.Background(), srv) - } + logger.Debug().Msg("trying to get trusted status for untrusted folders") + go command.HandleUntrustedFolders(context.Background(), srv) return nil, nil }) } diff --git a/application/server/server_smoke_test.go b/application/server/server_smoke_test.go index 63548838b..65e523bf6 100644 --- a/application/server/server_smoke_test.go +++ b/application/server/server_smoke_test.go @@ -35,11 +35,11 @@ import ( "github.com/snyk/snyk-ls/application/di" "github.com/snyk/snyk-ls/domain/ide/hover" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/code" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" ) @@ -474,7 +474,7 @@ func runSmokeTest(t *testing.T, repo string, commit string, file1 string, file2 continue } call, err := loc.Client.Call(ctx, "workspace/executeCommand", sglsp.ExecuteCommandParams{ - Command: snyk.CodeFixDiffsCommand, + Command: types.CodeFixDiffsCommand, Arguments: []any{uri.PathToUri(scanParams.FolderPath), uri.PathToUri(issue.FilePath), issue.Id}, }) assert.NoError(t, err) @@ -509,6 +509,7 @@ func setupRepoAndInitialize(t *testing.T, repo string, commit string, loc server Token: os.Getenv("SNYK_TOKEN"), EnableTrustedFoldersFeature: "false", FilterSeverity: lsp.DefaultSeverityFilter(), + AuthenticationMethod: lsp.TokenAuthentication, }, } @@ -527,7 +528,7 @@ func checkFeatureFlagStatus(t *testing.T, loc *server.Local, c *config.Config) { t.Helper() call, err := loc.Client.Call(ctx, "workspace/executeCommand", sglsp.ExecuteCommandParams{ - Command: snyk.GetFeatureFlagStatus, + Command: types.GetFeatureFlagStatus, Arguments: []any{"bitbucketConnectApp"}, }) diff --git a/application/server/server_test.go b/application/server/server_test.go index 2e2c2ecd6..c56eb2374 100644 --- a/application/server/server_test.go +++ b/application/server/server_test.go @@ -22,7 +22,6 @@ import ( "os" "os/exec" "path/filepath" - "reflect" "strings" "testing" "time" @@ -44,16 +43,18 @@ import ( "github.com/snyk/snyk-ls/domain/ide/converter" "github.com/snyk/snyk-ls/domain/ide/hover" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/cli" "github.com/snyk/snyk-ls/infrastructure/cli/cli_constants" "github.com/snyk/snyk-ls/infrastructure/cli/install" "github.com/snyk/snyk-ls/infrastructure/code" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/progress" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" ) @@ -62,10 +63,10 @@ const maxIntegTestDuration = 45 * time.Minute var ( ctx = context.Background() supportedCommands = []string{ - snyk.WorkspaceScanCommand, - snyk.OpenBrowserCommand, - snyk.NavigateToRangeCommand, - snyk.LoginCommand, + types.WorkspaceScanCommand, + types.OpenBrowserCommand, + types.NavigateToRangeCommand, + types.LoginCommand, } ) @@ -233,53 +234,6 @@ func Test_initialized_shouldCheckRequiredProtocolVersion(t *testing.T) { "did not receive callback because of wrong protocol version") } -func Test_initialize_shouldDefaultToTokenAuthentication(t *testing.T) { - loc, _ := setupServer(t) - - _, err := loc.Client.Call(ctx, "initialize", nil) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, lsp.TokenAuthentication, config.CurrentConfig().AuthenticationMethod()) - assert.Equal(t, "*snyk.FakeAuthenticationProvider", reflect.TypeOf(di.AuthenticationService().Provider()).String()) -} - -func Test_initialize_shouldInitToOauthAuthenticationWhenConfigured(t *testing.T) { - loc, _ := setupServer(t) - - settings := lsp.Settings{AuthenticationMethod: lsp.OAuthAuthentication} - - _, err := loc.Client.Call(ctx, "initialize", lsp.InitializeParams{InitializationOptions: settings}) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, lsp.OAuthAuthentication, config.CurrentConfig().AuthenticationMethod()) - assert.Equal(t, "*oauth.oAuthProvider", reflect.TypeOf(di.AuthenticationService().Provider()).String()) -} - -func Test_initialize_shouldInitToTokenAuthenticationWhenConfigured(t *testing.T) { - loc, _ := setupServer(t) - - settings := lsp.Settings{AuthenticationMethod: lsp.OAuthAuthentication} - - _, err := loc.Client.Call(ctx, "initialize", lsp.InitializeParams{InitializationOptions: settings}) - if err != nil { - t.Fatal(err) - } - - assert.Equal(t, "*oauth.oAuthProvider", reflect.TypeOf(di.AuthenticationService().Provider()).String()) - - _, err = loc.Client.Call(ctx, - "workspace/didChangeConfiguration", - lsp.DidChangeConfigurationParams{Settings: lsp.Settings{AuthenticationMethod: lsp.TokenAuthentication}}) - if err != nil { - t.Fatal(err) - } - - assert.Equal(t, lsp.TokenAuthentication, config.CurrentConfig().AuthenticationMethod()) - assert.Equal(t, "*auth.CliAuthenticationProvider", reflect.TypeOf(di.AuthenticationService().Provider()).String()) -} - func Test_initialize_shouldSupportAllCommands(t *testing.T) { loc, _ := setupServer(t) @@ -292,22 +246,22 @@ func Test_initialize_shouldSupportAllCommands(t *testing.T) { t.Fatal(err) } - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.NavigateToRangeCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.WorkspaceScanCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.WorkspaceFolderScanCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.OpenBrowserCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.LoginCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.CopyAuthLinkCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.LogoutCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.TrustWorkspaceFoldersCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.GetLearnLesson) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.OpenLearnLesson) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.GetSettingsSastEnabled) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.GetFeatureFlagStatus) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.GetActiveUserCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.CodeFixCommand) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.CodeSubmitFixFeedback) - assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, snyk.CodeFixDiffsCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.NavigateToRangeCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.WorkspaceScanCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.WorkspaceFolderScanCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.OpenBrowserCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.LoginCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.CopyAuthLinkCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.LogoutCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.TrustWorkspaceFoldersCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.GetLearnLesson) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.OpenLearnLesson) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.GetSettingsSastEnabled) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.GetFeatureFlagStatus) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.GetActiveUserCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.CodeFixCommand) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.CodeSubmitFixFeedback) + assert.Contains(t, result.Capabilities.ExecuteCommandProvider.Commands, types.CodeFixDiffsCommand) } func Test_initialize_shouldSupportDocumentSaving(t *testing.T) { @@ -388,7 +342,7 @@ func Test_TextDocumentCodeLenses_shouldReturnCodeLenses(t *testing.T) { testutil.IntegTest(t) // this needs an authenticated user loc, _ := setupServer(t) didOpenParams, dir := didOpenTextParams(t) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true clientParams := lsp.InitializeParams{ @@ -445,7 +399,7 @@ func Test_TextDocumentCodeLenses_dirtyFileShouldFilterCodeFixLenses(t *testing.T testutil.IntegTest(t) // this needs an authenticated user loc, _ := setupServer(t) didOpenParams, dir := didOpenTextParams(t) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true clientParams := lsp.InitializeParams{ @@ -736,7 +690,7 @@ func Test_initialize_handlesUntrustedFoldersWhenAuthenticated(t *testing.T) { Token: "token", } - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true params := lsp.InitializeParams{ @@ -780,7 +734,7 @@ func Test_initialize_doesnotHandleUntrustedFolders(t *testing.T) { func Test_textDocumentDidSaveHandler_shouldAcceptDocumentItemAndPublishDiagnostics(t *testing.T) { loc, jsonRPCRecorder := setupServer(t) config.CurrentConfig().SetSnykCodeEnabled(true) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true _, err := loc.Client.Call(ctx, "initialize", nil) @@ -827,9 +781,13 @@ patch: {} func Test_textDocumentDidSaveHandler_shouldTriggerScanForDotSnykFile(t *testing.T) { loc, jsonRPCRecorder := setupServer(t) - config.CurrentConfig().SetSnykCodeEnabled(false) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) - fakeAuthenticationProvider.IsAuthenticated = true + c := config.CurrentConfig() + c.SetSnykCodeEnabled(false) + c.SetAuthenticationMethod(lsp.FakeAuthentication) + di.AuthenticationService().ConfigureProviders(c) + + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0] + fakeAuthenticationProvider.(*authentication.FakeAuthenticationProvider).IsAuthenticated = true _, err := loc.Client.Call(ctx, "initialize", nil) if err != nil { @@ -879,7 +837,7 @@ func Test_textDocumentDidOpenHandler_shouldNotPublishIfNotCached(t *testing.T) { func Test_textDocumentDidOpenHandler_shouldPublishIfCached(t *testing.T) { loc, jsonRPCRecorder := setupServer(t) config.CurrentConfig().SetSnykCodeEnabled(true) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true _, err := loc.Client.Call(ctx, "initialize", nil) if err != nil { @@ -1021,8 +979,8 @@ func Test_CodeActionResolve_ShouldExecuteCommands(t *testing.T) { } config.CurrentConfig().SetAutomaticScanning(false) - expected := snyk.OpenBrowserCommand - serviceMock := snyk.NewCommandServiceMock() + expected := types.OpenBrowserCommand + serviceMock := types.NewCommandServiceMock() command.SetService(serviceMock) _, err = loc.Client.Call(ctx, "codeAction/resolve", lsp.CodeAction{ @@ -1076,7 +1034,7 @@ func Test_IntegrationHoverResults(t *testing.T) { loc, _ := setupServer(t) c := testutil.IntegTest(t) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true var cloneTargetDir, err = setupCustomTestRepo(t, "https://github.com/snyk-labs/nodejs-goof", "0336589", c.Logger()) @@ -1227,7 +1185,7 @@ func Test_handleProtocolVersion(t *testing.T) { notificationReceived := make(chan bool) f := func(params any) { - mrq, ok := params.(snyk.ShowMessageRequest) + mrq, ok := params.(types.ShowMessageRequest) require.True(t, ok) require.Contains(t, mrq.Message, "does not match") notificationReceived <- true diff --git a/application/server/trust_test.go b/application/server/trust_test.go index 513985439..7bc335db3 100644 --- a/application/server/trust_test.go +++ b/application/server/trust_test.go @@ -29,6 +29,7 @@ import ( "github.com/snyk/snyk-ls/domain/ide/command" "github.com/snyk/snyk-ls/domain/ide/workspace" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/uri" @@ -105,7 +106,7 @@ func Test_handleUntrustedFolders_shouldTriggerTrustRequestAndNotScanAfterNegativ func Test_initializeHandler_shouldCallHandleUntrustedFolders(t *testing.T) { loc, jsonRPCRecorder := setupServer(t) config.CurrentConfig().SetTrustedFolderFeatureEnabled(true) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true _, err := loc.Client.Call(context.Background(), "initialize", lsp.InitializeParams{ diff --git a/domain/ide/codelens/codelens.go b/domain/ide/codelens/codelens.go index 28eff287c..8efadaba6 100644 --- a/domain/ide/codelens/codelens.go +++ b/domain/ide/codelens/codelens.go @@ -22,6 +22,7 @@ import ( "github.com/snyk/snyk-ls/domain/ide/converter" "github.com/snyk/snyk-ls/domain/ide/workspace" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/types" ) func GetFor(filePath string) (lenses []sglsp.CodeLens) { @@ -39,7 +40,7 @@ func GetFor(filePath string) (lenses []sglsp.CodeLens) { return lenses } -func getCodeLensFromCommand(issue snyk.Issue, command snyk.CommandData) sglsp.CodeLens { +func getCodeLensFromCommand(issue snyk.Issue, command types.CommandData) sglsp.CodeLens { return sglsp.CodeLens{ Range: converter.ToRange(issue.Range), Command: sglsp.Command{ diff --git a/domain/ide/codelens/codelens_test.go b/domain/ide/codelens/codelens_test.go index 6f8f49f0c..74dddb17a 100644 --- a/domain/ide/codelens/codelens_test.go +++ b/domain/ide/codelens/codelens_test.go @@ -25,9 +25,9 @@ import ( "github.com/snyk/snyk-ls/application/di" "github.com/snyk/snyk-ls/domain/ide/converter" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/code" + "github.com/snyk/snyk-ls/internal/observability/performance" "github.com/snyk/snyk-ls/internal/progress" "github.com/snyk/snyk-ls/internal/testutil" ) @@ -51,7 +51,7 @@ func Test_GetCodeLensForPath(t *testing.T) { // this is using the real progress channel, so we need to listen to it dummyProgressListeners(t) - fakeAuthenticationProvider := di.AuthenticationService().Provider().(*snyk.FakeAuthenticationProvider) + fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider) fakeAuthenticationProvider.IsAuthenticated = true filePath, dir := code.TempWorkdirWithVulnerabilities(t) diff --git a/domain/ide/command/code_fix.go b/domain/ide/command/code_fix.go index 21c48ccf9..7aeaf6ed7 100644 --- a/domain/ide/command/code_fix.go +++ b/domain/ide/command/code_fix.go @@ -26,19 +26,20 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/converter" - "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" ) type fixCodeIssue struct { - command snyk.CommandData + command types.CommandData issueProvider snyk.IssueProvider notifier notification.Notifier logger *zerolog.Logger } -func (cmd *fixCodeIssue) Command() snyk.CommandData { +func (cmd *fixCodeIssue) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/code_fix_diffs.go b/domain/ide/command/code_fix_diffs.go index 63a55431f..bb5c6856d 100644 --- a/domain/ide/command/code_fix_diffs.go +++ b/domain/ide/command/code_fix_diffs.go @@ -25,20 +25,21 @@ import ( "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/code" + "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" uri2 "github.com/snyk/snyk-ls/internal/uri" ) type codeFixDiffs struct { - command snyk.CommandData + command types.CommandData notifier notification.Notifier issueProvider snyk.IssueProvider codeScanner *code.Scanner } -func (cmd *codeFixDiffs) Command() snyk.CommandData { +func (cmd *codeFixDiffs) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/code_fix_diffs_test.go b/domain/ide/command/code_fix_diffs_test.go index fe6af1642..bbebd0df1 100644 --- a/domain/ide/command/code_fix_diffs_test.go +++ b/domain/ide/command/code_fix_diffs_test.go @@ -29,6 +29,7 @@ import ( "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) func Test_codeFixDiffs_Command(t *testing.T) { @@ -81,7 +82,7 @@ func Test_codeFixDiffs_Execute(t *testing.T) { t.Run("happy path", func(t *testing.T) { cut.issueProvider = mockIssueProvider{} codeScanner.BundleHashes = map[string]string{"/folderPath": "bundleHash"} - cut.command = snyk.CommandData{ + cut.command = types.CommandData{ Arguments: []any{"file:///folderPath", "file:///folderPath/issuePath", "issueId"}, } @@ -94,7 +95,7 @@ func Test_codeFixDiffs_Execute(t *testing.T) { t.Run("unhappy - file not beneath folder", func(t *testing.T) { cut.issueProvider = mockIssueProvider{} codeScanner.BundleHashes = map[string]string{"/folderPath": "bundleHash"} - cut.command = snyk.CommandData{ + cut.command = types.CommandData{ Arguments: []any{"file:///folderPath", "file:///anotherFolder/issuePath", "issueId"}, } @@ -107,7 +108,7 @@ func Test_codeFixDiffs_Execute(t *testing.T) { t.Run("unhappy - folder empty", func(t *testing.T) { cut.issueProvider = mockIssueProvider{} codeScanner.BundleHashes = map[string]string{"/folderPath": "bundleHash"} - cut.command = snyk.CommandData{ + cut.command = types.CommandData{ Arguments: []any{"", "file:///anotherFolder/issuePath", "issueId"}, } @@ -120,7 +121,7 @@ func Test_codeFixDiffs_Execute(t *testing.T) { t.Run("unhappy - file empty", func(t *testing.T) { cut.issueProvider = mockIssueProvider{} codeScanner.BundleHashes = map[string]string{"/folderPath": "bundleHash"} - cut.command = snyk.CommandData{ + cut.command = types.CommandData{ Arguments: []any{"file://folder", "", "issueId"}, } diff --git a/domain/ide/command/code_fix_feedback.go b/domain/ide/command/code_fix_feedback.go index 9ad112c2e..0f6456f34 100644 --- a/domain/ide/command/code_fix_feedback.go +++ b/domain/ide/command/code_fix_feedback.go @@ -19,7 +19,7 @@ package command import ( "context" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/types" ) type SnykCodeHttpClient interface { @@ -27,11 +27,11 @@ type SnykCodeHttpClient interface { } type codeFixFeedback struct { - command snyk.CommandData + command types.CommandData apiClient SnykCodeHttpClient } -func (cmd *codeFixFeedback) Command() snyk.CommandData { +func (cmd *codeFixFeedback) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/code_fix_feedback_test.go b/domain/ide/command/code_fix_feedback_test.go index b132149f3..7e6b02c39 100644 --- a/domain/ide/command/code_fix_feedback_test.go +++ b/domain/ide/command/code_fix_feedback_test.go @@ -23,7 +23,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/types" ) type fakeCodeHttpClient struct { @@ -43,7 +43,7 @@ func (c *fakeCodeHttpClient) SubmitAutofixFeedback(ctx context.Context, fixId st func Test_codeFixFeedback_SubmittedSuccessfully(t *testing.T) { apiClient := fakeCodeHttpClient{} codeFixFeedbackCmd := codeFixFeedback{ - command: snyk.CommandData{ + command: types.CommandData{ Arguments: []any{"fixId", true}, }, apiClient: &apiClient, @@ -59,7 +59,7 @@ func Test_codeFixFeedback_SubmissionFailed(t *testing.T) { shouldError: true, } codeFixFeedbackCmd := codeFixFeedback{ - command: snyk.CommandData{ + command: types.CommandData{ Arguments: []any{"fixId", true}, }, apiClient: &apiClient, diff --git a/domain/ide/command/code_fix_test.go b/domain/ide/command/code_fix_test.go index f3be08271..4c392829a 100644 --- a/domain/ide/command/code_fix_test.go +++ b/domain/ide/command/code_fix_test.go @@ -31,6 +31,7 @@ import ( "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) var sampleRangeArg = map[string]interface{}{ @@ -74,8 +75,8 @@ func setupClientCapability(config *config.Config) { } func setupCommand(mockNotifier *notification.MockNotifier) *fixCodeIssue { - cmdData := snyk.CommandData{ - CommandId: snyk.CodeFixCommand, + cmdData := types.CommandData{ + CommandId: types.CodeFixCommand, Arguments: sampleArgs, } cmd := &fixCodeIssue{ @@ -104,7 +105,7 @@ func setupMockEdit() (edit *snyk.WorkspaceEdit, deferredEdit func() *snyk.Worksp return mockEdit, deferredMockEdit } -func setupSampleIssues(issueRange snyk.Range, codeAction snyk.CodeAction, cmdData snyk.CommandData) []snyk.Issue { +func setupSampleIssues(issueRange snyk.Range, codeAction snyk.CodeAction, cmdData types.CommandData) []snyk.Issue { return []snyk.Issue{{ ID: "SNYK-123", Range: issueRange, @@ -113,7 +114,7 @@ func setupSampleIssues(issueRange snyk.Range, codeAction snyk.CodeAction, cmdDat IssueType: snyk.CodeSecurityVulnerability, Message: "This is a dummy error (severity error)", CodeActions: []snyk.CodeAction{codeAction}, - CodelensCommands: []snyk.CommandData{ + CodelensCommands: []types.CommandData{ cmdData, }, }} @@ -123,8 +124,8 @@ func Test_fixCodeIssue_ErrorsWhenNoCapability(t *testing.T) { c := testutil.UnitTest(t) cmd := &fixCodeIssue{ logger: c.Logger(), - command: snyk.CommandData{ - CommandId: snyk.CodeFixCommand, + command: types.CommandData{ + CommandId: types.CodeFixCommand, Arguments: []any{sampleArgs}, }, } diff --git a/domain/ide/command/command_factory.go b/domain/ide/command/command_factory.go index 9b23dd12e..3404c16ed 100644 --- a/domain/ide/command/command_factory.go +++ b/domain/ide/command/command_factory.go @@ -20,55 +20,57 @@ import ( "fmt" "github.com/snyk/snyk-ls/application/config" - noti "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/code" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" ) // CreateFromCommandData gets a command based on the given parameters that can be passed to the CommandService // nolint: gocyclo, nolintlint // this is a factory, it's ok to have high cyclomatic complexity here -func CreateFromCommandData(c *config.Config, commandData snyk.CommandData, srv lsp.Server, authService snyk.AuthenticationService, learnService learn.Service, notifier noti.Notifier, issueProvider snyk.IssueProvider, codeApiClient SnykCodeHttpClient, codeScanner *code.Scanner) (snyk.Command, error) { +func CreateFromCommandData(c *config.Config, commandData types.CommandData, srv lsp.Server, authService authentication.AuthenticationService, learnService learn.Service, notifier noti.Notifier, issueProvider snyk.IssueProvider, codeApiClient SnykCodeHttpClient, codeScanner *code.Scanner) (types.Command, error) { httpClient := c.Engine().GetNetworkAccess().GetHttpClient switch commandData.CommandId { - case snyk.NavigateToRangeCommand: + case types.NavigateToRangeCommand: return &navigateToRangeCommand{command: commandData, srv: srv, logger: c.Logger()}, nil - case snyk.WorkspaceScanCommand: + case types.WorkspaceScanCommand: return &workspaceScanCommand{command: commandData, srv: srv}, nil - case snyk.WorkspaceFolderScanCommand: + case types.WorkspaceFolderScanCommand: return &workspaceFolderScanCommand{command: commandData, srv: srv, logger: c.Logger()}, nil - case snyk.OpenBrowserCommand: + case types.OpenBrowserCommand: return &openBrowserCommand{command: commandData, logger: c.Logger()}, nil - case snyk.LoginCommand: + case types.LoginCommand: return &loginCommand{command: commandData, authService: authService, notifier: notifier, logger: c.Logger()}, nil - case snyk.CopyAuthLinkCommand: + case types.CopyAuthLinkCommand: return ©AuthLinkCommand{command: commandData, authService: authService, notifier: notifier, logger: c.Logger()}, nil - case snyk.LogoutCommand: + case types.LogoutCommand: return &logoutCommand{command: commandData, authService: authService, logger: c.Logger()}, nil - case snyk.TrustWorkspaceFoldersCommand: + case types.TrustWorkspaceFoldersCommand: return &trustWorkspaceFoldersCommand{command: commandData, notifier: notifier, logger: c.Logger()}, nil - case snyk.GetLearnLesson: + case types.GetLearnLesson: return &getLearnLesson{command: commandData, srv: srv, learnService: learnService}, nil - case snyk.OpenLearnLesson: + case types.OpenLearnLesson: return &openLearnLesson{command: commandData, srv: srv, learnService: learnService}, nil - case snyk.GetSettingsSastEnabled: + case types.GetSettingsSastEnabled: apiClient := snyk_api.NewSnykApiClient(c, httpClient) return &sastEnabled{command: commandData, apiClient: apiClient, logger: c.Logger()}, nil - case snyk.GetFeatureFlagStatus: + case types.GetFeatureFlagStatus: apiClient := snyk_api.NewSnykApiClient(c, httpClient) return &featureFlagStatus{command: commandData, apiClient: apiClient}, nil - case snyk.GetActiveUserCommand: + case types.GetActiveUserCommand: return &getActiveUser{command: commandData, authService: authService, notifier: notifier}, nil - case snyk.ReportAnalyticsCommand: + case types.ReportAnalyticsCommand: return &reportAnalyticsCommand{command: commandData}, nil - case snyk.CodeFixCommand: + case types.CodeFixCommand: return &fixCodeIssue{command: commandData, issueProvider: issueProvider, notifier: notifier, logger: c.Logger()}, nil - case snyk.CodeSubmitFixFeedback: + case types.CodeSubmitFixFeedback: return &codeFixFeedback{command: commandData, apiClient: codeApiClient}, nil - case snyk.CodeFixDiffsCommand: + case types.CodeFixDiffsCommand: return &codeFixDiffs{ command: commandData, codeScanner: codeScanner, diff --git a/domain/ide/command/command_service.go b/domain/ide/command/command_service.go index 33764e880..1e06c7c15 100644 --- a/domain/ide/command/command_service.go +++ b/domain/ide/command/command_service.go @@ -23,17 +23,19 @@ import ( sglsp "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" - noti "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/code" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" ) -var instance snyk.CommandService +var instance types.CommandService type serviceImpl struct { - authService snyk.AuthenticationService + authService authentication.AuthenticationService notifier noti.Notifier learnService learn.Service issueProvider snyk.IssueProvider @@ -42,13 +44,13 @@ type serviceImpl struct { } func NewService( - authService snyk.AuthenticationService, + authService authentication.AuthenticationService, notifier noti.Notifier, learnService learn.Service, issueProvider snyk.IssueProvider, codeApiClient SnykCodeHttpClient, codeScanner *code.Scanner, -) snyk.CommandService { +) types.CommandService { return &serviceImpl{ authService: authService, notifier: notifier, @@ -60,17 +62,17 @@ func NewService( } // SetService sets the singleton instance of the command service. -func SetService(service snyk.CommandService) { +func SetService(service types.CommandService) { instance = service } // Service returns the singleton instance of the command service. If not already created, // it will create a new instance. -func Service() snyk.CommandService { +func Service() types.CommandService { return instance } -func (service *serviceImpl) ExecuteCommandData(ctx context.Context, commandData snyk.CommandData, server lsp.Server) (any, error) { +func (service *serviceImpl) ExecuteCommandData(ctx context.Context, commandData types.CommandData, server lsp.Server) (any, error) { c := config.CurrentConfig() logger := c.Logger().With().Str("method", "command.serviceImpl.ExecuteCommandData").Logger() diff --git a/domain/ide/command/command_service_test.go b/domain/ide/command/command_service_test.go index 9f26c92b8..3e5cc4453 100644 --- a/domain/ide/command/command_service_test.go +++ b/domain/ide/command/command_service_test.go @@ -22,19 +22,20 @@ import ( "github.com/stretchr/testify/assert" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) func Test_ExecuteCommand(t *testing.T) { c := testutil.UnitTest(t) - authProvider := &snyk.FakeAuthenticationProvider{ + authProvider := &authentication.FakeAuthenticationProvider{ ExpectedAuthURL: "https://auth.url", } - authenticationService := snyk.NewAuthenticationService(c, authProvider, nil, nil, nil) + authenticationService := authentication.NewAuthenticationService(c, []authentication.AuthenticationProvider{authProvider}, nil, nil, nil) service := NewService(authenticationService, nil, nil, nil, nil, nil) - cmd := snyk.CommandData{ - CommandId: snyk.CopyAuthLinkCommand, + cmd := types.CommandData{ + CommandId: types.CopyAuthLinkCommand, } url, _ := service.ExecuteCommandData(context.Background(), cmd, nil) diff --git a/domain/ide/command/copy_auth_link.go b/domain/ide/command/copy_auth_link.go index 32c5a9baa..b3c92dab0 100644 --- a/domain/ide/command/copy_auth_link.go +++ b/domain/ide/command/copy_auth_link.go @@ -22,23 +22,30 @@ import ( "github.com/atotto/clipboard" "github.com/rs/zerolog" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" ) type copyAuthLinkCommand struct { - command snyk.CommandData - authService snyk.AuthenticationService + command types.CommandData + authService authentication.AuthenticationService notifier noti.Notifier logger *zerolog.Logger } -func (cmd *copyAuthLinkCommand) Command() snyk.CommandData { +func (cmd *copyAuthLinkCommand) Command() types.CommandData { return cmd.command } func (cmd *copyAuthLinkCommand) Execute(ctx context.Context) (any, error) { - url := cmd.authService.Provider().AuthURL(ctx) + var url string + for _, provider := range cmd.authService.Providers() { + url = provider.AuthURL(ctx) + if url != "" { + break + } + } cmd.logger.Debug().Str("method", "copyAuthLinkCommand.Execute"). Str("url", url). Msgf("copying auth link to clipboard") diff --git a/domain/ide/command/get_active_user.go b/domain/ide/command/get_active_user.go index 821368c2e..f94ad1777 100644 --- a/domain/ide/command/get_active_user.go +++ b/domain/ide/command/get_active_user.go @@ -19,24 +19,25 @@ package command import ( "context" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" ) -// oauthRefreshCommand is a command that refreshes the oauth token +// oauthRefreshCommand is a command that refreshes the authentication token // This is needed because the token is only valid for a certain period of time // For doing this we call the whoami workflow that will refresh the token automatically type getActiveUser struct { - command snyk.CommandData - authService snyk.AuthenticationService + command types.CommandData + authService authentication.AuthenticationService notifier noti.Notifier } -func (cmd *getActiveUser) Command() snyk.CommandData { +func (cmd *getActiveUser) Command() types.CommandData { return cmd.command } func (cmd *getActiveUser) Execute(ctx context.Context) (any, error) { - user, err := snyk.GetActiveUser() + user, err := authentication.GetActiveUser() return user, err } diff --git a/domain/ide/command/get_active_user_test.go b/domain/ide/command/get_active_user_test.go index 886b077b5..3fda3bc1a 100644 --- a/domain/ide/command/get_active_user_test.go +++ b/domain/ide/command/get_active_user_test.go @@ -23,28 +23,28 @@ import ( "testing" "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/workflow" - "github.com/stretchr/testify/assert" + "github.com/snyk/snyk-ls/infrastructure/authentication" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/snyk" - "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/testutil" ) func Test_getActiveUser_Execute_User_found(t *testing.T) { testutil.UnitTest(t) cmd := &getActiveUser{ - command: snyk.CommandData{ - CommandId: snyk.GetActiveUserCommand, + command: types.CommandData{ + CommandId: types.GetActiveUserCommand, }, } expectedUser, expectedUserData := whoamiWorkflowResponse(t) c := config.CurrentConfig() - c.SetAuthenticationMethod(lsp.OAuthAuthentication) mockEngine, engineConfig := setUpEngineMock(t, c) mockEngine.EXPECT().GetConfiguration().Return(engineConfig).AnyTimes() mockEngine.EXPECT().InvokeWithConfig(localworkflows.WORKFLOWID_WHOAMI, gomock.Any()).Return(expectedUserData, nil) @@ -58,13 +58,12 @@ func Test_getActiveUser_Execute_User_found(t *testing.T) { func Test_getActiveUser_Execute_Result_Empty(t *testing.T) { testutil.UnitTest(t) cmd := &getActiveUser{ - command: snyk.CommandData{ - CommandId: snyk.GetActiveUserCommand, + command: types.CommandData{ + CommandId: types.GetActiveUserCommand, }, } c := config.CurrentConfig() - c.SetAuthenticationMethod(lsp.OAuthAuthentication) mockEngine, engineConfig := setUpEngineMock(t, c) mockEngine.EXPECT().GetConfiguration().Return(engineConfig).AnyTimes() mockEngine.EXPECT().InvokeWithConfig(localworkflows.WORKFLOWID_WHOAMI, gomock.Any()).Return([]workflow.Data{}, nil) @@ -78,13 +77,12 @@ func Test_getActiveUser_Execute_Result_Empty(t *testing.T) { func Test_getActiveUser_Execute_Error_Result(t *testing.T) { testutil.UnitTest(t) cmd := &getActiveUser{ - command: snyk.CommandData{ - CommandId: snyk.GetActiveUserCommand, + command: types.CommandData{ + CommandId: types.GetActiveUserCommand, }, } c := config.CurrentConfig() - c.SetAuthenticationMethod(lsp.OAuthAuthentication) mockEngine, engineConfig := setUpEngineMock(t, c) mockEngine.EXPECT().GetConfiguration().Return(engineConfig).AnyTimes() testError := errors.New("test error") @@ -96,9 +94,9 @@ func Test_getActiveUser_Execute_Error_Result(t *testing.T) { assert.Empty(t, actualUser) } -func whoamiWorkflowResponse(t *testing.T) (*snyk.ActiveUser, []workflow.Data) { +func whoamiWorkflowResponse(t *testing.T) (*authentication.ActiveUser, []workflow.Data) { t.Helper() - expectedUser := snyk.ActiveUser{ + expectedUser := authentication.ActiveUser{ Id: "id", UserName: "username", } diff --git a/domain/ide/command/get_feature_flag_status.go b/domain/ide/command/get_feature_flag_status.go index d8424d0e2..af5bb9a33 100644 --- a/domain/ide/command/get_feature_flag_status.go +++ b/domain/ide/command/get_feature_flag_status.go @@ -22,16 +22,16 @@ import ( "fmt" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/snyk_api" + "github.com/snyk/snyk-ls/internal/types" ) type featureFlagStatus struct { - command snyk.CommandData + command types.CommandData apiClient snyk_api.SnykApiClient } -func (cmd *featureFlagStatus) Command() snyk.CommandData { +func (cmd *featureFlagStatus) Command() types.CommandData { return cmd.command } @@ -39,7 +39,7 @@ func (cmd *featureFlagStatus) Execute(ctx context.Context) (any, error) { logger := config.CurrentConfig().Logger().With().Str("method", "featureFlagStatus.Execute").Logger() if config.CurrentConfig().Token() == "" { - return nil, errors.New("not authenticated, cannot retrieve feature flag status") + return snyk_api.FFResponse{Ok: false, UserMessage: "not authenticated, cannot retrieve feature flags"}, nil } args := cmd.command.Arguments @@ -59,7 +59,7 @@ func (cmd *featureFlagStatus) Execute(ctx context.Context) (any, error) { logger.Debug().Msg(message) if err != nil { - logger.Err(err).Msg("Failed to get feature flag: " + ffStr) + logger.Warn().Err(err).Msg("Failed to get feature flag: " + ffStr) return snyk_api.FFResponse{Ok: false, UserMessage: err.Error()}, nil } diff --git a/domain/ide/command/get_feature_flag_status_test.go b/domain/ide/command/get_feature_flag_status_test.go index 810f2adb6..6c8c65e07 100644 --- a/domain/ide/command/get_feature_flag_status_test.go +++ b/domain/ide/command/get_feature_flag_status_test.go @@ -22,9 +22,9 @@ import ( "github.com/stretchr/testify/assert" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) func Test_ApiClient_FeatureFlagIsEnabled(t *testing.T) { @@ -39,7 +39,7 @@ func Test_ApiClient_FeatureFlagIsEnabled(t *testing.T) { // Pass the featureFlagType to the command featureFlagStatusCmd := featureFlagStatus{ apiClient: fakeApiClient, - command: snyk.CommandData{Arguments: []interface{}{"snykCodeConsistentIgnores"}}, + command: types.CommandData{Arguments: []interface{}{"snykCodeConsistentIgnores"}}, } // Execute the command diff --git a/domain/ide/command/get_learn_lesson.go b/domain/ide/command/get_learn_lesson.go index 0276befaa..c336d0fb4 100644 --- a/domain/ide/command/get_learn_lesson.go +++ b/domain/ide/command/get_learn_lesson.go @@ -25,15 +25,16 @@ import ( "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/types" ) type getLearnLesson struct { - command snyk.CommandData + command types.CommandData srv lsp.Server learnService learn.Service } -func (cmd *getLearnLesson) Command() snyk.CommandData { +func (cmd *getLearnLesson) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/get_learn_lesson_test.go b/domain/ide/command/get_learn_lesson_test.go index 3b69aedcd..4cbb99b2f 100644 --- a/domain/ide/command/get_learn_lesson_test.go +++ b/domain/ide/command/get_learn_lesson_test.go @@ -26,6 +26,7 @@ import ( "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/infrastructure/learn/mock_learn" + "github.com/snyk/snyk-ls/internal/types" ) //goland:noinspection GoRedundantConversion @@ -37,9 +38,9 @@ func Test_getLearnLesson_Execute(t *testing.T) { rule := "javascript%2Fsqlinjection" cwes := "CWE-89,CWE-ZZ" cves := "CVE-2020-1234" - data := snyk.CommandData{ - Title: snyk.GetLearnLesson, - CommandId: snyk.GetLearnLesson, + data := types.CommandData{ + Title: types.GetLearnLesson, + CommandId: types.GetLearnLesson, Arguments: []any{rule, eco, cwes, cves, float64(snyk.DependencyVulnerability)}, } mockService := mock_learn.NewMockService(ctrl) diff --git a/domain/ide/command/login.go b/domain/ide/command/login.go index 8d734e0c6..20ac92e9f 100644 --- a/domain/ide/command/login.go +++ b/domain/ide/command/login.go @@ -21,19 +21,20 @@ import ( "github.com/rs/zerolog" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/util" ) type loginCommand struct { - command snyk.CommandData - authService snyk.AuthenticationService + command types.CommandData + authService authentication.AuthenticationService notifier noti.Notifier logger *zerolog.Logger } -func (cmd *loginCommand) Command() snyk.CommandData { +func (cmd *loginCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/logout.go b/domain/ide/command/logout.go index 85d8224dd..97dee5338 100644 --- a/domain/ide/command/logout.go +++ b/domain/ide/command/logout.go @@ -22,16 +22,17 @@ import ( "github.com/rs/zerolog" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" + "github.com/snyk/snyk-ls/internal/types" ) type logoutCommand struct { - command snyk.CommandData - authService snyk.AuthenticationService + command types.CommandData + authService authentication.AuthenticationService logger *zerolog.Logger } -func (cmd *logoutCommand) Command() snyk.CommandData { +func (cmd *logoutCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/logout_test.go b/domain/ide/command/logout_test.go index e8536f160..21579505b 100644 --- a/domain/ide/command/logout_test.go +++ b/domain/ide/command/logout_test.go @@ -25,30 +25,32 @@ import ( "github.com/snyk/snyk-ls/domain/ide/hover" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) func TestLogoutCommand_Execute_ClearsIssues(t *testing.T) { c := testutil.UnitTest(t) notifier := notification.NewNotifier() - provider := snyk.NewFakeCliAuthenticationProvider(c) + provider := authentication.NewFakeCliAuthenticationProvider(c) hoverService := hover.NewFakeHoverService() provider.IsAuthenticated = true scanNotifier := snyk.NewMockScanNotifier() - authenticationService := snyk.NewAuthenticationService( + authenticationService := authentication.NewAuthenticationService( c, - provider, + []authentication.AuthenticationProvider{provider}, ux.NewTestAnalytics(c), error_reporting.NewTestErrorReporter(), notifier, ) cmd := logoutCommand{ - command: snyk.CommandData{CommandId: snyk.LogoutCommand}, + command: types.CommandData{CommandId: types.LogoutCommand}, authService: authenticationService, logger: c.Logger(), } diff --git a/domain/ide/command/navigate_to_range.go b/domain/ide/command/navigate_to_range.go index 464c8794b..0f7472718 100644 --- a/domain/ide/command/navigate_to_range.go +++ b/domain/ide/command/navigate_to_range.go @@ -26,16 +26,17 @@ import ( "github.com/snyk/snyk-ls/domain/ide/converter" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" ) type navigateToRangeCommand struct { - command snyk.CommandData + command types.CommandData srv lsp.Server logger *zerolog.Logger } -func (cmd *navigateToRangeCommand) Command() snyk.CommandData { +func (cmd *navigateToRangeCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/open_browser.go b/domain/ide/command/open_browser.go index 49be784b7..e03577356 100644 --- a/domain/ide/command/open_browser.go +++ b/domain/ide/command/open_browser.go @@ -20,17 +20,17 @@ import ( "context" "github.com/rs/zerolog" - "github.com/snyk/go-application-framework/pkg/auth" - "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/go-application-framework/pkg/auth" + "github.com/snyk/snyk-ls/internal/types" ) type openBrowserCommand struct { - command snyk.CommandData + command types.CommandData logger *zerolog.Logger } -func (cmd *openBrowserCommand) Command() snyk.CommandData { +func (cmd *openBrowserCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/open_learn_lesson.go b/domain/ide/command/open_learn_lesson.go index 078e7d0c8..0c65022a7 100644 --- a/domain/ide/command/open_learn_lesson.go +++ b/domain/ide/command/open_learn_lesson.go @@ -21,19 +21,19 @@ import ( "github.com/pkg/errors" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/types" ) type openLearnLesson struct { - command snyk.CommandData + command types.CommandData srv lsp.Server learnService learn.Service openBrowserHandleFunc func(url string) } -func (cmd *openLearnLesson) Command() snyk.CommandData { +func (cmd *openLearnLesson) Command() types.CommandData { return cmd.command } @@ -48,7 +48,7 @@ func (cmd *openLearnLesson) Execute(_ context.Context) (any, error) { if cmd.openBrowserHandleFunc != nil { cmd.openBrowserHandleFunc(lesson.Url) } else { - snyk.DefaultOpenBrowserFunc(lesson.Url) + types.DefaultOpenBrowserFunc(lesson.Url) } return lesson, err } diff --git a/domain/ide/command/open_learn_lesson_test.go b/domain/ide/command/open_learn_lesson_test.go index 05779125a..65f261d15 100644 --- a/domain/ide/command/open_learn_lesson_test.go +++ b/domain/ide/command/open_learn_lesson_test.go @@ -27,6 +27,7 @@ import ( "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/infrastructure/learn/mock_learn" + "github.com/snyk/snyk-ls/internal/types" ) //goland:noinspection GoRedundantConversion because a json unmarshal would produce a float64, not an int8 @@ -44,9 +45,9 @@ func Test_openLearnLesson_Execute(t *testing.T) { rule := "javascript%2Fsqlinjection" cwes := "CWE-89,CWE-ZZ" cves := "CVE-2020-1234" - data := snyk.CommandData{ - Title: snyk.OpenLearnLesson, - CommandId: snyk.OpenLearnLesson, + data := types.CommandData{ + Title: types.OpenLearnLesson, + CommandId: types.OpenLearnLesson, Arguments: []any{rule, eco, cwes, cves, float64(snyk.DependencyVulnerability)}, } mockService := mock_learn.NewMockService(ctrl) diff --git a/domain/ide/command/report_analytics.go b/domain/ide/command/report_analytics.go index 4b97b5082..213d21a17 100644 --- a/domain/ide/command/report_analytics.go +++ b/domain/ide/command/report_analytics.go @@ -21,15 +21,15 @@ import ( "fmt" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/analytics" + "github.com/snyk/snyk-ls/internal/types" ) type reportAnalyticsCommand struct { - command snyk.CommandData + command types.CommandData } -func (cmd *reportAnalyticsCommand) Command() snyk.CommandData { +func (cmd *reportAnalyticsCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/report_analytics_test.go b/domain/ide/command/report_analytics_test.go index 5768e96f1..f93627f74 100644 --- a/domain/ide/command/report_analytics_test.go +++ b/domain/ide/command/report_analytics_test.go @@ -21,10 +21,12 @@ import ( "testing" "github.com/golang/mock/gomock" + localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" + "github.com/snyk/snyk-ls/internal/types" + "github.com/stretchr/testify/require" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/testutil" ) @@ -33,8 +35,8 @@ func Test_ReportAnalyticsCommand_IsCallingExtension(t *testing.T) { testInput := "some data" cmd := &reportAnalyticsCommand{ - command: snyk.CommandData{ - CommandId: snyk.ReportAnalyticsCommand, + command: types.CommandData{ + CommandId: types.ReportAnalyticsCommand, Arguments: []any{testInput}, }, } diff --git a/domain/ide/command/sast_enabled.go b/domain/ide/command/sast_enabled.go index 81e10b5b1..53456db16 100644 --- a/domain/ide/command/sast_enabled.go +++ b/domain/ide/command/sast_enabled.go @@ -22,17 +22,17 @@ import ( "github.com/rs/zerolog" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/snyk_api" + "github.com/snyk/snyk-ls/internal/types" ) type sastEnabled struct { - command snyk.CommandData + command types.CommandData apiClient snyk_api.SnykApiClient logger *zerolog.Logger } -func (cmd *sastEnabled) Command() snyk.CommandData { +func (cmd *sastEnabled) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/test_helpers.go b/domain/ide/command/test_helpers.go index 3b8da8cfc..404820109 100644 --- a/domain/ide/command/test_helpers.go +++ b/domain/ide/command/test_helpers.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/golang/mock/gomock" + "github.com/snyk/go-application-framework/pkg/configuration" "github.com/snyk/go-application-framework/pkg/mocks" diff --git a/domain/ide/command/trust_workspace_folders.go b/domain/ide/command/trust_workspace_folders.go index dda49db0f..15d0096ee 100644 --- a/domain/ide/command/trust_workspace_folders.go +++ b/domain/ide/command/trust_workspace_folders.go @@ -22,19 +22,19 @@ import ( "github.com/rs/zerolog" "github.com/snyk/snyk-ls/application/config" - noti "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" ) type trustWorkspaceFoldersCommand struct { - command snyk.CommandData + command types.CommandData notifier noti.Notifier logger *zerolog.Logger } -func (cmd *trustWorkspaceFoldersCommand) Command() snyk.CommandData { +func (cmd *trustWorkspaceFoldersCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/workspace_folder_scan.go b/domain/ide/command/workspace_folder_scan.go index 7529c785f..803c13c34 100644 --- a/domain/ide/command/workspace_folder_scan.go +++ b/domain/ide/command/workspace_folder_scan.go @@ -23,17 +23,17 @@ import ( "github.com/rs/zerolog" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/types" ) type workspaceFolderScanCommand struct { - command snyk.CommandData + command types.CommandData srv lsp.Server logger *zerolog.Logger } -func (cmd *workspaceFolderScanCommand) Command() snyk.CommandData { +func (cmd *workspaceFolderScanCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/command/workspace_scan.go b/domain/ide/command/workspace_scan.go index d7ffde573..86c4f1bed 100644 --- a/domain/ide/command/workspace_scan.go +++ b/domain/ide/command/workspace_scan.go @@ -20,16 +20,16 @@ import ( "context" "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/types" ) type workspaceScanCommand struct { - command snyk.CommandData + command types.CommandData srv lsp.Server } -func (cmd *workspaceScanCommand) Command() snyk.CommandData { +func (cmd *workspaceScanCommand) Command() types.CommandData { return cmd.command } diff --git a/domain/ide/converter/converter.go b/domain/ide/converter/converter.go index 54db2d3e1..98b0d0edb 100644 --- a/domain/ide/converter/converter.go +++ b/domain/ide/converter/converter.go @@ -25,6 +25,7 @@ import ( "github.com/snyk/snyk-ls/domain/ide/hover" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" ) @@ -82,7 +83,7 @@ func ToInlineValues(inlineValues []snyk.InlineValue) (values []lsp.InlineValue) return values } -func ToCommand(command *snyk.CommandData) *sglsp.Command { +func ToCommand(command *types.CommandData) *sglsp.Command { if command == nil { return nil } diff --git a/domain/ide/hover/fake_service.go b/domain/ide/hover/fake_service.go index b2c13504c..1e834b3f5 100644 --- a/domain/ide/hover/fake_service.go +++ b/domain/ide/hover/fake_service.go @@ -17,8 +17,8 @@ package hover import ( - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + ux2 "github.com/snyk/snyk-ls/internal/observability/ux" ) type FakeHoverService struct { diff --git a/domain/ide/hover/hover_analytics.go b/domain/ide/hover/hover_analytics.go index e9e05afc7..b93192964 100644 --- a/domain/ide/hover/hover_analytics.go +++ b/domain/ide/hover/hover_analytics.go @@ -17,8 +17,8 @@ package hover import ( - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/observability/ux" ) func NewIssueHoverIsDisplayedProperties(issue snyk.Issue) ux.IssueHoverIsDisplayedProperties { diff --git a/domain/ide/hover/hover_analytics_test.go b/domain/ide/hover/hover_analytics_test.go index 4ff91c992..497e2fdd3 100644 --- a/domain/ide/hover/hover_analytics_test.go +++ b/domain/ide/hover/hover_analytics_test.go @@ -20,8 +20,8 @@ import ( "reflect" "testing" - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/observability/ux" ) func TestNewIssueHoverIsDisplayedProperties(t *testing.T) { diff --git a/domain/ide/hover/service.go b/domain/ide/hover/service.go index c49f44c6c..0b4c82141 100644 --- a/domain/ide/hover/service.go +++ b/domain/ide/hover/service.go @@ -22,8 +22,8 @@ import ( "sync" "github.com/snyk/snyk-ls/application/config" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + ux2 "github.com/snyk/snyk-ls/internal/observability/ux" ) type Service interface { diff --git a/domain/ide/hover/service_test.go b/domain/ide/hover/service_test.go index b14363f92..30d8738d4 100644 --- a/domain/ide/hover/service_test.go +++ b/domain/ide/hover/service_test.go @@ -24,14 +24,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" ) func setupFakeHover() string { c := config.CurrentConfig() - target := NewDefaultService(c, ux2.NewTestAnalytics(c)).(*DefaultHoverService) + target := NewDefaultService(c, ux.NewTestAnalytics(c)).(*DefaultHoverService) fakeHover := []Hover[Context]{ {Range: snyk.Range{ Start: snyk.Position{Line: 3, Character: 56}, @@ -50,7 +50,7 @@ func setupFakeHover() string { func Test_registerHovers(t *testing.T) { c := testutil.UnitTest(t) - target := NewDefaultService(c, ux2.NewTestAnalytics(c)).(*DefaultHoverService) + target := NewDefaultService(c, ux.NewTestAnalytics(c)).(*DefaultHoverService) hover, path := fakeDocumentHover() target.registerHovers(hover) @@ -63,7 +63,7 @@ func Test_registerHovers(t *testing.T) { func Test_DeleteHover(t *testing.T) { c := testutil.UnitTest(t) - target := NewDefaultService(c, ux2.NewTestAnalytics(c)).(*DefaultHoverService) + target := NewDefaultService(c, ux.NewTestAnalytics(c)).(*DefaultHoverService) documentUri := setupFakeHover() target.DeleteHover(documentUri) @@ -73,7 +73,7 @@ func Test_DeleteHover(t *testing.T) { func Test_ClearAllHovers(t *testing.T) { c := testutil.UnitTest(t) - target := NewDefaultService(c, ux2.NewTestAnalytics(c)).(*DefaultHoverService) + target := NewDefaultService(c, ux.NewTestAnalytics(c)).(*DefaultHoverService) documentUri := setupFakeHover() target.ClearAllHovers() @@ -83,7 +83,7 @@ func Test_ClearAllHovers(t *testing.T) { func Test_GetHoverMultiline(t *testing.T) { c := testutil.UnitTest(t) - target := NewDefaultService(c, ux2.NewTestAnalytics(c)).(*DefaultHoverService) + target := NewDefaultService(c, ux.NewTestAnalytics(c)).(*DefaultHoverService) tests := []struct { hoverDetails []Hover[Context] @@ -166,7 +166,7 @@ func Test_GetHoverMultiline(t *testing.T) { func Test_TracksAnalytics(t *testing.T) { c := testutil.UnitTest(t) - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) target := NewDefaultService(c, analytics).(*DefaultHoverService) path := "path/to/package.json" @@ -189,16 +189,16 @@ func Test_TracksAnalytics(t *testing.T) { target.GetHover(path, snyk.Position{Line: 4, Character: 66}) assert.Len(t, analytics.GetAnalytics(), 1) - assert.Equal(t, ux2.IssueHoverIsDisplayedProperties{ + assert.Equal(t, ux.IssueHoverIsDisplayedProperties{ IssueId: "issue", - IssueType: ux2.ContainerVulnerability, - Severity: ux2.Medium, + IssueType: ux.ContainerVulnerability, + Severity: ux.Medium, }, analytics.GetAnalytics()[0]) } func Test_SendingHovers_AfterClearAll_DoesNotBlock(t *testing.T) { c := testutil.UnitTest(t) - service := NewDefaultService(c, ux2.NewTestAnalytics(c)).(*DefaultHoverService) + service := NewDefaultService(c, ux.NewTestAnalytics(c)).(*DefaultHoverService) service.ClearAllHovers() hover, _ := fakeDocumentHover() diff --git a/domain/ide/notification/notifier.go b/domain/ide/notification/notifier.go deleted file mode 100644 index 0c894899e..000000000 --- a/domain/ide/notification/notifier.go +++ /dev/null @@ -1,18 +0,0 @@ -package notification - -import ( - "github.com/sourcegraph/go-lsp" -) - -// Notifier should be passed as a dependency to the types that call "notification.x" functions. -// This allows using mocks and enables us to gradually refactor out the direct calls to -// the "notification" package functions. -type Notifier interface { - SendShowMessage(messageType lsp.MessageType, message string) - Send(msg any) - SendError(err error) - SendErrorDiagnostic(path string, err error) - Receive() (payload any, stop bool) - CreateListener(callback func(params any)) - DisposeListener() -} diff --git a/domain/ide/workspace/folder.go b/domain/ide/workspace/folder.go index a30c03249..3c8ed7bb9 100644 --- a/domain/ide/workspace/folder.go +++ b/domain/ide/workspace/folder.go @@ -20,12 +20,14 @@ import ( "context" "encoding/json" "fmt" - "github.com/snyk/snyk-ls/internal/util" "strings" "sync" + "github.com/snyk/snyk-ls/internal/util" + "github.com/google/uuid" "github.com/puzpuzpuz/xsync/v3" + gafanalytics "github.com/snyk/go-application-framework/pkg/analytics" "github.com/snyk/go-application-framework/pkg/instrumentation" "github.com/snyk/go-application-framework/pkg/local_workflows/json_schemas" @@ -33,10 +35,10 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/converter" "github.com/snyk/snyk-ls/domain/ide/hover" - noti "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/analytics" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/uri" ) diff --git a/domain/ide/workspace/folder_test.go b/domain/ide/workspace/folder_test.go index dbc7c48e0..ad4e532bf 100644 --- a/domain/ide/workspace/folder_test.go +++ b/domain/ide/workspace/folder_test.go @@ -27,21 +27,22 @@ import ( "github.com/golang/mock/gomock" "github.com/google/uuid" "github.com/puzpuzpuz/xsync/v3" + "github.com/spf13/pflag" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/snyk/go-application-framework/pkg/analytics" "github.com/snyk/go-application-framework/pkg/configuration" localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/mocks" "github.com/snyk/go-application-framework/pkg/workflow" - "github.com/spf13/pflag" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/hover" - noti "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/notification" + noti "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/util" diff --git a/domain/ide/workspace/workspace.go b/domain/ide/workspace/workspace.go index bc49870c5..221a2d40d 100644 --- a/domain/ide/workspace/workspace.go +++ b/domain/ide/workspace/workspace.go @@ -22,10 +22,10 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/hover" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/performance" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/performance" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/uri" ) diff --git a/domain/ide/workspace/workspace_test.go b/domain/ide/workspace/workspace_test.go index 140018fdf..6022a7a05 100644 --- a/domain/ide/workspace/workspace_test.go +++ b/domain/ide/workspace/workspace_test.go @@ -23,10 +23,10 @@ import ( "github.com/stretchr/testify/assert" - "github.com/snyk/snyk-ls/domain/observability/performance" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/performance" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/uri" ) diff --git a/domain/snyk/auth_service_impl.go b/domain/snyk/auth_service_impl.go deleted file mode 100644 index ae718d8da..000000000 --- a/domain/snyk/auth_service_impl.go +++ /dev/null @@ -1,123 +0,0 @@ -/* - * © 2022-2023 Snyk Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package snyk - -import ( - "context" - "reflect" - - "github.com/snyk/snyk-ls/application/config" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/ux" - "github.com/snyk/snyk-ls/internal/lsp" -) - -type ActiveUser struct { - Id string `json:"id"` - UserName string `json:"username,omitempty"` - Orgs []struct { - Name string `json:"name,omitempty"` - Id string `json:"id,omitempty"` - Group struct { - Name string `json:"name,omitempty"` - Id string `json:"id,omitempty"` - } `json:"group,omitempty"` - } `json:"orgs,omitempty"` -} - -type authenticationService struct { - authenticationProvider AuthenticationProvider - analytics ux.Analytics - errorReporter error_reporting.ErrorReporter - notifier noti.Notifier - c *config.Config -} - -func NewAuthenticationService( - c *config.Config, - authenticationProvider AuthenticationProvider, - analytics ux.Analytics, - errorReporter error_reporting.ErrorReporter, - notifier noti.Notifier, -) AuthenticationService { - return &authenticationService{authenticationProvider, analytics, errorReporter, notifier, c} -} - -func (a *authenticationService) Provider() AuthenticationProvider { - return a.authenticationProvider -} - -func (a *authenticationService) Authenticate(ctx context.Context) (string, error) { - token, err := a.authenticationProvider.Authenticate(ctx) - if token == "" || err != nil { - a.c.Logger().Error().Err(err).Msgf("Failed to authenticate using auth provider %v", reflect.TypeOf(a.Provider())) - return "", err - } - a.UpdateCredentials(token, true) - a.analytics.Identify() - return token, err -} - -func (a *authenticationService) UpdateCredentials(newToken string, sendNotification bool) { - c := config.CurrentConfig() - oldToken := c.Token() - if oldToken == newToken { - return - } - - c.SetToken(newToken) - - if sendNotification { - a.notifier.Send(lsp.AuthenticationParams{Token: newToken}) - } -} - -func (a *authenticationService) Logout(ctx context.Context) { - err := a.authenticationProvider.ClearAuthentication(ctx) - if err != nil { - a.c.Logger().Error().Err(err).Str("method", "Logout").Msg("Failed to log out.") - a.errorReporter.CaptureError(err) - return - } - - a.UpdateCredentials("", true) -} - -// IsAuthenticated returns true if the token is verified -// If the token is set, but not valid IsAuthenticated returns false and the reported error -func (a *authenticationService) IsAuthenticated() (bool, error) { - c := config.CurrentConfig() - if !c.NonEmptyToken() { - c.Logger().Info().Str("method", "IsAuthenticated").Msg("no credentials found") - return false, nil - } - - user, getActiveUserErr := a.authenticationProvider.GetCheckAuthenticationFunction()() - - if getActiveUserErr != nil { - a.c.Logger().Err(getActiveUserErr).Str("method", "IsAuthenticated").Msg("Failed to get active user") - return false, getActiveUserErr - } - - a.c.Logger().Debug().Msg("IsAuthenticated: " + user) - return true, nil -} - -func (a *authenticationService) SetProvider(provider AuthenticationProvider) { - a.authenticationProvider = provider -} diff --git a/domain/snyk/codeaction.go b/domain/snyk/codeaction.go index 05fc783f1..a04a0f34d 100644 --- a/domain/snyk/codeaction.go +++ b/domain/snyk/codeaction.go @@ -20,6 +20,8 @@ import ( "errors" "github.com/google/uuid" + + "github.com/snyk/snyk-ls/internal/types" ) // CodeAction represents a code action that can be executed by the client using an in-document menu. @@ -44,18 +46,18 @@ type CodeAction struct { DeferredEdit *func() *WorkspaceEdit // Command that will be executed after the Edit (if present). - Command *CommandData + Command *types.CommandData // DeferredCommand is a function that returns a Command. // Used for heavy calculations that shouldn't be done ahead of time. // A CodeAction cannot have both Command and DeferredCommand. - DeferredCommand *func() *CommandData + DeferredCommand *func() *types.CommandData // UUID is a unique identifier for this code action. This is used for deferred resolution of a command or edit. Uuid *uuid.UUID } -func NewCodeAction(title string, edit *WorkspaceEdit, command *CommandData) (CodeAction, error) { +func NewCodeAction(title string, edit *WorkspaceEdit, command *types.CommandData) (CodeAction, error) { if edit == nil && command == nil { return CodeAction{}, errors.New("a non-deferred action must have either an edit or a command") } @@ -70,7 +72,7 @@ func NewCodeAction(title string, edit *WorkspaceEdit, command *CommandData) (Cod func NewDeferredCodeAction(title string, deferredEdit *func() *WorkspaceEdit, - deferredCommand *func() *CommandData, + deferredCommand *func() *types.CommandData, ) (CodeAction, error) { if deferredEdit == nil && deferredCommand == nil { return CodeAction{}, errors.New("deferredEdit and deferredCommand cannot both be nil") diff --git a/domain/snyk/codeaction_test.go b/domain/snyk/codeaction_test.go index e76cf6ebe..ee2e46c76 100644 --- a/domain/snyk/codeaction_test.go +++ b/domain/snyk/codeaction_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/domain/snyk" + "github.com/snyk/snyk-ls/internal/types" ) var mockTextEdit = snyk.TextEdit{ @@ -21,7 +22,7 @@ var mockEdit = &snyk.WorkspaceEdit{ }, } -var mockCommand = &snyk.CommandData{ +var mockCommand = &types.CommandData{ Title: "command", } @@ -29,7 +30,7 @@ var mockDeferredEdit = func() *snyk.WorkspaceEdit { return mockEdit } -var mockDeferredCommand = func() *snyk.CommandData { +var mockDeferredCommand = func() *types.CommandData { return mockCommand } @@ -55,7 +56,7 @@ func Test_NewDeferredCodeAction(t *testing.T) { err, action, (*snyk.WorkspaceEdit)(nil), - (*snyk.CommandData)(nil), + (*types.CommandData)(nil), &mockDeferredEdit, &mockDeferredCommand) assert.NotNil(t, action.Uuid, "UUID should be initialized") @@ -65,9 +66,9 @@ func assertActionsInitializedCorrectly(t *testing.T, err error, action snyk.CodeAction, expectedEdit *snyk.WorkspaceEdit, - expectedCommand *snyk.CommandData, + expectedCommand *types.CommandData, mockDeferredEdit *func() *snyk.WorkspaceEdit, - mockDeferredCommand *func() *snyk.CommandData, + mockDeferredCommand *func() *types.CommandData, ) { t.Helper() assert.NoError(t, err) diff --git a/domain/snyk/issues.go b/domain/snyk/issues.go index ea95a6082..c394a1b0e 100644 --- a/domain/snyk/issues.go +++ b/domain/snyk/issues.go @@ -23,6 +23,7 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/product" + "github.com/snyk/snyk-ls/internal/types" ) type Reference struct { @@ -56,7 +57,7 @@ type Issue struct { // CodeActions can contain workspace edits or commands to be executed CodeActions []CodeAction // CodelensCommands that can be executed via a codelens - CodelensCommands []CommandData + CodelensCommands []types.CommandData // The Ecosystem of the issue, e.g. npm, maven, nuget, etc. Ecosystem string // A slice of the CWEs of the issue, e.g. CWEs-79 diff --git a/domain/snyk/scanner.go b/domain/snyk/scanner.go index ca8a4d851..8fa282c9a 100644 --- a/domain/snyk/scanner.go +++ b/domain/snyk/scanner.go @@ -23,11 +23,12 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/initialize" - "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/performance" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/product" ) @@ -58,10 +59,10 @@ type DelegatingConcurrentScanner struct { scanners []ProductScanner initializer initialize.Initializer instrumentor performance.Instrumentor - analytics ux2.Analytics + analytics ux.Analytics scanNotifier ScanNotifier snykApiClient snyk_api.SnykApiClient - authService AuthenticationService + authService authentication.AuthenticationService notifier notification.Notifier c *config.Config } @@ -174,10 +175,10 @@ func NewDelegatingScanner( c *config.Config, initializer initialize.Initializer, instrumentor performance.Instrumentor, - analytics ux2.Analytics, + analytics ux.Analytics, scanNotifier ScanNotifier, snykApiClient snyk_api.SnykApiClient, - authService AuthenticationService, + authService authentication.AuthenticationService, notifier notification.Notifier, scanners ...ProductScanner, ) Scanner { @@ -265,7 +266,7 @@ func (sc *DelegatingConcurrentScanner) Scan( analysisTypes := getEnabledAnalysisTypes(sc.scanners) if len(analysisTypes) > 0 { sc.analytics.AnalysisIsTriggered( - ux2.AnalysisIsTriggeredProperties{ + ux.AnalysisIsTriggeredProperties{ AnalysisType: analysisTypes, TriggeredByUser: false, }, @@ -312,23 +313,23 @@ func (sc *DelegatingConcurrentScanner) Scan( // TODO: handle learn actions centrally instead of in each scanner } -func getEnabledAnalysisTypes(productScanners []ProductScanner) (analysisTypes []ux2.AnalysisType) { +func getEnabledAnalysisTypes(productScanners []ProductScanner) (analysisTypes []ux.AnalysisType) { for _, ps := range productScanners { if !ps.IsEnabled() { continue } if ps.Product() == product.ProductInfrastructureAsCode { - analysisTypes = append(analysisTypes, ux2.InfrastructureAsCode) + analysisTypes = append(analysisTypes, ux.InfrastructureAsCode) } if ps.Product() == product.ProductOpenSource { - analysisTypes = append(analysisTypes, ux2.OpenSource) + analysisTypes = append(analysisTypes, ux.OpenSource) } if ps.Product() == product.ProductCode { if config.CurrentConfig().IsSnykCodeQualityEnabled() || config.CurrentConfig().IsSnykCodeEnabled() { - analysisTypes = append(analysisTypes, ux2.CodeQuality) + analysisTypes = append(analysisTypes, ux.CodeQuality) } if config.CurrentConfig().IsSnykCodeSecurityEnabled() || config.CurrentConfig().IsSnykCodeEnabled() { - analysisTypes = append(analysisTypes, ux2.CodeSecurity) + analysisTypes = append(analysisTypes, ux.CodeSecurity) } } } diff --git a/domain/snyk/scanner_test.go b/domain/snyk/scanner_test.go index 0a95f06c5..8073709f3 100644 --- a/domain/snyk/scanner_test.go +++ b/domain/snyk/scanner_test.go @@ -26,11 +26,12 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/ide/initialize" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/observability/ux" + "github.com/snyk/snyk-ls/infrastructure/authentication" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + ux2 "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/testutil" ) @@ -55,18 +56,18 @@ func TestScan_UsesEnabledProductLinesOnly(t *testing.T) { func setupScanner(testProductScanners ...ProductScanner) ( scanner Scanner, - analytics *ux.TestAnalytics, + analytics *ux2.TestAnalytics, scanNotifier ScanNotifier, ) { c := config.CurrentConfig() - analytics = ux.NewTestAnalytics(c) + analytics = ux2.NewTestAnalytics(c) scanNotifier = NewMockScanNotifier() notifier := notification.NewNotifier() apiClient := &snyk_api.FakeApiClient{CodeEnabled: false} er := error_reporting.NewTestErrorReporter() - authenticationProvider := NewFakeCliAuthenticationProvider(c) + authenticationProvider := authentication.NewFakeCliAuthenticationProvider(c) authenticationProvider.IsAuthenticated = true - authenticationService := NewAuthenticationService(c, authenticationProvider, analytics, er, notifier) + authenticationService := authentication.NewAuthenticationService(c, []authentication.AuthenticationProvider{authenticationProvider}, analytics, er, notifier) scanner = NewDelegatingScanner( c, initialize.NewDelegatingInitializer(), @@ -91,8 +92,8 @@ func TestScan_whenProductScannerEnabled_SendsAnalysisTriggered(t *testing.T) { scanner.Scan(context.Background(), "", NoopResultProcessor, "") assert.Contains(t, analytics.GetAnalytics(), - ux.AnalysisIsTriggeredProperties{ - AnalysisType: []ux.AnalysisType{ux.CodeQuality, ux.CodeSecurity}, + ux2.AnalysisIsTriggeredProperties{ + AnalysisType: []ux2.AnalysisType{ux2.CodeQuality, ux2.CodeSecurity}, TriggeredByUser: false, }) } diff --git a/go.mod b/go.mod index 782b67ab5..f87dc8c80 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 github.com/google/uuid v1.6.0 github.com/hexops/gotextdiff v1.0.3 + github.com/modern-go/reflect2 v1.0.2 github.com/pact-foundation/pact-go v1.7.0 github.com/pingcap/errors v0.11.4 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 5df4f3c32..b7bd879d0 100644 --- a/go.sum +++ b/go.sum @@ -322,6 +322,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= diff --git a/infrastructure/amplitude/client.go b/infrastructure/amplitude/client.go index 0d62f5a4b..7c71d3608 100644 --- a/infrastructure/amplitude/client.go +++ b/infrastructure/amplitude/client.go @@ -24,8 +24,8 @@ import ( "github.com/snyk/snyk-ls/ampli" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/ux" ) type Client struct { @@ -38,7 +38,7 @@ type Client struct { type captureEvent func(userId string, eventOptions ...ampli.EventOptions) -func NewAmplitudeClient(c *config.Config, authFunc func() (string, error), errorReporter error_reporting.ErrorReporter) ux2.Analytics { +func NewAmplitudeClient(c *config.Config, authFunc func() (string, error), errorReporter error_reporting.ErrorReporter) ux.Analytics { ampliConfig := amplitude.NewConfig("") ampli.Instance.Load(ampli.LoadOptions{ @@ -69,7 +69,7 @@ func (c *Client) Shutdown() error { return c.destination.Shutdown() } -func (c *Client) AnalysisIsReady(properties ux2.AnalysisIsReadyProperties) { +func (c *Client) AnalysisIsReady(properties ux.AnalysisIsReadyProperties) { c.c.Logger().Debug().Str("method", "AnalysisIsReady").Msg("analytics enqueued") analysisType := ampli.AnalysisIsReadyAnalysisType(properties.AnalysisType) ide := ampli.AnalysisIsReadyIde(getIdeProperty()) @@ -93,7 +93,7 @@ func (c *Client) AnalysisIsReady(properties ux2.AnalysisIsReadyProperties) { c.enqueueEvent(captureFn) } -func (c *Client) AnalysisIsTriggered(properties ux2.AnalysisIsTriggeredProperties) { +func (c *Client) AnalysisIsTriggered(properties ux.AnalysisIsTriggeredProperties) { c.c.Logger().Debug().Str("method", "AnalysisIsTriggered").Msg("analytics enqueued") analysisTypes := make([]string, 0, len(properties.AnalysisType)) for _, analysisType := range properties.AnalysisType { @@ -118,7 +118,7 @@ func (c *Client) AnalysisIsTriggered(properties ux2.AnalysisIsTriggeredPropertie c.enqueueEvent(captureFn) } -func (c *Client) IssueHoverIsDisplayed(properties ux2.IssueHoverIsDisplayedProperties) { +func (c *Client) IssueHoverIsDisplayed(properties ux.IssueHoverIsDisplayedProperties) { c.c.Logger().Debug().Str("method", "IssueHoverIsDisplayed").Msg("analytics enqueued") ide := ampli.IssueHoverIsDisplayedIde(getIdeProperty()) issueType := ampli.IssueHoverIsDisplayedIssueType(properties.IssueType) @@ -141,7 +141,7 @@ func (c *Client) IssueHoverIsDisplayed(properties ux2.IssueHoverIsDisplayedPrope c.enqueueEvent(captureFn) } -func (c *Client) PluginIsInstalled(_ ux2.PluginIsInstalledProperties) { +func (c *Client) PluginIsInstalled(_ ux.PluginIsInstalledProperties) { c.c.Logger().Debug().Str("method", "PluginIsInstalled").Msg("analytics enqueued") conf := config.CurrentConfig() @@ -160,7 +160,7 @@ func (c *Client) PluginIsInstalled(_ ux2.PluginIsInstalledProperties) { c.enqueueEvent(captureFn) } -func (c *Client) ScanModeIsSelected(properties ux2.ScanModeIsSelectedProperties) { +func (c *Client) ScanModeIsSelected(properties ux.ScanModeIsSelectedProperties) { conf := config.CurrentConfig() ide := ampli.ScanModeIsSelectedIde(getIdeProperty()) @@ -219,19 +219,19 @@ func (c *Client) Identify() { } // Only return an IDE property if it's a recognized IDE in the tracking plan -func getIdeProperty() ux2.IDE { +func getIdeProperty() ux.IDE { // Standardize the names integrationName := strings.Replace(strings.ToLower(config.CurrentConfig().IntegrationName()), "_", " ", -1) switch integrationName { - case string(ux2.Eclipse): - return ux2.Eclipse + case string(ux.Eclipse): + return ux.Eclipse case "vs code": - return ux2.VisualStudioCode - case string(ux2.VisualStudio): - return ux2.VisualStudio - case string(ux2.JetBrains): - return ux2.JetBrains + return ux.VisualStudioCode + case string(ux.VisualStudio): + return ux.VisualStudio + case string(ux.JetBrains): + return ux.JetBrains default: return "Other" // ensure we pass Amplitude validation, when IDE is not in the tracking plan } diff --git a/infrastructure/amplitude/client_test.go b/infrastructure/amplitude/client_test.go index 13866cd95..0b490f31b 100644 --- a/infrastructure/amplitude/client_test.go +++ b/infrastructure/amplitude/client_test.go @@ -25,8 +25,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/ux" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/amplitude/install_event.go b/infrastructure/amplitude/install_event.go index 6c7b2f0cd..67c5d714c 100644 --- a/infrastructure/amplitude/install_event.go +++ b/infrastructure/amplitude/install_event.go @@ -21,7 +21,7 @@ import ( "path/filepath" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/ux" + "github.com/snyk/snyk-ls/internal/observability/ux" ) const ( diff --git a/infrastructure/analytics/pact_test.go b/infrastructure/analytics/pact_test.go index 4c57fc941..1a672f43f 100644 --- a/infrastructure/analytics/pact_test.go +++ b/infrastructure/analytics/pact_test.go @@ -8,13 +8,14 @@ import ( "github.com/google/uuid" "github.com/pact-foundation/pact-go/dsl" + "github.com/stretchr/testify/assert" + "github.com/snyk/go-application-framework/pkg/analytics" "github.com/snyk/go-application-framework/pkg/configuration" "github.com/snyk/go-application-framework/pkg/instrumentation" "github.com/snyk/go-application-framework/pkg/local_workflows/json_schemas" "github.com/snyk/go-application-framework/pkg/networking" "github.com/snyk/go-application-framework/pkg/utils" - "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/testutil" diff --git a/infrastructure/authentication/auth_configuration.go b/infrastructure/authentication/auth_configuration.go new file mode 100644 index 000000000..795d36931 --- /dev/null +++ b/infrastructure/authentication/auth_configuration.go @@ -0,0 +1,94 @@ +/* + * © 2024 Snyk Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package authentication + +import ( + "context" + "errors" + "fmt" + + "golang.org/x/oauth2" + + "github.com/snyk/go-application-framework/pkg/auth" + "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/application/config" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/storage" + "github.com/snyk/snyk-ls/internal/types" +) + +// Token authentication configures token only authentication +func Token(c *config.Config, errorReporter error_reporting.ErrorReporter) []AuthenticationProvider { + return []AuthenticationProvider{NewCliAuthenticationProvider(c, errorReporter)} +} + +// Default authentication configures two authenticators, the first OAuth2, +// the second, as fallback, CLI Token auth +// the auth service parameter is needed, as the oauth2 provider needs a callback function +func Default(c *config.Config, errorReporter error_reporting.ErrorReporter, authenticationService AuthenticationService) []AuthenticationProvider { + authProviders := []AuthenticationProvider{} + + credentialsUpdateCallback := func(_ string, value any) { + newToken, ok := value.(string) + if !ok { + msg := fmt.Sprintf("Failed to cast creds of type %T to string", value) + errorReporter.CaptureError(errors.New(msg)) + return + } + go authenticationService.UpdateCredentials(newToken, true) + } + + openBrowserFunc := func(url string) { + for _, provider := range authenticationService.Providers() { + provider.SetAuthURL(url) + } + types.DefaultOpenBrowserFunc(url) + } + + // add both OAuth2 and CLI, with preference to OAuth2 + authProviders = append(authProviders, + NewOAuthProvider( + c, + auth.RefreshToken, + credentialsUpdateCallback, + openBrowserFunc, + ), + ) + authProviders = append(authProviders, NewCliAuthenticationProvider(c, errorReporter)) + return authProviders +} + +func NewOAuthProvider( + c *config.Config, + customTokenRefresherFunc func(ctx context.Context, oauthConfig *oauth2.Config, token *oauth2.Token) (*oauth2.Token, error), + credentialsUpdateCallback storage.StorageCallbackFunc, + openBrowserFunc func(string), +) *OAuth2Provider { + engine := c.Engine() + conf := engine.GetConfiguration() + + conf.Set(configuration.FF_OAUTH_AUTH_FLOW_ENABLED, true) + + c.Storage().RegisterCallback(auth.CONFIG_KEY_OAUTH_TOKEN, credentialsUpdateCallback) + + authenticator := auth.NewOAuth2AuthenticatorWithOpts( + conf, + auth.WithOpenBrowserFunc(openBrowserFunc), + auth.WithTokenRefresherFunc(customTokenRefresherFunc), + ) + return newOAuthProvider(conf, authenticator, c.Logger()) +} diff --git a/infrastructure/authentication/auth_configuration_test.go b/infrastructure/authentication/auth_configuration_test.go new file mode 100644 index 000000000..26d6b33b2 --- /dev/null +++ b/infrastructure/authentication/auth_configuration_test.go @@ -0,0 +1,91 @@ +/* + * © 2024 Snyk Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package authentication + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "golang.org/x/oauth2" + + "github.com/snyk/go-application-framework/pkg/auth" + "github.com/snyk/snyk-ls/internal/testutil" +) + +func Test_NewOAuthProvider_registersStorageCallback(t *testing.T) { + c := testutil.UnitTest(t) + + // a token that's set into the configuration + token := oauth2.Token{ + AccessToken: t.Name(), + RefreshToken: t.Name(), + Expiry: time.Now().Add(1 * time.Hour), + } + + tokenReceived := make(chan bool, 1) + credentialsUpdateCallback := func(_ string, newToken any) { + tokenReceived <- true + } + + NewOAuthProvider(c, auth.RefreshToken, credentialsUpdateCallback, nil) + + marshal, err := json.Marshal(token) + assert.NoError(t, err) + err = c.Storage().Set(auth.CONFIG_KEY_OAUTH_TOKEN, string(marshal)) + assert.NoError(t, err) + assert.Eventuallyf(t, func() bool { + return <-tokenReceived + }, 5*time.Second, 100*time.Millisecond, "token should have been received") +} + +func Test_NewOauthProvider_oauthProvider_created_with_injected_refreshMethod(t *testing.T) { + c := testutil.UnitTest(t) + + // an expired token that's set into the configuration + token := oauth2.Token{ + AccessToken: t.Name(), + RefreshToken: t.Name(), + Expiry: time.Now().Add(-1 * time.Hour), + } + + tokenBytes, err := json.Marshal(token) + assert.NoError(t, err) + + c.SetToken(string(tokenBytes)) + + // refresh func is replaced with func that sends true into a channel when called + triggeredChan := make(chan bool, 1) + testFunc := func(ctx context.Context, oauthConfig *oauth2.Config, token *oauth2.Token) (*oauth2.Token, error) { + triggeredChan <- true + token.Expiry = time.Now().Add(1 * time.Hour) + return token, nil + } + + provider := NewOAuthProvider(c, testFunc, nil, nil) + + // AddAuthenticationHeader will trigger the refresh method + _ = provider.Authenticator().AddAuthenticationHeader(httptest.NewRequest(http.MethodGet, "/", nil)) + + assert.Eventuallyf(t, func() bool { + return <-triggeredChan + }, 5*time.Second, 100*time.Millisecond, "refresh should have been triggered") +} diff --git a/domain/snyk/auth_provider.go b/infrastructure/authentication/auth_provider.go similarity index 94% rename from domain/snyk/auth_provider.go rename to infrastructure/authentication/auth_provider.go index ea8b780a2..1e07a23d0 100644 --- a/domain/snyk/auth_provider.go +++ b/infrastructure/authentication/auth_provider.go @@ -1,5 +1,5 @@ /* - * © 2022-2023 Snyk Limited + * © 2022-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package snyk +package authentication import ( "context" @@ -37,8 +37,6 @@ func (e *AuthenticationFailedError) Error() string { return message } -type AuthenticationFunction func() (string, error) - type AuthenticationProvider interface { // Authenticate triggers the authentication. This may involve manual steps, like logging in using a browser Authenticate(ctx context.Context) (string, error) diff --git a/domain/snyk/auth_service.go b/infrastructure/authentication/auth_service.go similarity index 74% rename from domain/snyk/auth_service.go rename to infrastructure/authentication/auth_service.go index a2b878e3e..1d25bbd2b 100644 --- a/domain/snyk/auth_service.go +++ b/infrastructure/authentication/auth_service.go @@ -1,5 +1,5 @@ /* - * © 2022-2023 Snyk Limited + * © 2022-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,19 @@ * limitations under the License. */ -package snyk +package authentication -import "context" +import ( + "context" + + "github.com/snyk/snyk-ls/application/config" +) type AuthenticationService interface { // Authenticate attempts to authenticate the user, and sends a notification to the client when successful Authenticate(ctx context.Context) (string, error) - Provider() AuthenticationProvider + Providers() []AuthenticationProvider // UpdateCredentials stores the token in the configuration, and sends a $/snyk.hasAuthenticated notification to the // client if sendNotification is true @@ -33,6 +37,9 @@ type AuthenticationService interface { // IsAuthenticated returns true if the token is verified IsAuthenticated() (bool, error) - // SetProvider sets the authentication provider - SetProvider(provider AuthenticationProvider) + // AddProvider sets the authentication provider + AddProvider(provider AuthenticationProvider) + + // ConfigureProviders updates the providers based on the stored configuration + ConfigureProviders(c *config.Config) } diff --git a/infrastructure/authentication/auth_service_impl.go b/infrastructure/authentication/auth_service_impl.go new file mode 100644 index 000000000..b58580129 --- /dev/null +++ b/infrastructure/authentication/auth_service_impl.go @@ -0,0 +1,162 @@ +/* + * © 2022-2024 Snyk Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package authentication + +import ( + "context" + "reflect" + + "github.com/snyk/snyk-ls/application/config" + "github.com/snyk/snyk-ls/internal/data_structure" + "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/ux" + "github.com/snyk/snyk-ls/internal/types" +) + +type AuthenticationServiceImpl struct { + providers []AuthenticationProvider + analytics ux.Analytics + errorReporter error_reporting.ErrorReporter + notifier noti.Notifier + c *config.Config +} + +func NewAuthenticationService(c *config.Config, authProviders []AuthenticationProvider, analytics ux.Analytics, errorReporter error_reporting.ErrorReporter, notifier noti.Notifier) AuthenticationService { + return &AuthenticationServiceImpl{authProviders, analytics, errorReporter, notifier, c} +} + +func (a *AuthenticationServiceImpl) Providers() []AuthenticationProvider { + return a.providers +} + +func (a *AuthenticationServiceImpl) Authenticate(ctx context.Context) (token string, err error) { + for _, provider := range a.providers { + token, err = provider.Authenticate(ctx) + if token == "" || err != nil { + a.c.Logger().Warn().Err(err).Msgf("Failed to authenticate using auth provider %v", reflect.TypeOf(provider)) + continue + } + a.UpdateCredentials(token, true) + a.analytics.Identify() + return token, err + } + return token, err +} + +func (a *AuthenticationServiceImpl) UpdateCredentials(newToken string, sendNotification bool) { + c := config.CurrentConfig() + oldToken := c.Token() + if oldToken == newToken { + return + } + + c.SetToken(newToken) + + if sendNotification { + a.notifier.Send(lsp.AuthenticationParams{Token: newToken}) + } +} + +func (a *AuthenticationServiceImpl) Logout(ctx context.Context) { + for _, provider := range a.providers { + err := provider.ClearAuthentication(ctx) + if err != nil { + a.c.Logger().Warn().Err(err).Str("method", "Logout").Msg("Failed to log out.") + a.errorReporter.CaptureError(err) + } + } + a.UpdateCredentials("", true) +} + +// IsAuthenticated returns true if the token is verified +// If the token is set, but not valid IsAuthenticated returns false and the reported error +func (a *AuthenticationServiceImpl) IsAuthenticated() (bool, error) { + logger := a.c.Logger().With().Str("method", "AuthenticationService.IsAuthenticated").Logger() + if !a.c.NonEmptyToken() { + logger.Info().Str("method", "IsAuthenticated").Msg("no credentials found") + return false, nil + } + var user string + var err error + for _, provider := range a.providers { + providerType := reflect.TypeOf(provider).String() + user, err = provider.GetCheckAuthenticationFunction()() + if user == "" || err != nil { + a.c.Logger(). + Err(err). + Str("method", "AuthenticationService.IsAuthenticated"). + Str("authProvider", providerType). + Msg("Failed to get active user") + } else { + break + } + } + + if user == "" { + a.HandleInvalidCredentials(a.c) + return false, err + } + + a.c.Logger().Debug().Msg("IsAuthenticated: " + user) + return true, nil +} + +func (a *AuthenticationServiceImpl) AddProvider(provider AuthenticationProvider) { + a.providers = append(a.providers, provider) +} + +func (a *AuthenticationServiceImpl) setProviders(providers []AuthenticationProvider) { + a.providers = providers +} + +func (a *AuthenticationServiceImpl) ConfigureProviders(c *config.Config) { + var as []AuthenticationProvider + switch c.AuthenticationMethod() { + case lsp.FakeAuthentication: + a.setProviders([]AuthenticationProvider{NewFakeCliAuthenticationProvider(c)}) + case lsp.TokenAuthentication: + as = Token(c, a.errorReporter) + a.setProviders(as) + case "": + // don't do anything + default: + as = Default(c, a.errorReporter, a) + a.setProviders(as) + } +} + +func (a *AuthenticationServiceImpl) HandleInvalidCredentials(c *config.Config) { + logger := c.Logger().With().Str("method", "AuthenticationServiceImpl.HandleInvalidCredentials").Logger() + msg := "Your authentication credentials cannot be validated. Automatically clearing credentials. You need to re-authenticate to use Snyk." + logger.Debug().Msg("logging out") + a.Logout(context.Background()) + + actions := data_structure.OrderedMap[types.MessageAction, types.CommandData]{} + actions.Add("Authenticate", types.CommandData{ + Title: "Authenticate", + CommandId: types.LoginCommand, + }) + actions.Add("Cancel", types.CommandData{}) + + a.notifier.Send(types.ShowMessageRequest{ + Message: msg, + Type: types.Warning, + Actions: &actions, + }) +} diff --git a/domain/snyk/auth_service_impl_test.go b/infrastructure/authentication/auth_service_impl_test.go similarity index 50% rename from domain/snyk/auth_service_impl_test.go rename to infrastructure/authentication/auth_service_impl_test.go index 190e74f18..35682456c 100644 --- a/domain/snyk/auth_service_impl_test.go +++ b/infrastructure/authentication/auth_service_impl_test.go @@ -1,5 +1,5 @@ /* - * © 2022-2023 Snyk Limited + * © 2022-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,37 +14,32 @@ * limitations under the License. */ -package snyk_test +package authentication import ( "context" "encoding/json" - "path/filepath" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/oauth2" "github.com/snyk/snyk-ls/application/config" - appNotification "github.com/snyk/snyk-ls/application/server/notification" - "github.com/snyk/snyk-ls/domain/ide/converter" - "github.com/snyk/snyk-ls/domain/ide/hover" - "github.com/snyk/snyk-ls/domain/ide/workspace" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/observability/ux" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" + "github.com/snyk/snyk-ls/internal/types" ) func Test_UpdateCredentials(t *testing.T) { t.Run("CLI Authentication", func(t *testing.T) { c := testutil.UnitTest(t) analytics := ux.NewTestAnalytics(c) - service := snyk.NewAuthenticationService( + service := NewAuthenticationService( c, nil, analytics, @@ -59,9 +54,8 @@ func Test_UpdateCredentials(t *testing.T) { t.Run("OAuth Authentication Authentication", func(t *testing.T) { c := testutil.UnitTest(t) - config.CurrentConfig().SetAuthenticationMethod(lsp.OAuthAuthentication) analytics := ux.NewTestAnalytics(c) - service := snyk.NewAuthenticationService(c, nil, analytics, error_reporting.NewTestErrorReporter(), + service := NewAuthenticationService(c, nil, analytics, error_reporting.NewTestErrorReporter(), notification.NewNotifier()) oauthCred := oauth2.Token{ AccessToken: t.Name(), @@ -84,8 +78,10 @@ func Test_IsAuthenticated(t *testing.T) { c := testutil.UnitTest(t) analytics := ux.NewTestAnalytics(c) - service := snyk.NewAuthenticationService(c, - &snyk.FakeAuthenticationProvider{IsAuthenticated: true, C: c}, + provider := FakeAuthenticationProvider{IsAuthenticated: true, C: c} + providers := []AuthenticationProvider{&provider} + service := NewAuthenticationService(c, + providers, analytics, error_reporting.NewTestErrorReporter(), notification.NewNotifier(), @@ -100,9 +96,11 @@ func Test_IsAuthenticated(t *testing.T) { t.Run("User is not authenticated", func(t *testing.T) { c := testutil.UnitTest(t) analytics := ux.NewTestAnalytics(c) - service := snyk.NewAuthenticationService( + provider := FakeAuthenticationProvider{IsAuthenticated: false, C: c} + providers := []AuthenticationProvider{&provider} + service := NewAuthenticationService( c, - &snyk.FakeAuthenticationProvider{IsAuthenticated: false, C: c}, + providers, analytics, error_reporting.NewTestErrorReporter(), notification.NewNotifier(), @@ -117,41 +115,63 @@ func Test_IsAuthenticated(t *testing.T) { func Test_Logout(t *testing.T) { c := testutil.IntegTest(t) - - // arrange - // set up workspace - notifier := notification.NewNotifier() - analytics := ux.NewTestAnalytics(c) - authProvider := snyk.FakeAuthenticationProvider{} - service := snyk.NewAuthenticationService(c, &authProvider, analytics, error_reporting.NewTestErrorReporter(), - notifier) - hoverService := hover.NewFakeHoverService() - scanner := snyk.NewTestScanner() - scanNotifier, _ := appNotification.NewScanNotifier(c, notifier) - w := workspace.New(c, performance.NewInstrumentor(), scanner, hoverService, scanNotifier, notifier) - workspace.Set(w) - f := workspace.NewFolder(c, "/testFolder", "testFikder", scanner, hoverService, scanNotifier, notifier) - w.AddFolder(f) - - // fake existing diagnostic & hover - issueFile := filepath.Join(f.Path(), "path/to/file.test") - issue := snyk.Issue{AffectedFilePath: issueFile} - scanner.AddTestIssue(issue) - f.ScanFile(context.Background(), issueFile) - - testIssue := snyk.Issue{FormattedMessage: "


"} - hovers := converter.ToHovers([]snyk.Issue{testIssue}) - - _, _ = service.Provider().Authenticate(context.Background()) - - hoverService.Channel() <- hover.DocumentHovers{ - Path: issueFile, - Hover: hovers, - } + provider := FakeAuthenticationProvider{IsAuthenticated: true} + service := NewAuthenticationService( + c, + []AuthenticationProvider{&provider}, + ux.NewTestAnalytics(c), + error_reporting.NewTestErrorReporter(), + notification.NewNotifier(), + ) // act service.Logout(context.Background()) // assert - assert.False(t, authProvider.IsAuthenticated) + assert.False(t, provider.IsAuthenticated) +} + +func TestHandleInvalidCredentials(t *testing.T) { + t.Run("should send request to client", func(t *testing.T) { + c := testutil.UnitTest(t) + analytics := ux.NewTestAnalytics(c) + errorReporter := error_reporting.NewTestErrorReporter() + notifier := notification.NewNotifier() + provider := NewFakeCliAuthenticationProvider(c) + provider.IsAuthenticated = false + providers := []AuthenticationProvider{provider} + c.SetToken("invalidCreds") + cut := NewAuthenticationService(c, providers, analytics, errorReporter, notifier).(*AuthenticationServiceImpl) + messageRequestReceived := false + tokenResetReceived := false + callback := func(params any) { + switch p := params.(type) { + case types.ShowMessageRequest: + actions := p.Actions + keys := actions.Keys() + loginAction, ok := actions.Get(keys[0]) + require.True(t, ok) + require.Equal(t, types.LoginCommand, loginAction.CommandId) + cancelAction, ok := actions.Get(keys[1]) + require.True(t, ok) + require.Empty(t, cancelAction.CommandId) + messageRequestReceived = true + case lsp.AuthenticationParams: + require.Empty(t, p.Token) + tokenResetReceived = true + } + } + go notifier.CreateListener(callback) + + cut.HandleInvalidCredentials(c) + + maxWait := time.Second * 10 + assert.Eventuallyf(t, func() bool { + return messageRequestReceived + }, maxWait, time.Millisecond, "didn't receive show message request to re-authenticate") + + assert.Eventuallyf(t, func() bool { + return tokenResetReceived + }, maxWait, time.Millisecond, "didn't receive token reset") + }) } diff --git a/domain/snyk/authentication_functions.go b/infrastructure/authentication/authentication_functions.go similarity index 78% rename from domain/snyk/authentication_functions.go rename to infrastructure/authentication/authentication_functions.go index f85cac475..54ce08373 100644 --- a/domain/snyk/authentication_functions.go +++ b/infrastructure/authentication/authentication_functions.go @@ -1,5 +1,5 @@ /* - * © 2023 Snyk Limited + * © 2023-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package snyk +package authentication import ( "encoding/json" @@ -23,11 +23,24 @@ import ( "github.com/snyk/go-application-framework/pkg/configuration" localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" - "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/internal/lsp" ) +type AuthenticationFunction func() (string, error) + +type ActiveUser struct { + Id string `json:"id"` + UserName string `json:"username,omitempty"` + Orgs []struct { + Name string `json:"name,omitempty"` + Id string `json:"id,omitempty"` + Group struct { + Name string `json:"name,omitempty"` + Id string `json:"id,omitempty"` + } `json:"group,omitempty"` + } `json:"orgs,omitempty"` +} + func AuthenticationCheck() (string, error) { user, err := GetActiveUser() if err != nil { @@ -38,15 +51,11 @@ func AuthenticationCheck() (string, error) { func GetActiveUser() (*ActiveUser, error) { c := config.CurrentConfig() + c.Logger().Debug().Str("method", "getActiveUser").Msg("checking active user") if c.Token() == "" { return nil, errors.New("no credentials found") } conf := c.Engine().GetConfiguration().Clone() - if c.AuthenticationMethod() == lsp.OAuthAuthentication { - conf.Set(configuration.FF_OAUTH_AUTH_FLOW_ENABLED, 1) - } else { - conf.Set(configuration.FF_OAUTH_AUTH_FLOW_ENABLED, 0) - } conf.Set(configuration.FLAG_EXPERIMENTAL, true) conf.Set("json", true) result, err := c.Engine().InvokeWithConfig(localworkflows.WORKFLOWID_WHOAMI, conf) diff --git a/infrastructure/cli/auth/provider.go b/infrastructure/authentication/cli_provider.go similarity index 94% rename from infrastructure/cli/auth/provider.go rename to infrastructure/authentication/cli_provider.go index 95e0b43f8..ceb93cdf6 100644 --- a/infrastructure/cli/auth/provider.go +++ b/infrastructure/authentication/cli_provider.go @@ -1,5 +1,5 @@ /* - * © 2022 Snyk Limited All rights reserved. + * © 2022-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package auth +package authentication import ( "bufio" @@ -28,9 +28,8 @@ import ( "github.com/pkg/errors" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" ) type CliAuthenticationProvider struct { @@ -39,11 +38,11 @@ type CliAuthenticationProvider struct { c *config.Config } -func (a *CliAuthenticationProvider) GetCheckAuthenticationFunction() snyk.AuthenticationFunction { - return snyk.AuthenticationCheck +func (a *CliAuthenticationProvider) GetCheckAuthenticationFunction() AuthenticationFunction { + return AuthenticationCheck } -func NewCliAuthenticationProvider(c *config.Config, errorReporter error_reporting.ErrorReporter) snyk.AuthenticationProvider { +func NewCliAuthenticationProvider(c *config.Config, errorReporter error_reporting.ErrorReporter) *CliAuthenticationProvider { return &CliAuthenticationProvider{"", errorReporter, c} } @@ -164,7 +163,7 @@ func (a *CliAuthenticationProvider) getToken(ctx context.Context) (string, error token = strings.TrimSuffix(token, "\n") if token == "" { - return "", snyk.ErrEmptyAPIToken + return "", ErrEmptyAPIToken } return token, nil diff --git a/infrastructure/cli/auth/provider_test.go b/infrastructure/authentication/cli_provider_test.go similarity index 94% rename from infrastructure/cli/auth/provider_test.go rename to infrastructure/authentication/cli_provider_test.go index 7562ea0da..a0dd0ba77 100644 --- a/infrastructure/cli/auth/provider_test.go +++ b/infrastructure/authentication/cli_provider_test.go @@ -1,5 +1,5 @@ /* - * © 2022 Snyk Limited All rights reserved. + * © 2022-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,11 @@ * limitations under the License. */ -package auth +package authentication import ( "context" + "os/exec" "testing" "github.com/snyk/snyk-ls/application/config" @@ -26,7 +27,13 @@ import ( "github.com/stretchr/testify/assert" ) -// todo: int tests for interface public methods ? +func assertCmd(t *testing.T, expectedArgs []string, actualCmd *exec.Cmd) { + t.Helper() + + actualArgs := actualCmd.Args[1:] + + assert.Equal(t, expectedArgs, actualArgs) +} func TestAuth_authCmd(t *testing.T) { c := testutil.UnitTest(t) diff --git a/infrastructure/cli/auth/initializer.go b/infrastructure/authentication/initializer.go similarity index 75% rename from infrastructure/cli/auth/initializer.go rename to infrastructure/authentication/initializer.go index 17db5b167..005395136 100644 --- a/infrastructure/cli/auth/initializer.go +++ b/infrastructure/authentication/initializer.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package auth +package authentication import ( "context" @@ -24,15 +24,13 @@ import ( sglsp "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/ide/command" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/ux" - "github.com/snyk/snyk-ls/domain/snyk" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/ux" ) type Initializer struct { - authenticationService snyk.AuthenticationService + authenticationService AuthenticationService errorReporter error_reporting.ErrorReporter analytics ux.Analytics notifier noti.Notifier @@ -40,7 +38,7 @@ type Initializer struct { c *config.Config } -func NewInitializer(c *config.Config, authenticator snyk.AuthenticationService, errorReporter error_reporting.ErrorReporter, analytics ux.Analytics, notifier noti.Notifier) *Initializer { +func NewInitializer(c *config.Config, authenticator AuthenticationService, errorReporter error_reporting.ErrorReporter, analytics ux.Analytics, notifier noti.Notifier) *Initializer { return &Initializer{ authenticationService: authenticator, errorReporter: errorReporter, @@ -56,14 +54,12 @@ func (i *Initializer) Init() error { const errorMessage = "Auth Initializer failed to authenticate." c := config.CurrentConfig() if c.NonEmptyToken() { - cmd, _ := command.CreateFromCommandData(c, snyk.CommandData{CommandId: snyk.GetActiveUserCommand}, nil, i.authenticationService, nil, i.notifier, nil, nil, nil) - user, _ := cmd.Execute(context.Background()) - if user != nil { + authenticated, err := i.authenticationService.IsAuthenticated() + if authenticated { c.Logger().Info().Str("method", "auth.initializer.init").Msg("Skipping authentication - user is already authenticated") return nil } - - return nil + return err } // token is empty from here on @@ -86,13 +82,13 @@ func (i *Initializer) Init() error { return nil } -func (i *Initializer) authenticate(authenticationService snyk.AuthenticationService, errorMessage string) error { +func (i *Initializer) authenticate(authenticationService AuthenticationService, errorMessage string) error { i.notifier.SendShowMessage(sglsp.Info, "Authenticating to Snyk. This could open a browser window.") token, err := authenticationService.Authenticate(context.Background()) if token == "" || err != nil { if err == nil { - err = &snyk.AuthenticationFailedError{} + err = &AuthenticationFailedError{} } i.notifier.SendError(err) err = errors.Wrap(err, errorMessage) diff --git a/infrastructure/cli/auth/initializer_test.go b/infrastructure/authentication/initializer_test.go similarity index 80% rename from infrastructure/cli/auth/initializer_test.go rename to infrastructure/authentication/initializer_test.go index 23ff6eab3..6048f86e5 100644 --- a/infrastructure/cli/auth/initializer_test.go +++ b/infrastructure/authentication/initializer_test.go @@ -1,5 +1,5 @@ /* - * © 2022-2023 Snyk Limited + * © 2022-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package auth +package authentication import ( "testing" @@ -22,10 +22,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - errorreporting "github.com/snyk/snyk-ls/domain/observability/error_reporting" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/notification" + errorreporting "github.com/snyk/snyk-ls/internal/observability/error_reporting" + ux2 "github.com/snyk/snyk-ls/internal/observability/ux" ) func Test_autoAuthenticationDisabled_doesNotAuthenticate(t *testing.T) { @@ -41,9 +40,10 @@ func getAutoAuthenticationTest(autoAuthentication bool, expectError bool) func(t c.SetAutomaticAuthentication(autoAuthentication) analytics := ux2.NewTestAnalytics(c) - provider := snyk.NewFakeCliAuthenticationProvider(c) + provider := NewFakeCliAuthenticationProvider(c) + providers := []AuthenticationProvider{provider} notifier := notification.NewNotifier() - authenticator := snyk.NewAuthenticationService(c, provider, analytics, errorreporting.NewTestErrorReporter(), notifier) + authenticator := NewAuthenticationService(c, providers, analytics, errorreporting.NewTestErrorReporter(), notifier) initializer := NewInitializer(c, authenticator, errorreporting.NewTestErrorReporter(), analytics, notifier) // Act diff --git a/infrastructure/oauth/oauth_provider.go b/infrastructure/authentication/oauth_provider.go similarity index 65% rename from infrastructure/oauth/oauth_provider.go rename to infrastructure/authentication/oauth_provider.go index 9836d82ff..5fe3d0afc 100644 --- a/infrastructure/oauth/oauth_provider.go +++ b/infrastructure/authentication/oauth_provider.go @@ -14,45 +14,44 @@ * limitations under the License. */ -package oauth +package authentication import ( "context" "github.com/rs/zerolog" + "github.com/snyk/go-application-framework/pkg/auth" "github.com/snyk/go-application-framework/pkg/configuration" - - "github.com/snyk/snyk-ls/domain/snyk" ) -type oAuthProvider struct { +type OAuth2Provider struct { authenticator auth.Authenticator config configuration.Configuration authURL string logger *zerolog.Logger } -func (p *oAuthProvider) GetCheckAuthenticationFunction() snyk.AuthenticationFunction { - return snyk.AuthenticationCheck +func (p *OAuth2Provider) GetCheckAuthenticationFunction() AuthenticationFunction { + return AuthenticationCheck } -func NewOAuthProvider(config configuration.Configuration, authenticator auth.Authenticator, logger *zerolog.Logger) snyk.AuthenticationProvider { +func newOAuthProvider(config configuration.Configuration, authenticator auth.Authenticator, logger *zerolog.Logger) *OAuth2Provider { logger.Debug().Msg("creating new OAuth provider") - return &oAuthProvider{authenticator: authenticator, config: config, logger: logger} + return &OAuth2Provider{authenticator: authenticator, config: config, logger: logger} } -func (p *oAuthProvider) Authenticate(_ context.Context) (string, error) { +func (p *OAuth2Provider) Authenticate(_ context.Context) (string, error) { err := p.authenticator.Authenticate() p.logger.Debug().Msg("authenticated with OAuth") return p.config.GetString(auth.CONFIG_KEY_OAUTH_TOKEN), err } -func (p *oAuthProvider) SetAuthURL(url string) { +func (p *OAuth2Provider) SetAuthURL(url string) { p.authURL = url } -func (p *oAuthProvider) ClearAuthentication(_ context.Context) error { +func (p *OAuth2Provider) ClearAuthentication(_ context.Context) error { p.logger.Debug().Msg("clearing authentication") p.config.Set(auth.CONFIG_KEY_OAUTH_TOKEN, "") p.config.Set(configuration.AUTHENTICATION_TOKEN, "") @@ -60,10 +59,10 @@ func (p *oAuthProvider) ClearAuthentication(_ context.Context) error { return nil } -func (p *oAuthProvider) AuthURL(_ context.Context) string { +func (p *OAuth2Provider) AuthURL(_ context.Context) string { return p.authURL } -func (p *oAuthProvider) Authenticator() auth.Authenticator { +func (p *OAuth2Provider) Authenticator() auth.Authenticator { return p.authenticator } diff --git a/infrastructure/oauth/oauth_provider_test.go b/infrastructure/authentication/oauth_provider_test.go similarity index 95% rename from infrastructure/oauth/oauth_provider_test.go rename to infrastructure/authentication/oauth_provider_test.go index dc3f6fdaf..b7506812b 100644 --- a/infrastructure/oauth/oauth_provider_test.go +++ b/infrastructure/authentication/oauth_provider_test.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package oauth +package authentication import ( "context" @@ -111,7 +111,7 @@ func TestAuthenticateUsesAuthenticator(t *testing.T) { config := configuration.New() authenticator := NewFakeOauthAuthenticator(defaultExpiry, true, config).(*fakeOauthAuthenticator) - provider := NewOAuthProvider(config, authenticator, config2.CurrentConfig().Logger()) + provider := newOAuthProvider(config, authenticator, config2.CurrentConfig().Logger()) authToken, err := provider.Authenticate(context.Background()) @@ -123,7 +123,7 @@ func TestAuthenticateUsesAuthenticator(t *testing.T) { func TestAuthURL_ShouldReturnURL(t *testing.T) { config := configuration.New() authenticator := NewFakeOauthAuthenticator(time.Now().Add(10*time.Second), true, config).(*fakeOauthAuthenticator) - provider := NewOAuthProvider(config, authenticator, config2.CurrentConfig().Logger()) + provider := newOAuthProvider(config, authenticator, config2.CurrentConfig().Logger()) provider.SetAuthURL("https://auth.fake.snyk.io") url := provider.AuthURL(context.Background()) diff --git a/domain/snyk/provider_fake.go b/infrastructure/authentication/provider_fake.go similarity index 97% rename from domain/snyk/provider_fake.go rename to infrastructure/authentication/provider_fake.go index fa0189a39..052dc34cd 100644 --- a/domain/snyk/provider_fake.go +++ b/infrastructure/authentication/provider_fake.go @@ -1,5 +1,5 @@ /* - * © 2022-2023 Snyk Limited + * © 2022-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package snyk +package authentication import ( "context" diff --git a/infrastructure/cli/auth/cmd_test.go b/infrastructure/cli/auth/cmd_test.go deleted file mode 100644 index 55204a316..000000000 --- a/infrastructure/cli/auth/cmd_test.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - * © 2022 Snyk Limited All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package auth - -import ( - "os/exec" - "testing" - - "github.com/stretchr/testify/assert" -) - -func assertCmd(t *testing.T, expectedArgs []string, actualCmd *exec.Cmd) { - t.Helper() - - actualArgs := actualCmd.Args[1:] - - assert.Equal(t, expectedArgs, actualArgs) -} diff --git a/infrastructure/cli/cli.go b/infrastructure/cli/cli.go index f2b1737b5..516fc0571 100644 --- a/infrastructure/cli/cli.go +++ b/infrastructure/cli/cli.go @@ -27,29 +27,26 @@ import ( "github.com/rs/zerolog" "github.com/snyk/snyk-ls/application/config" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/ux" - "github.com/snyk/snyk-ls/domain/snyk" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/ux" ) type SnykCli struct { - authenticationService snyk.AuthenticationService - errorReporter error_reporting.ErrorReporter - analytics ux.Analytics - semaphore chan int - cliTimeout time.Duration - notifier noti.Notifier - c *config.Config + errorReporter error_reporting.ErrorReporter + analytics ux.Analytics + semaphore chan int + cliTimeout time.Duration + notifier noti.Notifier + c *config.Config } var Mutex = &sync.Mutex{} -func NewExecutor(c *config.Config, authenticationService snyk.AuthenticationService, errorReporter error_reporting.ErrorReporter, analytics ux.Analytics, notifier noti.Notifier) Executor { +func NewExecutor(c *config.Config, errorReporter error_reporting.ErrorReporter, analytics ux.Analytics, notifier noti.Notifier) Executor { concurrencyLimit := 2 return &SnykCli{ - authenticationService, errorReporter, analytics, make(chan int, concurrencyLimit), @@ -98,7 +95,7 @@ func (c SnykCli) getCommand(cmd []string, workingDir string, ctx context.Context } command := exec.CommandContext(ctx, cmd[0], cmd[1:]...) command.Dir = workingDir - cliEnv := AppendCliEnvironmentVariables(os.Environ(), true) + cliEnv := AppendCliEnvironmentVariables(os.Environ(), c.c.NonEmptyToken()) command.Env = cliEnv c.c.Logger().Trace().Str("method", "getCommand").Interface("command.Args", command.Args).Send() c.c.Logger().Trace().Str("method", "getCommand").Interface("command.Env", command.Env).Send() diff --git a/infrastructure/cli/cli_extension_executor_test.go b/infrastructure/cli/cli_extension_executor_test.go index 0db750f82..4f4af06b7 100644 --- a/infrastructure/cli/cli_extension_executor_test.go +++ b/infrastructure/cli/cli_extension_executor_test.go @@ -22,11 +22,12 @@ import ( "github.com/snyk/snyk-ls/internal/testutil" + "github.com/spf13/pflag" + "github.com/stretchr/testify/assert" + "github.com/snyk/go-application-framework/pkg/app" "github.com/snyk/go-application-framework/pkg/configuration" "github.com/snyk/go-application-framework/pkg/workflow" - "github.com/spf13/pflag" - "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" ) diff --git a/infrastructure/cli/environment.go b/infrastructure/cli/environment.go index 35f3cf37f..c2f0ccb95 100644 --- a/infrastructure/cli/environment.go +++ b/infrastructure/cli/environment.go @@ -25,7 +25,6 @@ import ( "github.com/snyk/go-application-framework/pkg/configuration" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/internal/lsp" ) const ( @@ -46,6 +45,7 @@ const ( func AppendCliEnvironmentVariables(currentEnv []string, appendToken bool) []string { var updatedEnv []string currentConfig := config.CurrentConfig() + logger := currentConfig.Logger().With().Str("method", "AppendCliEnvironmentVariables").Logger() // remove any existing env vars that we are going to set valuesToRemove := map[string]bool{ @@ -65,21 +65,25 @@ func AppendCliEnvironmentVariables(currentEnv []string, appendToken bool) []stri updatedEnv = append(updatedEnv, s) } - if appendToken { - // there can only be one - highlander principle - if currentConfig.AuthenticationMethod() == lsp.OAuthAuthentication { - oAuthToken, err := currentConfig.TokenAsOAuthToken() - if err == nil && len(oAuthToken.AccessToken) > 0 { - updatedEnv = append(updatedEnv, SnykOauthTokenEnvVar+"="+oAuthToken.AccessToken) - } + if appendToken && currentConfig.NonEmptyToken() { + // default to authentication, if not there, try to set the api key + oAuthToken, err := currentConfig.TokenAsOAuthToken() + if err == nil && len(oAuthToken.AccessToken) > 0 { + logger.Debug().Msg("using oauth2 authentication") + updatedEnv = append(updatedEnv, SnykOauthTokenEnvVar+"="+oAuthToken.AccessToken) } else { + // fallback to token if existent + logger.Debug().Msg("falling back to API key authentication") updatedEnv = append(updatedEnv, TokenEnvVar+"="+currentConfig.Token()) } } + if currentConfig.SnykApi() != "" { + logger.Debug().Msgf("adding endpoint: %s", currentConfig.SnykApi()) updatedEnv = append(updatedEnv, ApiEnvVar+"="+currentConfig.SnykApi()) } if !currentConfig.IsTelemetryEnabled() || !currentConfig.IsAnalyticsPermitted() { + logger.Debug().Msgf("disabling amplitude") updatedEnv = append(updatedEnv, DisableAnalyticsEnvVar+"=1") } @@ -91,6 +95,7 @@ func AppendCliEnvironmentVariables(currentEnv []string, appendToken bool) []stri } if currentConfig.Logger().GetLevel() == zerolog.TraceLevel { + logger.Trace().Msgf("setting log-level to trace") updatedEnv = append(updatedEnv, "SNYK_LOG_LEVEL=trace") } diff --git a/infrastructure/cli/environment_test.go b/infrastructure/cli/environment_test.go index 8e3d86627..a36e9aedc 100644 --- a/infrastructure/cli/environment_test.go +++ b/infrastructure/cli/environment_test.go @@ -17,9 +17,13 @@ package cli import ( + "encoding/json" "testing" + "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/oauth2" "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/lsp" @@ -27,6 +31,17 @@ import ( ) func TestAddConfigValuesToEnv(t *testing.T) { + t.Run("Adds legacy token to env", func(t *testing.T) { + testutil.UnitTest(t) + c := config.CurrentConfig() + c.SetAuthenticationMethod(lsp.TokenAuthentication) + + updatedEnv := AppendCliEnvironmentVariables([]string{}, true) + + token := c.Token() + assert.Contains(t, updatedEnv, TokenEnvVar+"="+token) + }) + t.Run("Adds values to env", func(t *testing.T) { const expectedIntegrationName = "ECLIPSE" const expectedIntegrationVersion = "20230606.182718" @@ -41,11 +56,22 @@ func TestAddConfigValuesToEnv(t *testing.T) { c.SetIntegrationVersion(expectedIntegrationVersion) c.SetIdeVersion(expectedIdeVersion) c.SetIdeName(expectedIdeName) + s := oauth2.Token{ + AccessToken: "test", + TokenType: "test", + RefreshToken: "test", + Expiry: time.Time{}, + } + marshal, err := json.Marshal(s) + require.NoError(t, err) + c.SetToken(string(marshal)) updatedEnv := AppendCliEnvironmentVariables([]string{}, true) assert.Contains(t, updatedEnv, ApiEnvVar+"=https://app.snyk.io/api") - assert.Contains(t, updatedEnv, TokenEnvVar+"="+c.Token()) + token, err := c.TokenAsOAuthToken() + require.NoError(t, err) + assert.Contains(t, updatedEnv, SnykOauthTokenEnvVar+"="+token.AccessToken) assert.Contains(t, updatedEnv, IntegrationNameEnvVarKey+"="+expectedIntegrationName) assert.Contains(t, updatedEnv, IntegrationVersionEnvVarKey+"="+expectedIntegrationVersion) assert.Contains(t, updatedEnv, IntegrationEnvironmentEnvVarKey+"="+expectedIdeName) @@ -55,7 +81,6 @@ func TestAddConfigValuesToEnv(t *testing.T) { t.Run("Removes existing snyk token env variables", func(t *testing.T) { testutil.UnitTest(t) c := config.CurrentConfig() - c.SetAuthenticationMethod(lsp.OAuthAuthentication) c.SetToken("{\"access_token\": \"testToken\"}") tokenVar := TokenEnvVar + "={asdf}" inputEnv := []string{tokenVar} @@ -67,10 +92,9 @@ func TestAddConfigValuesToEnv(t *testing.T) { assert.Contains(t, updatedEnv, SnykOauthTokenEnvVar+"="+token.AccessToken) assert.NotContains(t, updatedEnv, tokenVar) }) - t.Run("Removes existing oauth env variables", func(t *testing.T) { + t.Run("Removes existing authentication env variables", func(t *testing.T) { testutil.UnitTest(t) c := config.CurrentConfig() - c.SetAuthenticationMethod(lsp.TokenAuthentication) c.SetToken("testToken") oauthVar := SnykOauthTokenEnvVar + "={asdf}" inputEnv := []string{oauthVar} @@ -83,7 +107,6 @@ func TestAddConfigValuesToEnv(t *testing.T) { t.Run("Adds Snyk Token to env", func(t *testing.T) { testutil.UnitTest(t) c := config.CurrentConfig() - c.SetAuthenticationMethod(lsp.TokenAuthentication) c.SetToken("testToken") updatedEnv := AppendCliEnvironmentVariables([]string{}, true) @@ -94,7 +117,6 @@ func TestAddConfigValuesToEnv(t *testing.T) { t.Run("Adds OAuth Token to env", func(t *testing.T) { testutil.UnitTest(t) c := config.CurrentConfig() - c.SetAuthenticationMethod(lsp.OAuthAuthentication) c.SetToken("{\"access_token\": \"testToken\"}") updatedEnv := AppendCliEnvironmentVariables([]string{}, true) diff --git a/infrastructure/cli/initializer.go b/infrastructure/cli/initializer.go index 02b36d320..ba59e343a 100644 --- a/infrastructure/cli/initializer.go +++ b/infrastructure/cli/initializer.go @@ -27,10 +27,10 @@ import ( sglsp "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" "github.com/snyk/snyk-ls/infrastructure/cli/install" "github.com/snyk/snyk-ls/internal/lsp" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" ) type Initializer struct { diff --git a/infrastructure/cli/initializer_test.go b/infrastructure/cli/initializer_test.go index 16b5882aa..4d74a7cbc 100644 --- a/infrastructure/cli/initializer_test.go +++ b/infrastructure/cli/initializer_test.go @@ -26,10 +26,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" "github.com/snyk/snyk-ls/infrastructure/cli/filename" "github.com/snyk/snyk-ls/infrastructure/cli/install" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/cli/install/downloader.go b/infrastructure/cli/install/downloader.go index 9621fe92b..dcaa23290 100644 --- a/infrastructure/cli/install/downloader.go +++ b/infrastructure/cli/install/downloader.go @@ -26,7 +26,7 @@ import ( "github.com/pkg/errors" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/internal/progress" ) diff --git a/infrastructure/cli/install/installer.go b/infrastructure/cli/install/installer.go index 52cb0e515..e43df9870 100644 --- a/infrastructure/cli/install/installer.go +++ b/infrastructure/cli/install/installer.go @@ -29,7 +29,7 @@ import ( "time" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" ) type Installer interface { diff --git a/infrastructure/cli/install/installer_test.go b/infrastructure/cli/install/installer_test.go index 2639181c1..b68080ddf 100644 --- a/infrastructure/cli/install/installer_test.go +++ b/infrastructure/cli/install/installer_test.go @@ -28,7 +28,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/code/bundle.go b/infrastructure/code/bundle.go index be01575c6..efad580b8 100644 --- a/infrastructure/code/bundle.go +++ b/infrastructure/code/bundle.go @@ -24,6 +24,7 @@ import ( "time" "github.com/rs/zerolog" + codeClientObservability "github.com/snyk/code-client-go/observability" "github.com/snyk/snyk-ls/application/config" diff --git a/infrastructure/code/bundle_uploader.go b/infrastructure/code/bundle_uploader.go index 35cd593e5..2f01be178 100644 --- a/infrastructure/code/bundle_uploader.go +++ b/infrastructure/code/bundle_uploader.go @@ -22,6 +22,7 @@ import ( "path/filepath" "github.com/puzpuzpuz/xsync" + codeClientObservability "github.com/snyk/code-client-go/observability" "github.com/snyk/snyk-ls/application/config" diff --git a/infrastructure/code/code.go b/infrastructure/code/code.go index 3a34e776e..c7f400947 100644 --- a/infrastructure/code/code.go +++ b/infrastructure/code/code.go @@ -25,18 +25,20 @@ import ( "github.com/erni27/imcache" "github.com/pkg/errors" "github.com/puzpuzpuz/xsync" + codeClient "github.com/snyk/code-client-go" codeClientObservability "github.com/snyk/code-client-go/observability" "github.com/snyk/code-client-go/scan" + "github.com/snyk/snyk-ls/internal/observability/ux" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/ide/notification" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/filefilter" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/float" + "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/progress" "github.com/snyk/snyk-ls/internal/uri" @@ -65,7 +67,7 @@ type Scanner struct { BundleUploader *BundleUploader SnykApiClient snyk_api.SnykApiClient errorReporter codeClientObservability.ErrorReporter - analytics ux2.Analytics + analytics ux.Analytics changedFilesMutex sync.Mutex scanStatusMutex sync.Mutex runningScans map[string]*ScanStatus @@ -89,7 +91,7 @@ type Scanner struct { func New(bundleUploader *BundleUploader, apiClient snyk_api.SnykApiClient, reporter codeClientObservability.ErrorReporter, - analytics ux2.Analytics, + analytics ux.Analytics, learnService learn.Service, notifier notification.Notifier, codeScanner codeClient.CodeScanner, @@ -124,8 +126,8 @@ func (sc *Scanner) Product() product.Product { return product.ProductCode } -func (sc *Scanner) SupportedCommands() []snyk.CommandName { - return []snyk.CommandName{snyk.NavigateToRangeCommand} +func (sc *Scanner) SupportedCommands() []types.CommandName { + return []types.CommandName{types.NavigateToRangeCommand} } func (sc *Scanner) Scan(ctx context.Context, path string, folderPath string) (issues []snyk.Issue, err error) { @@ -540,17 +542,17 @@ type ScanMetrics struct { } func (sc *Scanner) trackResult(success bool, scanMetrics *ScanMetrics) { - var result ux2.Result + var result ux.Result if success { - result = ux2.Success + result = ux.Success } else { - result = ux2.Error + result = ux.Error } duration := time.Since(scanMetrics.lastScanStartTime) scanMetrics.lastScanDurationInSeconds = float.ToFixed(duration.Seconds(), 2) sc.analytics.AnalysisIsReady( - ux2.AnalysisIsReadyProperties{ - AnalysisType: ux2.CodeSecurity, + ux.AnalysisIsReadyProperties{ + AnalysisType: ux.CodeSecurity, Result: result, FileCount: scanMetrics.lastScanFileCount, DurationInSeconds: scanMetrics.lastScanDurationInSeconds, diff --git a/infrastructure/code/code_error_reporter.go b/infrastructure/code/code_error_reporter.go index f633d90b5..95d75565e 100644 --- a/infrastructure/code/code_error_reporter.go +++ b/infrastructure/code/code_error_reporter.go @@ -18,8 +18,7 @@ package code import ( codeClient "github.com/snyk/code-client-go/observability" - - "github.com/snyk/snyk-ls/domain/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" ) // A Sentry implementation of our error reporter that respects user preferences regarding tracking diff --git a/infrastructure/code/code_instrumentor.go b/infrastructure/code/code_instrumentor.go index 7392b6e60..ed3f3b889 100644 --- a/infrastructure/code/code_instrumentor.go +++ b/infrastructure/code/code_instrumentor.go @@ -21,8 +21,7 @@ import ( "sync" codeClient "github.com/snyk/code-client-go/observability" - - "github.com/snyk/snyk-ls/domain/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/performance" ) type spanRecorderCodeImpl struct { diff --git a/infrastructure/code/code_test.go b/infrastructure/code/code_test.go index 0d855719f..130228a76 100644 --- a/infrastructure/code/code_test.go +++ b/infrastructure/code/code_test.go @@ -33,12 +33,12 @@ import ( "github.com/stretchr/testify/require" "github.com/snyk/snyk-ls/application/config" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/infrastructure/learn/mock_learn" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/uri" "github.com/snyk/snyk-ls/internal/util" @@ -174,7 +174,7 @@ func TestCreateBundle(t *testing.T) { NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), nil, notification.NewNotifier(), &FakeCodeScannerClient{}, @@ -263,7 +263,7 @@ func setupTestScanner(t *testing.T) (*FakeSnykCodeClient, *Scanner) { NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), learnMock, notification.NewNotifier(), &FakeCodeScannerClient{}, @@ -286,7 +286,7 @@ func TestUploadAndAnalyze(t *testing.T) { NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), learnMock, notification.NewNotifier(), &FakeCodeScannerClient{}, @@ -316,7 +316,7 @@ func TestUploadAndAnalyze(t *testing.T) { NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), learnMock, notification.NewNotifier(), &FakeCodeScannerClient{}, @@ -352,7 +352,7 @@ func TestUploadAndAnalyze(t *testing.T) { t.Run( "should track analytics", func(t *testing.T) { snykCodeMock := &FakeSnykCodeClient{C: c} - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) c := New( NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, @@ -372,9 +372,9 @@ func TestUploadAndAnalyze(t *testing.T) { assert.Len(t, analytics.GetAnalytics(), 1) assert.Equal( - t, ux2.AnalysisIsReadyProperties{ - AnalysisType: ux2.CodeSecurity, - Result: ux2.Success, + t, ux.AnalysisIsReadyProperties{ + AnalysisType: ux.CodeSecurity, + Result: ux.Success, FileCount: metrics.lastScanFileCount, DurationInSeconds: metrics.lastScanDurationInSeconds, }, analytics.GetAnalytics()[0], @@ -403,7 +403,7 @@ func TestUploadAndAnalyzeWithIgnores(t *testing.T) { &snyk_api.FakeApiClient{CodeEnabled: true}, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), learnMock, notification.NewNotifier(), fakeCodeScanner, @@ -571,7 +571,7 @@ func Test_Scan(t *testing.T) { NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: false}, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), nil, notification.NewNotifier(), &FakeCodeScannerClient{}, @@ -600,7 +600,7 @@ func Test_Scan(t *testing.T) { NewBundler(c, snykCodeMock, NewCodeInstrumentor()), snykApiMock, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), learnMock, notification.NewNotifier(), &FakeCodeScannerClient{}, @@ -629,7 +629,7 @@ func Test_Scan(t *testing.T) { NewBundler(c, snykCodeMock, NewCodeInstrumentor()), snykApiMock, newTestCodeErrorReporter(), - ux2.NewTestAnalytics(c), + ux.NewTestAnalytics(c), learnMock, notification.NewNotifier(), &FakeCodeScannerClient{}, @@ -791,7 +791,7 @@ func TestUploadAnalyzeWithAutofix(t *testing.T) { autofixSetupAndCleanup(t) snykCodeMock := &FakeSnykCodeClient{C: c} - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := New( NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, @@ -829,7 +829,7 @@ func TestUploadAnalyzeWithAutofix(t *testing.T) { snykCodeMock := &FakeSnykCodeClient{C: c} snykCodeMock.NoFixSuggestions = true - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := New( NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, @@ -864,7 +864,7 @@ func TestUploadAnalyzeWithAutofix(t *testing.T) { getCodeSettings().isAutofixEnabled.Set(true) snykCodeMock := &FakeSnykCodeClient{C: c} - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := New( NewBundler(c, snykCodeMock, NewCodeInstrumentor()), &snyk_api.FakeApiClient{CodeEnabled: true}, diff --git a/infrastructure/code/code_tracker.go b/infrastructure/code/code_tracker.go index 4d5e43d3c..d23a7ee48 100644 --- a/infrastructure/code/code_tracker.go +++ b/infrastructure/code/code_tracker.go @@ -19,6 +19,7 @@ package code import ( "github.com/google/uuid" "github.com/rs/zerolog/log" + codeClientScan "github.com/snyk/code-client-go/scan" "github.com/snyk/snyk-ls/internal/lsp" diff --git a/infrastructure/code/fake_snyk_code_api_service.go b/infrastructure/code/fake_snyk_code_api_service.go index bf4ecae91..bb8d64c37 100644 --- a/infrastructure/code/fake_snyk_code_api_service.go +++ b/infrastructure/code/fake_snyk_code_api_service.go @@ -32,6 +32,7 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/internal/product" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/util" ) @@ -59,14 +60,14 @@ var ( Character: 7, }, } - FakeCommand = snyk.CommandData{ + FakeCommand = types.CommandData{ Title: "Code Flow blah blah fake", - CommandId: snyk.NavigateToRangeCommand, + CommandId: types.NavigateToRangeCommand, Arguments: []any{"path", fakeRange}, } - FakeFixCommand = snyk.CommandData{ + FakeFixCommand = types.CommandData{ Title: "Code Flow blah blah fake", - CommandId: snyk.CodeFixCommand, + CommandId: types.CodeFixCommand, Arguments: []any{"id", "path", fakeRange}, } @@ -77,7 +78,7 @@ var ( Product: product.ProductCode, IssueType: snyk.CodeQualityIssue, Message: "This is a dummy error (severity error)", - CodelensCommands: []snyk.CommandData{FakeCommand, FakeFixCommand}, + CodelensCommands: []types.CommandData{FakeCommand, FakeFixCommand}, CodeActions: []snyk.CodeAction{FakeCodeAction}, AdditionalData: snyk.CodeIssueData{ Key: uuid.New().String(), diff --git a/infrastructure/code/issue_enhancer.go b/infrastructure/code/issue_enhancer.go index e66aba526..bf94cc3f8 100644 --- a/infrastructure/code/issue_enhancer.go +++ b/infrastructure/code/issue_enhancer.go @@ -24,13 +24,15 @@ import ( "time" codeClientObservability "github.com/snyk/code-client-go/observability" + "github.com/snyk/snyk-ls/internal/types" + sglsp "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/internal/data_structure" + "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/progress" "github.com/snyk/snyk-ls/internal/util" ) @@ -96,9 +98,9 @@ func (b *IssueEnhancer) addIssueActions(ctx context.Context, issues []snyk.Issue issues[i].CodeActions = append(issues[i].CodeActions, codeAction) codeActionId := *codeAction.Uuid - issues[i].CodelensCommands = append(issues[i].CodelensCommands, snyk.CommandData{ + issues[i].CodelensCommands = append(issues[i].CodelensCommands, types.CommandData{ Title: "⚡ Fix this issue: " + issueTitle(issues[i]), - CommandId: snyk.CodeFixCommand, + CommandId: types.CodeFixCommand, Arguments: []any{ codeActionId, issues[i].AffectedFilePath, @@ -221,9 +223,9 @@ func (b *IssueEnhancer) autofixFunc(ctx context.Context, issue snyk.Issue, } else { // sleep to give client side to actually apply & review the fix time.Sleep(2 * time.Second) - b.notifier.Send(snyk.ShowMessageRequest{ + b.notifier.Send(types.ShowMessageRequest{ Message: successMessage + " Was this fix helpful?", - Type: snyk.Info, + Type: types.Info, Actions: actionCommandMap, }) } @@ -247,15 +249,15 @@ func ToEncodedNormalizedPath(rootPath string, filePath string) (string, error) { return encodedRelativePath, nil } -func (b *IssueEnhancer) autofixFeedbackActions(fixId string) (*data_structure.OrderedMap[snyk.MessageAction, snyk.CommandData], error) { - createCommandData := func(positive bool) snyk.CommandData { - return snyk.CommandData{ - Title: snyk.CodeSubmitFixFeedback, - CommandId: snyk.CodeSubmitFixFeedback, +func (b *IssueEnhancer) autofixFeedbackActions(fixId string) (*data_structure.OrderedMap[types.MessageAction, types.CommandData], error) { + createCommandData := func(positive bool) types.CommandData { + return types.CommandData{ + Title: types.CodeSubmitFixFeedback, + CommandId: types.CodeSubmitFixFeedback, Arguments: []any{fixId, positive}, } } - actionCommandMap := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() + actionCommandMap := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() positiveFeedbackCmd := createCommandData(true) negativeFeedbackCmd := createCommandData(false) @@ -277,9 +279,9 @@ func (b *IssueEnhancer) createOpenSnykLearnCodeAction(issue snyk.Issue) (ca *sny if lesson != nil && lesson.Url != "" { ca = &snyk.CodeAction{ Title: title, - Command: &snyk.CommandData{ + Command: &types.CommandData{ Title: title, - CommandId: snyk.OpenBrowserCommand, + CommandId: types.OpenBrowserCommand, Arguments: []any{lesson.Url}, }, } diff --git a/infrastructure/code/issue_enhancer_test.go b/infrastructure/code/issue_enhancer_test.go index 285d6bdfe..196966af5 100644 --- a/infrastructure/code/issue_enhancer_test.go +++ b/infrastructure/code/issue_enhancer_test.go @@ -31,6 +31,7 @@ import ( "github.com/snyk/snyk-ls/internal/data_structure" "github.com/snyk/snyk-ls/internal/notification" "github.com/snyk/snyk-ls/internal/product" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/util" ) @@ -86,36 +87,36 @@ func Test_autofixFunc(t *testing.T) { t.Run("Shows success message when fix provided", func(t *testing.T) { fn := issueEnhancer.autofixFunc(context.Background(), FakeIssue, bundleHash) fn() - var feedbackMessageReq snyk.ShowMessageRequest + var feedbackMessageReq types.ShowMessageRequest assert.Eventually(t, func() bool { messages := mockNotifier.SentMessages() if messages == nil || len(messages) < 2 { return false } for _, message := range messages { - if _, ok := message.(snyk.ShowMessageRequest); ok { - feedbackMessageReq = message.(snyk.ShowMessageRequest) + if _, ok := message.(types.ShowMessageRequest); ok { + feedbackMessageReq = message.(types.ShowMessageRequest) break } } - return snyk.Info == feedbackMessageReq.Type && + return types.Info == feedbackMessageReq.Type && "Congratulations! 🎉 You’ve just fixed this SNYK-123 issue. Was this fix helpful?" == feedbackMessageReq.Message }, 10*time.Second, 1*time.Second) // Compare button action commands - actionCommandMap := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() - commandData1 := snyk.CommandData{ - Title: snyk.CodeSubmitFixFeedback, - CommandId: snyk.CodeSubmitFixFeedback, + actionCommandMap := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() + commandData1 := types.CommandData{ + Title: types.CodeSubmitFixFeedback, + CommandId: types.CodeSubmitFixFeedback, Arguments: []any{"123e4567-e89b-12d3-a456-426614174000/1", true}, } - commandData2 := snyk.CommandData{ - Title: snyk.CodeSubmitFixFeedback, - CommandId: snyk.CodeSubmitFixFeedback, + commandData2 := types.CommandData{ + Title: types.CodeSubmitFixFeedback, + CommandId: types.CodeSubmitFixFeedback, Arguments: []any{"123e4567-e89b-12d3-a456-426614174000/1", false}, } - positiveFeedback := snyk.MessageAction("👍") - negativeFeedback := snyk.MessageAction("👎") + positiveFeedback := types.MessageAction("👍") + negativeFeedback := types.MessageAction("👎") actionCommandMap.Add(positiveFeedback, commandData1) actionCommandMap.Add(negativeFeedback, commandData2) @@ -134,36 +135,36 @@ func Test_autofixFunc(t *testing.T) { fn := issueEnhancer.autofixFunc(context.Background(), fakeTestIssue, bundleHash) fn() - var feedbackMessageReq snyk.ShowMessageRequest + var feedbackMessageReq types.ShowMessageRequest assert.Eventually(t, func() bool { messages := mockNotifier.SentMessages() if messages == nil || len(messages) < 2 { return false } for _, message := range messages { - if _, ok := message.(snyk.ShowMessageRequest); ok { - feedbackMessageReq = message.(snyk.ShowMessageRequest) + if _, ok := message.(types.ShowMessageRequest); ok { + feedbackMessageReq = message.(types.ShowMessageRequest) break } } - return snyk.Info == feedbackMessageReq.Type && + return types.Info == feedbackMessageReq.Type && "Congratulations! 🎉 You’ve just fixed this SNYK-123 issue. Was this fix helpful?" == feedbackMessageReq.Message }, 10*time.Second, 1*time.Second) // Compare button action commands - actionCommandMap := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() - commandData1 := snyk.CommandData{ - Title: snyk.CodeSubmitFixFeedback, - CommandId: snyk.CodeSubmitFixFeedback, + actionCommandMap := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() + commandData1 := types.CommandData{ + Title: types.CodeSubmitFixFeedback, + CommandId: types.CodeSubmitFixFeedback, Arguments: []any{"123e4567-e89b-12d3-a456-426614174000/1", true}, } - commandData2 := snyk.CommandData{ - Title: snyk.CodeSubmitFixFeedback, - CommandId: snyk.CodeSubmitFixFeedback, + commandData2 := types.CommandData{ + Title: types.CodeSubmitFixFeedback, + CommandId: types.CodeSubmitFixFeedback, Arguments: []any{"123e4567-e89b-12d3-a456-426614174000/1", false}, } - positiveFeedback := snyk.MessageAction("👍") - negativeFeedback := snyk.MessageAction("👎") + positiveFeedback := types.MessageAction("👍") + negativeFeedback := types.MessageAction("👎") actionCommandMap.Add(positiveFeedback, commandData1) actionCommandMap.Add(negativeFeedback, commandData2) @@ -216,7 +217,7 @@ func Test_addIssueActions(t *testing.T) { Product: product.ProductCode, IssueType: snyk.CodeQualityIssue, Message: "This is a dummy error (severity error)", - CodelensCommands: []snyk.CommandData{FakeCommand}, + CodelensCommands: []types.CommandData{FakeCommand}, CodeActions: []snyk.CodeAction{FakeCodeAction}, IsIgnored: isIgnored, AdditionalData: snyk.CodeIssueData{ diff --git a/infrastructure/code/sast_enabled.go b/infrastructure/code/sast_enabled.go index 8e7f9f6a1..e15730c0b 100644 --- a/infrastructure/code/sast_enabled.go +++ b/infrastructure/code/sast_enabled.go @@ -17,34 +17,34 @@ package code import ( - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/data_structure" + "github.com/snyk/snyk-ls/internal/types" ) const codeDisabledInOrganisationMessageText = "It looks like your organization has disabled Snyk Code. " + "You can easily enable it by clicking on 'Enable Snyk Code'. " + "This will open your organization settings in your browser." -const enableSnykCodeMessageActionItemTitle snyk.MessageAction = "Enable Snyk Code" -const closeMessageActionItemTitle snyk.MessageAction = "Close" +const enableSnykCodeMessageActionItemTitle types.MessageAction = "Enable Snyk Code" +const closeMessageActionItemTitle types.MessageAction = "Close" func (sc *Scanner) isSastEnabled(sastResponse snyk_api.SastResponse) bool { if !sastResponse.SastEnabled { // this is processed in the listener registered to translate into the right client protocol - actionCommandMap := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() - commandData := snyk.CommandData{ - Title: snyk.OpenBrowserCommand, - CommandId: snyk.OpenBrowserCommand, + actionCommandMap := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() + commandData := types.CommandData{ + Title: types.OpenBrowserCommand, + CommandId: types.OpenBrowserCommand, Arguments: []any{getCodeEnablementUrl()}, } actionCommandMap.Add(enableSnykCodeMessageActionItemTitle, commandData) - actionCommandMap.Add(closeMessageActionItemTitle, snyk.CommandData{}) + actionCommandMap.Add(closeMessageActionItemTitle, types.CommandData{}) - sc.notifier.Send(snyk.ShowMessageRequest{ + sc.notifier.Send(types.ShowMessageRequest{ Message: codeDisabledInOrganisationMessageText, - Type: snyk.Warning, + Type: types.Warning, Actions: actionCommandMap, }) return false diff --git a/infrastructure/code/sast_enabled_test.go b/infrastructure/code/sast_enabled_test.go index fae75af33..0439f14f3 100644 --- a/infrastructure/code/sast_enabled_test.go +++ b/infrastructure/code/sast_enabled_test.go @@ -23,10 +23,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/snyk_api" "github.com/snyk/snyk-ls/internal/data_structure" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/types" ) func TestIsSastEnabled(t *testing.T) { @@ -86,17 +86,17 @@ func TestIsSastEnabled(t *testing.T) { errorReporter: newTestCodeErrorReporter(), notifier: notifier, } - actionMap := data_structure.NewOrderedMap[snyk.MessageAction, snyk.CommandData]() + actionMap := data_structure.NewOrderedMap[types.MessageAction, types.CommandData]() - actionMap.Add(enableSnykCodeMessageActionItemTitle, snyk.CommandData{ - Title: snyk.OpenBrowserCommand, - CommandId: snyk.OpenBrowserCommand, + actionMap.Add(enableSnykCodeMessageActionItemTitle, types.CommandData{ + Title: types.OpenBrowserCommand, + CommandId: types.OpenBrowserCommand, Arguments: []any{getCodeEnablementUrl()}, }) - actionMap.Add(closeMessageActionItemTitle, snyk.CommandData{}) - expectedShowMessageRequest := snyk.ShowMessageRequest{ + actionMap.Add(closeMessageActionItemTitle, types.CommandData{}) + expectedShowMessageRequest := types.ShowMessageRequest{ Message: codeDisabledInOrganisationMessageText, - Type: snyk.Warning, + Type: types.Warning, Actions: actionMap, } diff --git a/infrastructure/code/snyk_code_http_client.go b/infrastructure/code/snyk_code_http_client.go index f0c5a02bd..0005a2c87 100644 --- a/infrastructure/code/snyk_code_http_client.go +++ b/infrastructure/code/snyk_code_http_client.go @@ -33,9 +33,9 @@ import ( codeClientObservability "github.com/snyk/code-client-go/observability" codeClientSarif "github.com/snyk/code-client-go/sarif" + performance2 "github.com/snyk/snyk-ls/internal/observability/performance" "github.com/snyk/snyk-ls/application/config" - performance2 "github.com/snyk/snyk-ls/domain/observability/performance" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/code/encoding" ) diff --git a/infrastructure/code/snyk_code_http_client_pact_test.go b/infrastructure/code/snyk_code_http_client_pact_test.go index 33ec61170..652aa9067 100644 --- a/infrastructure/code/snyk_code_http_client_pact_test.go +++ b/infrastructure/code/snyk_code_http_client_pact_test.go @@ -23,9 +23,10 @@ import ( "testing" "github.com/pact-foundation/pact-go/dsl" - codeClientSarif "github.com/snyk/code-client-go/sarif" "github.com/stretchr/testify/assert" + codeClientSarif "github.com/snyk/code-client-go/sarif" + "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/internal/testutil" "github.com/snyk/snyk-ls/internal/util" diff --git a/infrastructure/iac/iac.go b/infrastructure/iac/iac.go index 62545bdc1..71a57044f 100644 --- a/infrastructure/iac/iac.go +++ b/infrastructure/iac/iac.go @@ -35,14 +35,15 @@ import ( sglsp "github.com/sourcegraph/go-lsp" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/progress" "github.com/snyk/snyk-ls/internal/scans" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/uri" ) @@ -66,14 +67,14 @@ var extensions = map[string]bool{ type Scanner struct { instrumentor performance.Instrumentor errorReporter error_reporting.ErrorReporter - analytics ux2.Analytics + analytics ux.Analytics cli cli.Executor mutex sync.Mutex runningScans map[sglsp.DocumentURI]*scans.ScanProgress c *config.Config } -func New(c *config.Config, instrumentor performance.Instrumentor, errorReporter error_reporting.ErrorReporter, analytics ux2.Analytics, cli cli.Executor) *Scanner { +func New(c *config.Config, instrumentor performance.Instrumentor, errorReporter error_reporting.ErrorReporter, analytics ux.Analytics, cli cli.Executor) *Scanner { return &Scanner{ instrumentor: instrumentor, errorReporter: errorReporter, @@ -93,8 +94,8 @@ func (iac *Scanner) Product() product.Product { return product.ProductInfrastructureAsCode } -func (iac *Scanner) SupportedCommands() []snyk.CommandName { - return []snyk.CommandName{} +func (iac *Scanner) SupportedCommands() []types.CommandName { + return []types.CommandName{} } func (iac *Scanner) Scan(ctx context.Context, path string, _ string) (issues []snyk.Issue, err error) { @@ -311,15 +312,15 @@ func (iac *Scanner) retrieveAnalysis(scanResult iacScanResult, workspacePath str } func (iac *Scanner) trackResult(success bool) { - var result ux2.Result + var result ux.Result if success { - result = ux2.Success + result = ux.Success } else { - result = ux2.Error + result = ux.Error } iac.analytics.AnalysisIsReady( - ux2.AnalysisIsReadyProperties{ - AnalysisType: ux2.InfrastructureAsCode, + ux.AnalysisIsReadyProperties{ + AnalysisType: ux.InfrastructureAsCode, Result: result, }, ) @@ -440,10 +441,10 @@ func parseIacIssuePath(path []any) ([]string, error) { return pathTokens, nil } -func newIacCommand(codeActionTitle string, issueURL *url.URL) *snyk.CommandData { - command := &snyk.CommandData{ +func newIacCommand(codeActionTitle string, issueURL *url.URL) *types.CommandData { + command := &types.CommandData{ Title: codeActionTitle, - CommandId: snyk.OpenBrowserCommand, + CommandId: types.OpenBrowserCommand, Arguments: []any{issueURL.String()}, } return command diff --git a/infrastructure/iac/iac_test.go b/infrastructure/iac/iac_test.go index 987a41830..d849e073a 100644 --- a/infrastructure/iac/iac_test.go +++ b/infrastructure/iac/iac_test.go @@ -24,11 +24,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" ) @@ -38,7 +38,7 @@ import ( func Test_Scan_IsInstrumented(t *testing.T) { c := testutil.UnitTest(t) instrumentor := performance.NewInstrumentor() - scanner := New(c, instrumentor, error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor()) + scanner := New(c, instrumentor, error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor()) _, _ = scanner.Scan(context.Background(), "fake.yml", "") @@ -54,7 +54,7 @@ func Test_Scan_IsInstrumented(t *testing.T) { func Test_SuccessfulScanFile_TracksAnalytics(t *testing.T) { c := testutil.UnitTest(t) - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), analytics, cli.NewTestExecutor()) issues, err := scanner.Scan(context.Background(), "fake.yml", "") @@ -62,15 +62,15 @@ func Test_SuccessfulScanFile_TracksAnalytics(t *testing.T) { assert.Nil(t, err) assert.Len(t, issues, 0) assert.Len(t, analytics.GetAnalytics(), 1) - assert.Equal(t, ux2.AnalysisIsReadyProperties{ - AnalysisType: ux2.InfrastructureAsCode, - Result: ux2.Success, + assert.Equal(t, ux.AnalysisIsReadyProperties{ + AnalysisType: ux.InfrastructureAsCode, + Result: ux.Success, }, analytics.GetAnalytics()[0]) } func Test_ErroredWorkspaceScan_TracksAnalytics(t *testing.T) { c := testutil.UnitTest(t) - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) executor := cli.NewTestExecutor() scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), analytics, executor) @@ -80,15 +80,15 @@ func Test_ErroredWorkspaceScan_TracksAnalytics(t *testing.T) { assert.NotNil(t, err) assert.Len(t, issues, 0) assert.Len(t, analytics.GetAnalytics(), 1) - assert.Equal(t, ux2.AnalysisIsReadyProperties{ - AnalysisType: ux2.InfrastructureAsCode, - Result: ux2.Error, + assert.Equal(t, ux.AnalysisIsReadyProperties{ + AnalysisType: ux.InfrastructureAsCode, + Result: ux.Error, }, analytics.GetAnalytics()[0]) } func Test_toHover_asHTML(t *testing.T) { c := testutil.UnitTest(t) - scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor()) + scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor()) config.CurrentConfig().SetFormat(config.FormatHtml) h := scanner.getExtendedMessage(sampleIssue()) @@ -102,7 +102,7 @@ func Test_toHover_asHTML(t *testing.T) { func Test_toHover_asMD(t *testing.T) { c := testutil.UnitTest(t) - scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor()) + scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor()) config.CurrentConfig().SetFormat(config.FormatMd) h := scanner.getExtendedMessage(sampleIssue()) @@ -118,7 +118,7 @@ func Test_Scan_CancelledContext_DoesNotScan(t *testing.T) { // Arrange c := testutil.UnitTest(t) cliMock := cli.NewTestExecutor() - scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cliMock) + scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cliMock) ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -132,7 +132,7 @@ func Test_Scan_CancelledContext_DoesNotScan(t *testing.T) { func Test_retrieveIssues_IgnoresParsingErrors(t *testing.T) { c := testutil.UnitTest(t) - scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor()) + scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor()) results := []iacScanResult{ { @@ -159,7 +159,7 @@ func Test_retrieveIssues_IgnoresParsingErrors(t *testing.T) { func Test_createIssueDataForCustomUI_SuccessfullyParses(t *testing.T) { c := testutil.UnitTest(t) sampleIssue := sampleIssue() - scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor()) + scanner := New(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor()) issue, err := scanner.toIssue("test.yml", sampleIssue, "") expectedAdditionalData := snyk.IaCIssueData{ diff --git a/infrastructure/learn/pact_test.go b/infrastructure/learn/pact_test.go index 253c2dca2..c950dbfef 100644 --- a/infrastructure/learn/pact_test.go +++ b/infrastructure/learn/pact_test.go @@ -24,7 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - errorreporting "github.com/snyk/snyk-ls/domain/observability/error_reporting" + errorreporting "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/learn/service.go b/infrastructure/learn/service.go index 7da09016a..23ea18100 100644 --- a/infrastructure/learn/service.go +++ b/infrastructure/learn/service.go @@ -28,9 +28,9 @@ import ( "github.com/rs/zerolog" "github.com/snyk/go-application-framework/pkg/configuration" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" "github.com/snyk/snyk-ls/domain/snyk" ) diff --git a/infrastructure/learn/service_test.go b/infrastructure/learn/service_test.go index 2f216497e..456eb872c 100644 --- a/infrastructure/learn/service_test.go +++ b/infrastructure/learn/service_test.go @@ -23,8 +23,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - errorreporting "github.com/snyk/snyk-ls/domain/observability/error_reporting" "github.com/snyk/snyk-ls/domain/snyk" + errorreporting "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/oss/cli_package_scan_test.go b/infrastructure/oss/cli_package_scan_test.go index a26cc718a..18caaa760 100644 --- a/infrastructure/oss/cli_package_scan_test.go +++ b/infrastructure/oss/cli_package_scan_test.go @@ -26,13 +26,13 @@ import ( "golang.org/x/exp/maps" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" "github.com/snyk/snyk-ls/infrastructure/oss/parser" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/oss/cli_scanner.go b/infrastructure/oss/cli_scanner.go index 53997dee5..a458d4c9d 100644 --- a/infrastructure/oss/cli_scanner.go +++ b/infrastructure/oss/cli_scanner.go @@ -31,13 +31,13 @@ import ( "golang.org/x/exp/slices" "github.com/snyk/snyk-ls/application/config" - noti "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" "github.com/snyk/snyk-ls/infrastructure/learn" + noti "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/product" "github.com/snyk/snyk-ls/internal/progress" "github.com/snyk/snyk-ls/internal/scans" @@ -63,7 +63,7 @@ var ( type CLIScanner struct { instrumentor performance.Instrumentor errorReporter error_reporting.ErrorReporter - analytics ux2.Analytics + analytics ux.Analytics cli cli.Executor mutex *sync.Mutex packageScanMutex *sync.Mutex @@ -80,7 +80,7 @@ type CLIScanner struct { config *config.Config } -func NewCLIScanner(c *config.Config, instrumentor performance.Instrumentor, errorReporter error_reporting.ErrorReporter, analytics ux2.Analytics, cli cli.Executor, learnService learn.Service, notifier noti.Notifier) snyk.ProductScanner { +func NewCLIScanner(c *config.Config, instrumentor performance.Instrumentor, errorReporter error_reporting.ErrorReporter, analytics ux.Analytics, cli cli.Executor, learnService learn.Service, notifier noti.Notifier) snyk.ProductScanner { scanner := CLIScanner{ instrumentor: instrumentor, errorReporter: errorReporter, @@ -378,14 +378,14 @@ func (cliScanner *CLIScanner) retrieveIssues( } func (cliScanner *CLIScanner) trackResult(success bool) { - var result ux2.Result + var result ux.Result if success { - result = ux2.Success + result = ux.Success } else { - result = ux2.Error + result = ux.Error } - cliScanner.analytics.AnalysisIsReady(ux2.AnalysisIsReadyProperties{ - AnalysisType: ux2.OpenSource, + cliScanner.analytics.AnalysisIsReady(ux.AnalysisIsReadyProperties{ + AnalysisType: ux.OpenSource, Result: result, }) } @@ -418,8 +418,8 @@ func (cliScanner *CLIScanner) scheduleRefreshScan(ctx context.Context, path stri } cliScanner.analytics.AnalysisIsTriggered( - ux2.AnalysisIsTriggeredProperties{ - AnalysisType: []ux2.AnalysisType{ux2.OpenSource}, + ux.AnalysisIsTriggeredProperties{ + AnalysisType: []ux.AnalysisType{ux.OpenSource}, TriggeredByUser: false, }, ) diff --git a/infrastructure/oss/issue.go b/infrastructure/oss/issue.go index 530faf8e6..44f0fe2cd 100644 --- a/infrastructure/oss/issue.go +++ b/infrastructure/oss/issue.go @@ -24,10 +24,11 @@ import ( "github.com/gomarkdown/markdown" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" "github.com/snyk/snyk-ls/internal/product" + "github.com/snyk/snyk-ls/internal/types" ) var issuesSeverity = map[string]snyk.Severity{ @@ -48,12 +49,12 @@ func toIssue( // this needs to be first so that the lesson from Snyk Learn is added codeActions := issue.AddCodeActions(learnService, ep, affectedFilePath, issueRange) - var codelensCommands []snyk.CommandData + var codelensCommands []types.CommandData for _, codeAction := range codeActions { if strings.Contains(codeAction.Title, "Upgrade to") { - codelensCommands = append(codelensCommands, snyk.CommandData{ + codelensCommands = append(codelensCommands, types.CommandData{ Title: "⚡ Fix this issue: " + codeAction.Title, - CommandId: snyk.CodeFixCommand, + CommandId: types.CodeFixCommand, Arguments: []any{ codeAction.Uuid, affectedFilePath, diff --git a/infrastructure/oss/oss_integration_test.go b/infrastructure/oss/oss_integration_test.go index 41009b707..a0d49cbff 100644 --- a/infrastructure/oss/oss_integration_test.go +++ b/infrastructure/oss/oss_integration_test.go @@ -27,14 +27,14 @@ import ( "github.com/snyk/snyk-ls/application/config" "github.com/snyk/snyk-ls/application/di" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" "github.com/snyk/snyk-ls/infrastructure/cli/install" "github.com/snyk/snyk-ls/infrastructure/oss" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" ) @@ -60,7 +60,7 @@ func Test_Scan(t *testing.T) { instrumentor := performance.NewInstrumentor() er := error_reporting.NewTestErrorReporter() analytics := ux.NewTestAnalytics(c) - cliExecutor := cli.NewExecutor(c, di.AuthenticationService(), er, analytics, notification.NewNotifier()) + cliExecutor := cli.NewExecutor(c, er, analytics, notification.NewNotifier()) scanner := oss.NewCLIScanner(c, instrumentor, er, analytics, cliExecutor, di.LearnService(), notification.NewNotifier()) workingDir, _ := os.Getwd() diff --git a/infrastructure/oss/oss_test.go b/infrastructure/oss/oss_test.go index 6c57d7580..65afd837e 100644 --- a/infrastructure/oss/oss_test.go +++ b/infrastructure/oss/oss_test.go @@ -29,14 +29,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/infrastructure/learn/mock_learn" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" ) @@ -60,7 +60,7 @@ func Test_toIssueSeverity(t *testing.T) { func Test_determineTargetFile(t *testing.T) { c := testutil.UnitTest(t) - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) assert.Equal(t, "package.json", scanner.determineTargetFile("package-lock.json")) assert.Equal(t, "pom.xml", scanner.determineTargetFile("pom.xml")) assert.Equal(t, "asdf", scanner.determineTargetFile("asdf")) @@ -69,7 +69,7 @@ func Test_determineTargetFile(t *testing.T) { func Test_SuccessfulScanFile_TracksAnalytics(t *testing.T) { c := testutil.UnitTest(t) - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) workingDir, _ := os.Getwd() executor := cli.NewTestExecutor() fileContent, _ := os.ReadFile(workingDir + "/testdata/oss-result.json") @@ -80,9 +80,9 @@ func Test_SuccessfulScanFile_TracksAnalytics(t *testing.T) { _, _ = scanner.Scan(context.Background(), p, "") assert.Len(t, analytics.GetAnalytics(), 1) - assert.Equal(t, ux2.AnalysisIsReadyProperties{ - AnalysisType: ux2.OpenSource, - Result: ux2.Success, + assert.Equal(t, ux.AnalysisIsReadyProperties{ + AnalysisType: ux.OpenSource, + Result: ux.Success, }, analytics.GetAnalytics()[0]) } @@ -298,7 +298,7 @@ func Test_introducingPackageAndVersionJava(t *testing.T) { func Test_ContextCanceled_Scan_DoesNotScan(t *testing.T) { c := testutil.UnitTest(t) cliMock := cli.NewTestExecutor() - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cliMock, getLearnMock(t), notification.NewNotifier()) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cliMock, getLearnMock(t), notification.NewNotifier()) ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -326,7 +326,7 @@ func mavenTestIssue() ossIssue { func TestUnmarshalOssJsonSingle(t *testing.T) { c := testutil.UnitTest(t) - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) dir, err := os.Getwd() if err != nil { @@ -344,7 +344,7 @@ func TestUnmarshalOssJsonSingle(t *testing.T) { func TestUnmarshalOssJsonArray(t *testing.T) { c := testutil.UnitTest(t) - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) dir, err := os.Getwd() if err != nil { @@ -362,7 +362,7 @@ func TestUnmarshalOssJsonArray(t *testing.T) { func TestUnmarshalOssErroneousJson(t *testing.T) { c := testutil.UnitTest(t) - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) dir, err := os.Getwd() if err != nil { @@ -416,7 +416,7 @@ func Test_SeveralScansOnSameFolder_DoNotRunAtOnce(t *testing.T) { folderPath := workingDir fakeCli := cli.NewTestExecutor() fakeCli.ExecuteDuration = time.Second - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), fakeCli, getLearnMock(t), notification.NewNotifier()) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), fakeCli, getLearnMock(t), notification.NewNotifier()) wg := sync.WaitGroup{} p, _ := filepath.Abs(workingDir + testDataPackageJson) @@ -456,7 +456,7 @@ func sampleIssue() ossIssue { func Test_prepareScanCommand(t *testing.T) { c := testutil.UnitTest(t) - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), cli.NewTestExecutor(), getLearnMock(t), notification.NewNotifier()).(*CLIScanner) t.Run("Expands parameters", func(t *testing.T) { settings := config.CliSettings{ @@ -491,7 +491,7 @@ func Test_Scan_SchedulesNewScan(t *testing.T) { workingDir, _ := os.Getwd() fakeCli := cli.NewTestExecutorWithResponseFromFile(path.Join(workingDir, "testdata/oss-result.json"), c.Logger()) fakeCli.ExecuteDuration = time.Millisecond - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), fakeCli, getLearnMock(t), notification.NewNotifier()).(*CLIScanner) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), fakeCli, getLearnMock(t), notification.NewNotifier()).(*CLIScanner) scanner.refreshScanWaitDuration = 50 * time.Millisecond ctx, cancel := context.WithCancel(context.Background()) @@ -512,7 +512,7 @@ func Test_scheduleNewScan_CapturesAnalytics(t *testing.T) { c := testutil.UnitTest(t) // Arrange fakeCli := cli.NewTestExecutor() - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), analytics, fakeCli, getLearnMock(t), notification.NewNotifier()).(*CLIScanner) scanner.refreshScanWaitDuration = 50 * time.Millisecond @@ -529,8 +529,8 @@ func Test_scheduleNewScan_CapturesAnalytics(t *testing.T) { return fakeCli.GetFinishedScans() == 1 }, 3*time.Second, 50*time.Millisecond) - assert.Equal(t, ux2.AnalysisIsTriggeredProperties{ - AnalysisType: []ux2.AnalysisType{ux2.OpenSource}, + assert.Equal(t, ux.AnalysisIsTriggeredProperties{ + AnalysisType: []ux.AnalysisType{ux.OpenSource}, TriggeredByUser: false, }, analytics.GetAnalytics()[0]) } @@ -542,7 +542,7 @@ func Test_scheduleNewScanWithProductDisabled_NoScanRun(t *testing.T) { config.CurrentConfig().SetSnykOssEnabled(false) fakeCli := cli.NewTestExecutor() fakeCli.ExecuteDuration = time.Millisecond - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), analytics, fakeCli, getLearnMock(t), notification.NewNotifier()).(*CLIScanner) scanner.refreshScanWaitDuration = 50 * time.Millisecond @@ -566,7 +566,7 @@ func Test_scheduleNewScanTwice_RunsOnlyOnce(t *testing.T) { // Arrange fakeCli := cli.NewTestExecutor() fakeCli.ExecuteDuration = time.Millisecond - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), analytics, fakeCli, getLearnMock(t), notification.NewNotifier()).(*CLIScanner) scanner.refreshScanWaitDuration = 50 * time.Millisecond @@ -592,7 +592,7 @@ func Test_scheduleNewScan_ContextCancelledAfterScanScheduled_NoScanRun(t *testin // Arrange fakeCli := cli.NewTestExecutor() fakeCli.ExecuteDuration = time.Millisecond - analytics := ux2.NewTestAnalytics(c) + analytics := ux.NewTestAnalytics(c) scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), analytics, fakeCli, getLearnMock(t), notification.NewNotifier()).(*CLIScanner) scanner.refreshScanWaitDuration = 2 * time.Second @@ -619,7 +619,7 @@ func Test_Scan_missingDisplayTargetFileDoesNotBreakAnalysis(t *testing.T) { fakeCli := cli.NewTestExecutorWithResponseFromFile(path.Join(workingDir, "testdata/oss-result-without-targetFile.json"), c.Logger()) fakeCli.ExecuteDuration = time.Millisecond - scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux2.NewTestAnalytics(c), fakeCli, getLearnMock(t), notification.NewNotifier()) + scanner := NewCLIScanner(c, performance.NewInstrumentor(), error_reporting.NewTestErrorReporter(), ux.NewTestAnalytics(c), fakeCli, getLearnMock(t), notification.NewNotifier()) filePath, _ := filepath.Abs(workingDir + testDataPackageJson) // Act diff --git a/infrastructure/oss/types.go b/infrastructure/oss/types.go index 929c50602..6598fb507 100644 --- a/infrastructure/oss/types.go +++ b/infrastructure/oss/types.go @@ -18,19 +18,21 @@ package oss import ( "fmt" - "github.com/rs/zerolog/log" "net/url" "strings" "time" + "github.com/rs/zerolog/log" + "github.com/gomarkdown/markdown" "github.com/pkg/errors" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/learn" "github.com/snyk/snyk-ls/internal/lsp" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/types" "github.com/snyk/snyk-ls/internal/util" ) @@ -245,9 +247,9 @@ func (i *ossIssue) AddCodeActions(learnService learn.Service, ep error_reporting } title := fmt.Sprintf("Open description of '%s affecting package %s' in browser (Snyk)", i.Title, i.PackageName) - command := &snyk.CommandData{ + command := &types.CommandData{ Title: title, - CommandId: snyk.OpenBrowserCommand, + CommandId: types.OpenBrowserCommand, Arguments: []any{i.CreateIssueURL().String()}, } @@ -277,9 +279,9 @@ func (i *ossIssue) AddSnykLearnAction(learnService learn.Service, ep error_repor title := fmt.Sprintf("Learn more about %s (Snyk)", i.Title) action = &snyk.CodeAction{ Title: title, - Command: &snyk.CommandData{ + Command: &types.CommandData{ Title: title, - CommandId: snyk.OpenBrowserCommand, + CommandId: types.OpenBrowserCommand, Arguments: []any{lesson.Url}, }, } diff --git a/infrastructure/oss/vulnerability_count_test.go b/infrastructure/oss/vulnerability_count_test.go index d781f61a4..d189aceb5 100644 --- a/infrastructure/oss/vulnerability_count_test.go +++ b/infrastructure/oss/vulnerability_count_test.go @@ -22,12 +22,12 @@ import ( "github.com/stretchr/testify/assert" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" - "github.com/snyk/snyk-ls/domain/observability/performance" - ux2 "github.com/snyk/snyk-ls/domain/observability/ux" "github.com/snyk/snyk-ls/domain/snyk" "github.com/snyk/snyk-ls/infrastructure/cli" "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/observability/performance" + ux2 "github.com/snyk/snyk-ls/internal/observability/ux" "github.com/snyk/snyk-ls/internal/testutil" ) diff --git a/infrastructure/sentry/sentry_error_reporter.go b/infrastructure/sentry/sentry_error_reporter.go index 99233b340..efa14b5ba 100644 --- a/infrastructure/sentry/sentry_error_reporter.go +++ b/infrastructure/sentry/sentry_error_reporter.go @@ -22,8 +22,8 @@ import ( "github.com/getsentry/sentry-go" "github.com/snyk/snyk-ls/application/config" - "github.com/snyk/snyk-ls/domain/ide/notification" - "github.com/snyk/snyk-ls/domain/observability/error_reporting" + "github.com/snyk/snyk-ls/internal/notification" + "github.com/snyk/snyk-ls/internal/observability/error_reporting" ) // A Sentry implementation of our error reporter that respects user preferences regarding tracking diff --git a/internal/lsp/message_types.go b/internal/lsp/message_types.go index 7044c2e13..5d73d4388 100644 --- a/internal/lsp/message_types.go +++ b/internal/lsp/message_types.go @@ -557,6 +557,8 @@ type AuthenticationMethod string const TokenAuthentication AuthenticationMethod = "token" const OAuthAuthentication AuthenticationMethod = "oauth" +const FakeAuthentication AuthenticationMethod = "fake" +const EmptyAuthenticationMethod AuthenticationMethod = "" type DidChangeConfigurationParams struct { // The actual changed settings diff --git a/internal/notification/notifier.go b/internal/notification/notifier.go index 75610807d..5ad09aba7 100644 --- a/internal/notification/notifier.go +++ b/internal/notification/notifier.go @@ -5,12 +5,24 @@ import ( sglsp "github.com/sourcegraph/go-lsp" - "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/uri" ) -func NewNotifier() notification.Notifier { +// Notifier should be passed as a dependency to the types that call "notification.x" functions. +// This allows using mocks and enables us to gradually refactor out the direct calls to +// the "notification" package functions. +type Notifier interface { + SendShowMessage(messageType sglsp.MessageType, message string) + Send(msg any) + SendError(err error) + SendErrorDiagnostic(path string, err error) + Receive() (payload any, stop bool) + CreateListener(callback func(params any)) + DisposeListener() +} + +func NewNotifier() Notifier { return ¬ifierImpl{ channel: make(chan any, 100), stopChannel: make(chan any, 100), diff --git a/internal/notification/notifier_mock.go b/internal/notification/notifier_mock.go index e7b7656d0..7d5e65b49 100644 --- a/internal/notification/notifier_mock.go +++ b/internal/notification/notifier_mock.go @@ -5,12 +5,11 @@ import ( sglsp "github.com/sourcegraph/go-lsp" - "github.com/snyk/snyk-ls/domain/ide/notification" "github.com/snyk/snyk-ls/internal/lsp" "github.com/snyk/snyk-ls/internal/uri" ) -var _ notification.Notifier = &MockNotifier{} +var _ Notifier = &MockNotifier{} type MockNotifier struct { sendShowMessageCounter int diff --git a/domain/observability/error_reporting/error_reporter.go b/internal/observability/error_reporting/error_reporter.go similarity index 100% rename from domain/observability/error_reporting/error_reporter.go rename to internal/observability/error_reporting/error_reporter.go diff --git a/domain/observability/error_reporting/test_error_reporter.go b/internal/observability/error_reporting/test_error_reporter.go similarity index 100% rename from domain/observability/error_reporting/test_error_reporter.go rename to internal/observability/error_reporting/test_error_reporter.go diff --git a/domain/observability/performance/instrumentor_test_types.go b/internal/observability/performance/instrumentor_test_types.go similarity index 100% rename from domain/observability/performance/instrumentor_test_types.go rename to internal/observability/performance/instrumentor_test_types.go diff --git a/domain/observability/performance/interfaces.go b/internal/observability/performance/interfaces.go similarity index 100% rename from domain/observability/performance/interfaces.go rename to internal/observability/performance/interfaces.go diff --git a/domain/observability/performance/noop_span.go b/internal/observability/performance/noop_span.go similarity index 100% rename from domain/observability/performance/noop_span.go rename to internal/observability/performance/noop_span.go diff --git a/domain/observability/performance/traceid.go b/internal/observability/performance/traceid.go similarity index 100% rename from domain/observability/performance/traceid.go rename to internal/observability/performance/traceid.go diff --git a/domain/observability/performance/traceid_test.go b/internal/observability/performance/traceid_test.go similarity index 100% rename from domain/observability/performance/traceid_test.go rename to internal/observability/performance/traceid_test.go diff --git a/domain/observability/ux/analytics.go b/internal/observability/ux/analytics.go similarity index 100% rename from domain/observability/ux/analytics.go rename to internal/observability/ux/analytics.go diff --git a/domain/observability/ux/recorder.go b/internal/observability/ux/recorder.go similarity index 100% rename from domain/observability/ux/recorder.go rename to internal/observability/ux/recorder.go diff --git a/domain/observability/ux/types.go b/internal/observability/ux/types.go similarity index 100% rename from domain/observability/ux/types.go rename to internal/observability/ux/types.go diff --git a/application/config/storage.go b/internal/storage/storage.go similarity index 97% rename from application/config/storage.go rename to internal/storage/storage.go index 29b5fb133..21d6f8e71 100644 --- a/application/config/storage.go +++ b/internal/storage/storage.go @@ -1,5 +1,5 @@ /* - * © 2023 Snyk Limited + * © 2023-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package config +package storage import "github.com/snyk/go-application-framework/pkg/configuration" diff --git a/application/config/storage_test.go b/internal/storage/storage_test.go similarity index 96% rename from application/config/storage_test.go rename to internal/storage/storage_test.go index 4fe5dea98..cfe82b64f 100644 --- a/application/config/storage_test.go +++ b/internal/storage/storage_test.go @@ -1,5 +1,5 @@ /* - * © 2023 Snyk Limited + * © 2023-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package config +package storage import ( "testing" diff --git a/domain/snyk/command.go b/internal/types/command.go similarity index 99% rename from domain/snyk/command.go rename to internal/types/command.go index 799416b8d..7230ad4a0 100644 --- a/domain/snyk/command.go +++ b/internal/types/command.go @@ -14,7 +14,7 @@ * limitations under the License. */ -package snyk +package types import ( "context" diff --git a/domain/snyk/message.go b/internal/types/message.go similarity index 96% rename from domain/snyk/message.go rename to internal/types/message.go index f38c4b44a..fd79f4af2 100644 --- a/domain/snyk/message.go +++ b/internal/types/message.go @@ -1,5 +1,5 @@ /* - * © 2023 Snyk Limited + * © 2023-2024 Snyk Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package snyk +package types import "github.com/snyk/snyk-ls/internal/data_structure" diff --git a/ls_extension/main_test.go b/ls_extension/main_test.go index cd89b55a8..a04c35cb6 100644 --- a/ls_extension/main_test.go +++ b/ls_extension/main_test.go @@ -5,9 +5,10 @@ import ( "github.com/snyk/snyk-ls/application/config" + "github.com/stretchr/testify/assert" + "github.com/snyk/go-application-framework/pkg/app" "github.com/snyk/go-application-framework/pkg/configuration" - "github.com/stretchr/testify/assert" ) func Test_ExtensionEntryPoint(t *testing.T) {