Skip to content

Commit

Permalink
fix: IDE-24 Disable Tracking via Segment and Amplitude for NON-MT-US …
Browse files Browse the repository at this point in the history
* fix: IDE-24 Disable Tracking via Segment and Amplitude for NON-MT-US customers

* chore: refactor test cases to use a list of uris

* fix: improved test cases by shorten the descriptions and fix the test with customEndpointUrl issues.

* fix: updating unit test cases for the SenryErrorReporter

* fix: solved a space issue fouund by linter.
  • Loading branch information
acke authored Feb 5, 2024
1 parent 2a9409c commit 3155d36
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 36 deletions.
26 changes: 13 additions & 13 deletions src/main/kotlin/io/snyk/plugin/services/SnykAnalyticsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import snyk.analytics.QuickFixIsDisplayed
import snyk.analytics.QuickFixIsTriggered
import snyk.analytics.WelcomeIsViewed
import snyk.common.SnykError
import snyk.common.isFedramp
import snyk.common.isAnalyticsPermitted
import snyk.container.ContainerResult
import snyk.iac.IacResult
import snyk.oss.OssResult
Expand Down Expand Up @@ -146,7 +146,7 @@ class SnykAnalyticsService : Disposable {
}

fun obtainUserId(token: String?): String {
if (!settings.usageAnalyticsEnabled || isFedramp()) {
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted()) {
log.warn("Token is null or empty, or analytics disabled. User public id will not be obtained.")
return ""
}
Expand All @@ -164,7 +164,7 @@ class SnykAnalyticsService : Disposable {
}

fun identify() {
if (!settings.usageAnalyticsEnabled || isFedramp() || userId.isBlank()) {
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted() || userId.isBlank()) {
return
}

Expand All @@ -174,15 +174,15 @@ class SnykAnalyticsService : Disposable {
}

fun logWelcomeIsViewed(event: WelcomeIsViewed) {
if (!settings.usageAnalyticsEnabled || isFedramp()) return
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted()) return

catchAll(log, "welcomeIsViewed") {
itly.logWelcomeIsViewed(userId, event)
}
}

fun logAnalysisIsTriggered(event: AnalysisIsTriggered) {
if (!settings.usageAnalyticsEnabled || isFedramp() || userId.isBlank()) {
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted() || userId.isBlank()) {
return
}

Expand All @@ -192,7 +192,7 @@ class SnykAnalyticsService : Disposable {
}

private fun logAnalysisIsReady(event: AnalysisIsReady) {
if (!settings.usageAnalyticsEnabled || isFedramp() || userId.isBlank()) {
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted() || userId.isBlank()) {
return
}

Expand All @@ -202,7 +202,7 @@ class SnykAnalyticsService : Disposable {
}

fun logIssueInTreeIsClicked(event: IssueInTreeIsClicked) {
if (!settings.usageAnalyticsEnabled || isFedramp() || userId.isBlank()) {
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted() || userId.isBlank()) {
return
}

Expand All @@ -212,7 +212,7 @@ class SnykAnalyticsService : Disposable {
}

fun logHealthScoreIsClicked(event: HealthScoreIsClicked) {
if (!settings.usageAnalyticsEnabled || isFedramp() || userId.isBlank()) {
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted() || userId.isBlank()) {
return
}

Expand All @@ -222,39 +222,39 @@ class SnykAnalyticsService : Disposable {
}

fun logPluginIsInstalled(event: PluginIsInstalled) {
if (!settings.usageAnalyticsEnabled || isFedramp()) return
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted()) return

catchAll(log, "pluginIsInstalled") {
itly.logPluginIsInstalled(userId, event)
}
}

fun logPluginIsUninstalled(event: PluginIsUninstalled) {
if (!settings.usageAnalyticsEnabled || isFedramp()) return
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted()) return

catchAll(log, "pluginIsUninstalled") {
itly.logPluginIsUninstalled(userId, event)
}
}

fun logAuthenticateButtonIsClicked(event: AuthenticateButtonIsClicked) {
if (!settings.usageAnalyticsEnabled || isFedramp()) return
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted()) return

catchAll(log, "authenticateButtonIsClicked") {
itly.logAuthenticateButtonIsClicked(userId, event)
}
}

fun logQuickFixIsDisplayed(event: QuickFixIsDisplayed) {
if (!settings.usageAnalyticsEnabled || isFedramp()) return
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted()) return

catchAll(log, "quickFixIsDisplayed") {
itly.logQuickFixIsDisplayed(userId, event)
}
}

fun logQuickFixIsTriggered(event: QuickFixIsTriggered) {
if (!settings.usageAnalyticsEnabled || isFedramp()) return
if (!settings.usageAnalyticsEnabled || !isAnalyticsPermitted()) return

catchAll(log, "quickFixIsTriggered") {
itly.logQuickFixIsTriggered(userId, event)
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/snyk/amplitude/AmplitudeExperimentService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import snyk.amplitude.api.AmplitudeExperimentApiClient
import snyk.amplitude.api.AmplitudeExperimentApiClient.Defaults.FALLBACK_VARIANT
import snyk.amplitude.api.ExperimentUser
import snyk.amplitude.api.Variant
import snyk.common.isFedramp
import snyk.common.isAnalyticsPermitted
import java.io.IOException
import java.util.Properties
import java.util.concurrent.ConcurrentHashMap
Expand All @@ -31,7 +31,7 @@ class AmplitudeExperimentService : Disposable {
prop.load(javaClass.classLoader.getResourceAsStream("application.properties"))
val apiKey = prop.getProperty("amplitude.experiment.api-key") ?: ""
val settings = pluginSettings()
if (settings.usageAnalyticsEnabled && !isFedramp()) {
if (settings.usageAnalyticsEnabled && !isAnalyticsPermitted()) {
apiClient = AmplitudeExperimentApiClient.create(apiKey = apiKey)
} else {
LOG.debug("Amplitude experiment disabled.")
Expand Down
7 changes: 4 additions & 3 deletions src/main/kotlin/snyk/common/CustomEndpoints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,14 @@ fun URI.isOauth() = isSnykGov()

fun URI.isDev() = isSnykDomain() && host.lowercase().startsWith("dev.")

fun URI.isFedramp() = isSnykGov()
fun URI.isAnalyticsPermitted() = host != null &&
(host.lowercase() == "app.snyk.io" || host.lowercase() == "app.us.snyk.io" || host.lowercase() == "snyk.io")

fun isFedramp(): Boolean {
fun isAnalyticsPermitted(): Boolean {
val settings = pluginSettings()
return settings.customEndpointUrl
?.let { URI(it) }
?.isFedramp() ?: false
?.isAnalyticsPermitted() ?: true
}

fun URI.isLocalCodeEngine() = pluginSettings().localCodeEngineEnabled == true
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/snyk/common/EnvironmentHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object EnvironmentHelper {

environment["SNYK_API"] = endpoint

if (!pluginSettings().usageAnalyticsEnabled || endpointURI.isFedramp()) {
if (!pluginSettings().usageAnalyticsEnabled || !endpointURI.isAnalyticsPermitted()) {
environment["SNYK_CFG_DISABLE_ANALYTICS"] = "1"
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/snyk/errorHandler/SentryErrorReporter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import io.sentry.protocol.SentryId
import io.sentry.protocol.SentryRuntime
import io.snyk.plugin.pluginSettings
import snyk.PropertyLoader
import snyk.common.isFedramp
import snyk.common.isAnalyticsPermitted
import snyk.pluginInfo

object SentryErrorReporter {
Expand Down Expand Up @@ -109,7 +109,7 @@ object SentryErrorReporter {
if (ApplicationManager.getApplication().isUnitTestMode) return SentryId.EMPTY_ID

val settings = pluginSettings()
return if (settings.crashReportingEnabled && !isFedramp()) {
return if (settings.crashReportingEnabled && isAnalyticsPermitted()) {
val sentryId = Sentry.captureException(throwable)
LOG.info("Sentry event reported: $sentryId")
sentryId
Expand Down
41 changes: 29 additions & 12 deletions src/test/kotlin/snyk/common/CustomEndpointsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,14 @@ class CustomEndpointsTest {

@Test
fun `api snyk path needs token`() {
var uri = "https://api.snyk.io/v1"
assertTrue(needsSnykToken(uri))
uri = "https://app.eu.snyk.io/api"
assertTrue(needsSnykToken(uri))
uri = "https://app.au.snyk.io/api"
assertTrue(needsSnykToken(uri))
val uris = listOf(
"https://api.snyk.io/v1",
"https://app.eu.snyk.io/api",
"https://app.au.snyk.io/api"
)
uris.forEach { uri ->
assertTrue(needsSnykToken(uri))
}
}

@Test
Expand All @@ -204,14 +206,29 @@ class CustomEndpointsTest {
}

@Test
fun `isFedramp true for the right URI`() {
val uri = URI("https://app.fedramp.snykgov.io")
assertTrue(uri.isFedramp())
fun `isAnalyticsPermitted false for URIs not allowed`() {
val uris = listOf(
"https://app.fedramp.snykgov.io",
"https://app.eu.snyk.io/api",
"https://app.au.snyk.io/api"
)
uris.forEach { uri ->
assertFalse(URI(uri).isAnalyticsPermitted())
}
}

@Test
fun `isFedramp false for the right URI`() {
val uri = URI("https://app.fedddramp.snykagov.io")
assertFalse(uri.isFedramp())
fun `isAnalyticsPermitted true for the right URIs`() {
val uris = listOf(
"https://snyk.io/api",
"https://app.snyk.io",
"https://app.us.snyk.io",
"https://app.snyk.io/api",
"https://app.snyk.io/v1"
)

uris.forEach { uri ->
assertTrue(URI(uri).isAnalyticsPermitted())
}
}
}
29 changes: 26 additions & 3 deletions src/test/kotlin/snyk/errorHandler/SentryErrorReporterTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ import io.sentry.Sentry
import io.sentry.protocol.SentryId
import io.snyk.plugin.pluginSettings
import io.snyk.plugin.services.SnykApplicationSettingsStateService
import junit.framework.TestCase
import org.junit.After
import org.junit.Before
import org.junit.Test
import snyk.PluginInformation
import snyk.common.isAnalyticsPermitted
import snyk.pluginInfo
import java.net.URI

class SentryErrorReporterTest {
@Before
Expand Down Expand Up @@ -43,15 +46,35 @@ class SentryErrorReporterTest {
}

@Test
fun `captureException should not send exceptions to Sentry when crashReportingEnabled is true and fedramp`() {
fun `captureException should only report if permitted env`() {
val settings = mockPluginInformation()
setUnitTesting(false)
settings.crashReportingEnabled = true
settings.customEndpointUrl = "https://api.fedramp.snykgov.io"

val uris = listOf(
"https://app.fedramp.snykgov.io",
"https://app.eu.snyk.io/api",
"https://app.au.snyk.io/api"
)

uris.forEach { uri ->
settings.customEndpointUrl = uri

SentryErrorReporter.captureException(RuntimeException("test"))

verify(exactly = 0) { Sentry.captureException(any()) }
}
}
@Test
fun `captureException should send exceptions to Sentry when URL is a permitted environment`() {
val settings = mockPluginInformation()
setUnitTesting(false)
settings.crashReportingEnabled = true
settings.customEndpointUrl = "https://app.snyk.io"

SentryErrorReporter.captureException(RuntimeException("test"))

verify(exactly = 0) { Sentry.captureException(any()) }
verify(exactly = 1) { Sentry.captureException(any()) }
}

@Test
Expand Down

0 comments on commit 3155d36

Please sign in to comment.