-
Notifications
You must be signed in to change notification settings - Fork 17
feat(flutter-tracker): add deep link and push notification event tracking #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
12643f7
6178cc5
4a28732
99fccbb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code library with Restrictive license More DetailsCode library Remediation guidance
To ignore this finding as an exception, reply to this conversation with If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more). To get more details on how to remediate this issue using AI, reply to this conversation with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code library with Restrictive license More DetailsCode library Remediation guidance
To ignore this finding as an exception, reply to this conversation with If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more). To get more details on how to remediate this issue using AI, reply to this conversation with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Code library with Restrictive license More DetailsCode library Remediation guidance
To ignore this finding as an exception, reply to this conversation with If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more). To get more details on how to remediate this issue using AI, reply to this conversation with |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // Copyright (c) 2022-present Snowplow Analytics Ltd. All rights reserved. | ||
| // | ||
| // This program is licensed to you under the Apache License Version 2.0, | ||
| // and you may not use this file except in compliance with the Apache License Version 2.0. | ||
| // You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the Apache License Version 2.0 is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
|
|
||
| package com.snowplowanalytics.snowplow_tracker.readers.events | ||
|
|
||
| import com.snowplowanalytics.snowplow.event.DeepLinkReceived | ||
|
|
||
| class DeepLinkReceivedReader(val values: Map<String, Any>) { | ||
| private val valuesDefault = values.withDefault { null } | ||
|
|
||
| val url: String by values | ||
| val referrer: String? by valuesDefault | ||
|
|
||
| fun toDeepLinkReceived(): DeepLinkReceived { | ||
| val event = DeepLinkReceived(url) | ||
| referrer?.let { event.referrer(it) } | ||
| return event | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // Copyright (c) 2022-present Snowplow Analytics Ltd. All rights reserved. | ||
| // | ||
| // This program is licensed to you under the Apache License Version 2.0, | ||
| // and you may not use this file except in compliance with the Apache License Version 2.0. | ||
| // You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the Apache License Version 2.0 is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
|
|
||
| package com.snowplowanalytics.snowplow_tracker.readers.events | ||
|
|
||
| import com.snowplowanalytics.snowplow.event.MessageNotification | ||
| import com.snowplowanalytics.snowplow.event.MessageNotificationAttachment | ||
| import com.snowplowanalytics.snowplow.event.MessageNotificationTrigger | ||
|
|
||
| class MessageNotificationReader(val values: Map<String, Any>) { | ||
| private val valuesDefault = values.withDefault { null } | ||
|
|
||
| val title: String by values | ||
| val body: String by values | ||
| private val trigger: String by values | ||
| val action: String? by valuesDefault | ||
| val badge: Int? by lazy { (values["badge"] as? Number)?.toInt() } | ||
| val categoryIdentifier: String? by valuesDefault | ||
| val launchImageName: String? by valuesDefault | ||
| val notificationTimestamp: String? by valuesDefault | ||
| val sound: String? by valuesDefault | ||
| val subtitle: String? by valuesDefault | ||
| val threadIdentifier: String? by valuesDefault | ||
| private val attachmentsRaw: List<Map<String, Any>>? by valuesDefault | ||
| private val processedAttachments: List<MessageNotificationAttachment>? by lazy { | ||
| attachmentsRaw?.map { map -> | ||
| MessageNotificationAttachment( | ||
| map["identifier"] as String, | ||
| map["type"] as String, | ||
| map["url"] as String | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| private fun toTrigger(): MessageNotificationTrigger { | ||
| return when (trigger) { | ||
| "push" -> MessageNotificationTrigger.push | ||
| "calendar" -> MessageNotificationTrigger.calendar | ||
| "timeInterval" -> MessageNotificationTrigger.timeInterval | ||
| "location" -> MessageNotificationTrigger.location | ||
| else -> MessageNotificationTrigger.push | ||
| } | ||
| } | ||
|
|
||
| fun toMessageNotification(): MessageNotification { | ||
| val event = MessageNotification(title, body, toTrigger()) | ||
| action?.let { event.action(it) } | ||
| badge?.let { event.badge(it) } | ||
| categoryIdentifier?.let { event.categoryIdentifier(it) } | ||
| launchImageName?.let { event.launchImageName(it) } | ||
| notificationTimestamp?.let { event.notificationTimestamp(it) } | ||
| sound?.let { event.sound(it) } | ||
| subtitle?.let { event.subtitle(it) } | ||
| threadIdentifier?.let { event.thread(it) } | ||
| processedAttachments?.let { event.attachments(it) } | ||
| return event | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| // Copyright (c) 2022-present Snowplow Analytics Ltd. All rights reserved. | ||
| // | ||
| // This program is licensed to you under the Apache License Version 2.0, | ||
| // and you may not use this file except in compliance with the Apache License Version 2.0. | ||
| // You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the Apache License Version 2.0 is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
|
|
||
| package com.snowplowanalytics.snowplow_tracker.readers.events | ||
|
|
||
| import org.junit.Assert.* | ||
| import org.junit.Test | ||
|
|
||
| class DeepLinkReceivedReaderTest { | ||
|
|
||
| @Test | ||
| fun `reader extracts required url`() { | ||
| val map = mapOf("url" to "https://example.com/path") | ||
| val reader = DeepLinkReceivedReader(map) | ||
|
|
||
| assertEquals("https://example.com/path", reader.url) | ||
| assertNull(reader.referrer) | ||
| } | ||
|
|
||
| @Test | ||
| fun `reader extracts optional referrer`() { | ||
| val map = mapOf( | ||
| "url" to "https://example.com/path", | ||
| "referrer" to "https://referrer.example.com" | ||
| ) | ||
| val reader = DeepLinkReceivedReader(map) | ||
|
|
||
| assertEquals("https://example.com/path", reader.url) | ||
| assertEquals("https://referrer.example.com", reader.referrer) | ||
| } | ||
|
|
||
| @Test | ||
| fun `toDeepLinkReceived produces event with url`() { | ||
| val map = mapOf("url" to "https://example.com/path") | ||
| val reader = DeepLinkReceivedReader(map) | ||
| val event = reader.toDeepLinkReceived() | ||
|
|
||
| assertNotNull(event) | ||
| } | ||
|
|
||
| @Test | ||
| fun `toDeepLinkReceived produces event with referrer`() { | ||
| val map = mapOf( | ||
| "url" to "https://example.com/path", | ||
| "referrer" to "https://referrer.example.com" | ||
| ) | ||
| val reader = DeepLinkReceivedReader(map) | ||
| val event = reader.toDeepLinkReceived() | ||
|
|
||
| assertNotNull(event) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| // Copyright (c) 2022-present Snowplow Analytics Ltd. All rights reserved. | ||
| // | ||
| // This program is licensed to you under the Apache License Version 2.0, | ||
| // and you may not use this file except in compliance with the Apache License Version 2.0. | ||
| // You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the Apache License Version 2.0 is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
|
|
||
| package com.snowplowanalytics.snowplow_tracker.readers.events | ||
|
|
||
| import org.junit.Assert.* | ||
| import org.junit.Test | ||
|
|
||
| class MessageNotificationReaderTest { | ||
|
|
||
| @Test | ||
| fun `reader extracts required fields`() { | ||
| val map = mapOf( | ||
| "title" to "Test Title", | ||
| "body" to "Test Body", | ||
| "trigger" to "push" | ||
| ) | ||
| val reader = MessageNotificationReader(map) | ||
|
|
||
| assertEquals("Test Title", reader.title) | ||
| assertEquals("Test Body", reader.body) | ||
| } | ||
|
|
||
| @Test | ||
| fun `reader extracts optional fields`() { | ||
| val map = mapOf( | ||
| "title" to "Title", | ||
| "body" to "Body", | ||
| "trigger" to "calendar", | ||
| "action" to "Open", | ||
| "badge" to 3, | ||
| "categoryIdentifier" to "cat1", | ||
| "launchImageName" to "launch", | ||
| "notificationTimestamp" to "2023-01-01T00:00:00Z", | ||
| "sound" to "default", | ||
| "subtitle" to "Subtitle", | ||
| "threadIdentifier" to "thread1" | ||
| ) | ||
| val reader = MessageNotificationReader(map) | ||
|
|
||
| assertEquals("Open", reader.action) | ||
| assertEquals(3, reader.badge) | ||
| assertEquals("cat1", reader.categoryIdentifier) | ||
| assertEquals("launch", reader.launchImageName) | ||
| assertEquals("2023-01-01T00:00:00Z", reader.notificationTimestamp) | ||
| assertEquals("default", reader.sound) | ||
| assertEquals("Subtitle", reader.subtitle) | ||
| assertEquals("thread1", reader.threadIdentifier) | ||
| } | ||
|
|
||
| @Test | ||
| fun `reader nulls optional fields when absent`() { | ||
| val map = mapOf( | ||
| "title" to "Title", | ||
| "body" to "Body", | ||
| "trigger" to "push" | ||
| ) | ||
| val reader = MessageNotificationReader(map) | ||
|
|
||
| assertNull(reader.action) | ||
| assertNull(reader.badge) | ||
| assertNull(reader.categoryIdentifier) | ||
| assertNull(reader.launchImageName) | ||
| assertNull(reader.notificationTimestamp) | ||
| assertNull(reader.sound) | ||
| assertNull(reader.subtitle) | ||
| assertNull(reader.threadIdentifier) | ||
| } | ||
|
|
||
| @Test | ||
| fun `toMessageNotification produces event with required fields`() { | ||
| val map = mapOf( | ||
| "title" to "Title", | ||
| "body" to "Body", | ||
| "trigger" to "push" | ||
| ) | ||
| val reader = MessageNotificationReader(map) | ||
| val event = reader.toMessageNotification() | ||
|
|
||
| assertNotNull(event) | ||
| } | ||
|
|
||
| @Test | ||
| fun `toMessageNotification produces event with all optional fields`() { | ||
| val attachmentMap = mapOf( | ||
| "identifier" to "att1", | ||
| "type" to "image/png", | ||
| "url" to "https://example.com/image.png" | ||
| ) | ||
| val map = mapOf( | ||
| "title" to "Title", | ||
| "body" to "Body", | ||
| "trigger" to "timeInterval", | ||
| "action" to "Open", | ||
| "badge" to 2, | ||
| "categoryIdentifier" to "cat1", | ||
| "launchImageName" to "launch", | ||
| "notificationTimestamp" to "2023-01-01T00:00:00Z", | ||
| "sound" to "default", | ||
| "subtitle" to "Subtitle", | ||
| "threadIdentifier" to "thread1", | ||
| "attachments" to listOf(attachmentMap) | ||
| ) | ||
| val reader = MessageNotificationReader(map) | ||
| val event = reader.toMessageNotification() | ||
|
|
||
| assertNotNull(event) | ||
| } | ||
|
|
||
| @Test | ||
| fun `reader handles all trigger values`() { | ||
| listOf("push", "calendar", "timeInterval", "location").forEach { triggerStr -> | ||
| val map = mapOf( | ||
| "title" to "Title", | ||
| "body" to "Body", | ||
| "trigger" to triggerStr | ||
| ) | ||
| val reader = MessageNotificationReader(map) | ||
| val event = reader.toMessageNotification() | ||
| assertNotNull("Event should not be null for trigger: $triggerStr", event) | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code library with Restrictive license
More Details
Code library
net.sf.proguard:proguard-gradleversion6.0.3hasGPL-2.0-onlylicense, categorized asRestrictive, its use may cause a supply chain licensing issue.Remediation guidance
To ignore this finding as an exception, reply to this conversation with
#wiz_ignore reasonIf you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).
To get more details on how to remediate this issue using AI, reply to this conversation with
#wiz remediate