Skip to content

Commit

Permalink
Sanitize dictionaries before serialization (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored Nov 2, 2023
1 parent 6c8d69d commit 67c923e
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 65 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
build: buildSdk buildExample

buildSdk:
set -o pipefail && xcodebuild build -project PostHog.xcodeproj -scheme PostHog -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.0' | xcpretty
set -o pipefail && xcodebuild build -project PostHog.xcodeproj -scheme PostHog -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.0.1' | xcpretty

buildExample:
set -o pipefail && xcodebuild build -project PostHog.xcodeproj -scheme PostHogExample -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.0' | xcpretty
set -o pipefail && xcodebuild build -project PostHog.xcodeproj -scheme PostHogExample -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.0.1' | xcpretty

format: swiftLint swiftFormat

Expand All @@ -17,7 +17,7 @@ swiftFormat:
swiftformat . --swiftversion 5.3

test:
set -o pipefail && xcodebuild test -project PostHog.xcodeproj -scheme PostHog -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.0' | xcpretty
set -o pipefail && xcodebuild test -project PostHog.xcodeproj -scheme PostHog -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.0.1' | xcpretty

lint:
swiftformat . --lint --swiftversion 5.3 && swiftlint
Expand Down
8 changes: 4 additions & 4 deletions PostHog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
3A0F108529C9ABB6002C0084 /* ReadWriteLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0F108429C9ABB6002C0084 /* ReadWriteLock.swift */; };
3A0F108929C9BD76002C0084 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0F108829C9BD76002C0084 /* Errors.swift */; };
3A2BCF4C299E4E35008BB5F3 /* QueueTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BCF4B299E4E35008BB5F3 /* QueueTest.swift */; };
3A2BCF52299F7724008BB5F3 /* CodableUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BCF51299F7724008BB5F3 /* CodableUtils.swift */; };
3A580B3F29E481F200C5C6F3 /* OHHTTPStubs in Frameworks */ = {isa = PBXBuildFile; productRef = 3A580B3E29E481F200C5C6F3 /* OHHTTPStubs */; };
3A580B4129E481F200C5C6F3 /* OHHTTPStubsSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 3A580B4029E481F200C5C6F3 /* OHHTTPStubsSwift */; };
3A580B4329E489D000C5C6F3 /* URLSession+body.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A580B4229E489D000C5C6F3 /* URLSession+body.swift */; };
Expand Down Expand Up @@ -44,6 +43,7 @@
3AE3FB4B2993A68500AFFC18 /* StorageTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE3FB4A2993A68500AFFC18 /* StorageTest.swift */; };
3AE3FB4E2993D1D600AFFC18 /* PostHogSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE3FB4D2993D1D600AFFC18 /* PostHogSessionManager.swift */; };
690FF05F2AE7E2D400A0B06B /* Data+Gzip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690FF05E2AE7E2D400A0B06B /* Data+Gzip.swift */; };
690FF0B52AEBBD3C00A0B06B /* DictUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690FF0B42AEBBD3C00A0B06B /* DictUtils.swift */; };
690FF0AF2AEB9C1400A0B06B /* DateUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690FF0AE2AEB9C1400A0B06B /* DateUtils.swift */; };
690FF0C52AEFAE8200A0B06B /* PostHogLegacyQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 690FF0C42AEFAE8200A0B06B /* PostHogLegacyQueue.swift */; };
69261D132AD5685B00232EC7 /* PostHogFeatureFlags.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69261D122AD5685B00232EC7 /* PostHogFeatureFlags.swift */; };
Expand Down Expand Up @@ -141,7 +141,6 @@
3A0F108429C9ABB6002C0084 /* ReadWriteLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadWriteLock.swift; sourceTree = "<group>"; };
3A0F108829C9BD76002C0084 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = "<group>"; };
3A2BCF4B299E4E35008BB5F3 /* QueueTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueTest.swift; sourceTree = "<group>"; };
3A2BCF51299F7724008BB5F3 /* CodableUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableUtils.swift; sourceTree = "<group>"; };
3A580B4229E489D000C5C6F3 /* URLSession+body.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSession+body.swift"; sourceTree = "<group>"; };
3A62646329C9E0E7007E8C07 /* PostHogTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogTest.swift; sourceTree = "<group>"; };
3A62646929C9E385007E8C07 /* MockPostHogServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPostHogServer.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -172,6 +171,7 @@
690FF02F2AE7C5BA00A0B06B /* PostHogExampleWithPods.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = PostHogExampleWithPods.xcodeproj; path = PostHogExampleWithPods/PostHogExampleWithPods.xcodeproj; sourceTree = "<group>"; };
690FF0532AE7DB3700A0B06B /* PostHogExampleWithSPM.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = PostHogExampleWithSPM.xcodeproj; path = PostHogExampleWithSPM/PostHogExampleWithSPM.xcodeproj; sourceTree = "<group>"; };
690FF05E2AE7E2D400A0B06B /* Data+Gzip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Gzip.swift"; sourceTree = "<group>"; };
690FF0B42AEBBD3C00A0B06B /* DictUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictUtils.swift; sourceTree = "<group>"; };
690FF0AE2AEB9C1400A0B06B /* DateUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateUtils.swift; sourceTree = "<group>"; };
690FF0C42AEFAE8200A0B06B /* PostHogLegacyQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogLegacyQueue.swift; sourceTree = "<group>"; };
69261D122AD5685B00232EC7 /* PostHogFeatureFlags.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogFeatureFlags.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -282,10 +282,10 @@
children = (
3AE3FB422992985A00AFFC18 /* Reachability.swift */,
3AE3FB462992AB0000AFFC18 /* Hedgelog.swift */,
3A2BCF51299F7724008BB5F3 /* CodableUtils.swift */,
3A0F108429C9ABB6002C0084 /* ReadWriteLock.swift */,
3A0F108829C9BD76002C0084 /* Errors.swift */,
690FF05E2AE7E2D400A0B06B /* Data+Gzip.swift */,
690FF0B42AEBBD3C00A0B06B /* DictUtils.swift */,
690FF0AE2AEB9C1400A0B06B /* DateUtils.swift */,
);
path = Utils;
Expand Down Expand Up @@ -636,7 +636,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3A2BCF52299F7724008BB5F3 /* CodableUtils.swift in Sources */,
690FF05F2AE7E2D400A0B06B /* Data+Gzip.swift in Sources */,
69261D1F2AD9681300232EC7 /* PostHogConsumerPayload.swift in Sources */,
69261D252AD9787A00232EC7 /* PostHogExtensions.swift in Sources */,
Expand All @@ -654,6 +653,7 @@
3AE3FB3F29924F4F00AFFC18 /* PostHogConfig.swift in Sources */,
690FF0C52AEFAE8200A0B06B /* PostHogLegacyQueue.swift in Sources */,
3AE3FB332991388500AFFC18 /* PostHogQueue.swift in Sources */,
690FF0B52AEBBD3C00A0B06B /* DictUtils.swift in Sources */,
69261D1B2AD9678C00232EC7 /* PostHogEvent.swift in Sources */,
3AE3FB472992AB0000AFFC18 /* Hedgelog.swift in Sources */,
69261D132AD5685B00232EC7 /* PostHogFeatureFlags.swift in Sources */,
Expand Down
38 changes: 24 additions & 14 deletions PostHog/PostHogSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,14 @@ let maxRetryDelay = 30.0
return
}

let sanitizedProps = sanitizeDicionary(properties)
if sanitizedProps == nil {
return
}

personPropsLock.withLock {
// TODO: Sanitise props for storage
let props = getRegisteredProperties()
let mergedProps = props.merging(properties) { _, new in new }
let mergedProps = props.merging(sanitizedProps!) { _, new in new }
storage?.setDictionary(forKey: .registerProperties, contents: mergedProps)
}
}
Expand Down Expand Up @@ -274,7 +278,7 @@ let maxRetryDelay = 30.0
properties: buildProperties(properties: [
"distinct_id": distinctId,
"$anon_distinct_id": getAnonymousId(),
], userProperties: userProperties, userPropertiesSetOnce: userPropertiesSetOnce)
], userProperties: sanitizeDicionary(userProperties), userPropertiesSetOnce: sanitizeDicionary(userPropertiesSetOnce))
))

if distinctId != oldDistinctId {
Expand Down Expand Up @@ -331,10 +335,10 @@ let maxRetryDelay = 30.0
queue.add(PostHogEvent(
event: event,
distinctId: getDistinctId(),
properties: buildProperties(properties: properties,
userProperties: userProperties,
userPropertiesSetOnce: userPropertiesSetOnce,
groupProperties: groupProperties)
properties: buildProperties(properties: sanitizeDicionary(properties),
userProperties: sanitizeDicionary(userProperties),
userPropertiesSetOnce: sanitizeDicionary(userPropertiesSetOnce),
groupProperties: sanitizeDicionary(groupProperties))
))
}

Expand All @@ -354,7 +358,7 @@ let maxRetryDelay = 30.0

let props = [
"$screen_name": screenTitle,
].merging(properties ?? [:]) { prop, _ in prop }
].merging(sanitizeDicionary(properties) ?? [:]) { prop, _ in prop }

queue.add(PostHogEvent(
event: "$screen",
Expand Down Expand Up @@ -417,15 +421,21 @@ let maxRetryDelay = 30.0
guard let queue = queue else {
return
}

var props: [String: Any] = ["$group_type": type,
"$group_key": key]

let groupProps = sanitizeDicionary(groupProperties)

if groupProps != nil {
props["$group_set"] = groupProps
}

// Same as .group but without associating the current user with the group
queue.add(PostHogEvent(
event: "$groupidentify",
distinctId: getDistinctId(),
properties: buildProperties(properties: [
"$group_type": type,
"$group_key": key,
"$group_set": groupProperties ?? [],
])
properties: buildProperties(properties: props)
))
}

Expand All @@ -443,7 +453,7 @@ let maxRetryDelay = 30.0
_ = groups([type: key])

if groupProperties != nil {
groupIdentify(type: type, key: key, groupProperties: groupProperties)
groupIdentify(type: type, key: key, groupProperties: sanitizeDicionary(groupProperties))
}
}

Expand Down
43 changes: 0 additions & 43 deletions PostHog/Utils/CodableUtils.swift

This file was deleted.

43 changes: 43 additions & 0 deletions PostHog/Utils/DictUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// DictUtils.swift
// PostHog
//
// Created by Manoel Aranda Neto on 27.10.23.
//

import Foundation

public func sanitizeDicionary(_ dict: [String: Any]?) -> [String: Any]? {
if dict == nil || dict!.isEmpty {
return nil
}

var newDict = dict!

for (key, value) in newDict where !isValidObject(value) {
if value is URL {
newDict[key] = (value as! URL).absoluteString
continue
}
if value is Date {
newDict[key] = ISO8601DateFormatter().string(from: (value as! Date))
continue
}

newDict.removeValue(forKey: key)
hedgeLog("property: \(key) isn't serializable, dropping the item")
}

return newDict
}

private func isValidObject(_ object: Any) -> Bool {
if object is String || object is Bool || object is any Numeric || object is NSNumber {
return true
}
if object is [Any?] || object is [String: Any?] {
return JSONSerialization.isValidJSONObject(object)
}
// workaround [object] since isValidJSONObject only accepts an Array or Dict
return JSONSerialization.isValidJSONObject([object])
}
2 changes: 1 addition & 1 deletion PostHogTests/FeatureFlagsTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class FeatureFlagTests: QuickSpec {
posthog = harness.posthog

let expectation = self.expectation(description: "Waits for flags")
posthog.reloadFeatureFlags { _, _ in
posthog.reloadFeatureFlags {
expectation.fulfill()
}

Expand Down

0 comments on commit 67c923e

Please sign in to comment.