diff --git a/docs/Event.md b/docs/Event.md index 87e44134..66037c94 100644 --- a/docs/Event.md +++ b/docs/Event.md @@ -2,7 +2,7 @@ # Event -Contains results from Fingerprint Identification and all active Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. +Contains results from Fingerprint Identification and all active Smart Signals, or from the Automation Intelligence API. Check `source` to see which properties can be present: - `device` - generated by the JS agent or a mobile SDK running on an end-user device. Contains Identification (`visitor_id`) and Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. - `edge` - generated by the Automation Intelligence API (`/edge` endpoint). Contains only IP and bot analysis, never Identification or Smart Signals derived from device telemetry. Events stored before `source` was added don't have it; treat them as `device`. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. ## Properties diff --git a/res/fingerprint-server-api.yaml b/res/fingerprint-server-api.yaml index 531bdae8..cddd3495 100644 --- a/res/fingerprint-server-api.yaml +++ b/res/fingerprint-server-api.yaml @@ -1204,6 +1204,11 @@ components: enum: - device - edge + EnvironmentId: + type: string + examples: + - ae_47abaca3db2c7c43 + description: Environment ID of the event. Url: type: string examples: @@ -1720,11 +1725,6 @@ components: enum: - partially_completed - completed - EnvironmentId: - type: string - examples: - - ae_47abaca3db2c7c43 - description: Environment ID of the event. Suspect: type: boolean description: >- @@ -3146,11 +3146,24 @@ components: team](https://fingerprint.com/support/). Event: type: object - description: >- + description: > Contains results from Fingerprint Identification and all active Smart + Signals, or from the Automation Intelligence API. Check `source` to see + which properties can be present: + + - `device` - generated by the JS agent or a mobile SDK running on an + end-user device. Contains Identification (`visitor_id`) and Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported - devices. Consult the [Smart Signals + devices. + + - `edge` - generated by the Automation Intelligence API (`/edge` + endpoint). Contains only IP and bot analysis, never Identification or + Smart Signals derived from device telemetry. + + + Events stored before `source` was added don't have it; treat them as + `device`. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. required: diff --git a/sdk/src/main/java/com/fingerprint/v4/model/Event.java b/sdk/src/main/java/com/fingerprint/v4/model/Event.java index b49f2041..ff632a26 100644 --- a/sdk/src/main/java/com/fingerprint/v4/model/Event.java +++ b/sdk/src/main/java/com/fingerprint/v4/model/Event.java @@ -22,7 +22,7 @@ import java.util.Objects; /** - * Contains results from Fingerprint Identification and all active Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. + * Contains results from Fingerprint Identification and all active Smart Signals, or from the Automation Intelligence API. Check `source` to see which properties can be present: - `device` - generated by the JS agent or a mobile SDK running on an end-user device. Contains Identification (`visitor_id`) and Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. - `edge` - generated by the Automation Intelligence API (`/edge` endpoint). Contains only IP and bot analysis, never Identification or Smart Signals derived from device telemetry. Events stored before `source` was added don't have it; treat them as `device`. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. */ @JsonPropertyOrder({ Event.JSON_PROPERTY_EVENT_ID, diff --git a/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java b/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java index 8bfe0689..dc25547e 100644 --- a/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java +++ b/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java @@ -2,9 +2,11 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -14,6 +16,7 @@ import com.fingerprint.v4.model.ErrorResponse; import com.fingerprint.v4.model.Event; import com.fingerprint.v4.model.EventRuleAction; +import com.fingerprint.v4.model.EventSource; import com.fingerprint.v4.sdk.JSON; import java.io.File; import java.io.IOException; @@ -104,6 +107,54 @@ public void deserializeEventWithUnknownRuleActionTypeValue() throws IOException assertInstanceOf(EventRuleAction.UnknownEventRuleAction.class, event.getRuleAction()); } + @Test + public void deserializeEventWithoutSource() throws IOException { + ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper(); + + ObjectNode eventNode = + sdkObjectMapper.readValue( + getFileAsIOStream(EVENTS_DIR + "/get_event_200.json"), ObjectNode.class); + eventNode.remove("source"); + + Event event = sdkObjectMapper.treeToValue(eventNode, Event.class); + + assertNull(event.getSource()); + assertNotNull(event.getIdentification()); + assertEquals(eventNode.get("event_id").asText(), event.getEventId()); + assertFalse(sdkObjectMapper.writeValueAsString(event).contains("\"source\"")); + } + + @Test + public void deserializeEdgeEvent() throws IOException { + ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper(); + + Event event = + sdkObjectMapper.readValue( + getFileAsIOStream(EVENTS_DIR + "/get_event_with_edge_200.json"), Event.class); + + assertEquals(EventSource.EDGE, event.getSource()); + assertNull(event.getIdentification()); + assertNotNull(event.getIpInfo()); + assertNotNull(event.getBotInfo()); + assertEquals( + "edge", + sdkObjectMapper.readTree(sdkObjectMapper.writeValueAsString(event)).get("source").asText()); + } + + @Test + public void deserializeEventWithUnknownSource() throws IOException { + ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper(); + + ObjectNode eventNode = + sdkObjectMapper.readValue( + getFileAsIOStream(EVENTS_DIR + "/get_event_200.json"), ObjectNode.class); + eventNode.put("source", "something_new"); + + Event event = sdkObjectMapper.treeToValue(eventNode, Event.class); + + assertEquals(EventSource.UNSUPPORTED_VALUE_SDK_UPGRADE_REQUIRED, event.getSource()); + } + @TestFactory public Stream deserializeErrorResponses() { ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper(); diff --git a/sdk/src/test/resources/mocks/errors/504_search_timeout_exceeded.json b/sdk/src/test/resources/mocks/errors/504_search_timeout_exceeded.json new file mode 100644 index 00000000..cc5fcbd7 --- /dev/null +++ b/sdk/src/test/resources/mocks/errors/504_search_timeout_exceeded.json @@ -0,0 +1,6 @@ +{ + "error": { + "code": "failed", + "message": "gateway timeout" + } +} diff --git a/sdk/src/test/resources/mocks/webhook/webhook_event.json b/sdk/src/test/resources/mocks/webhook/webhook_event.json index 35567917..c50663be 100644 --- a/sdk/src/test/resources/mocks/webhook/webhook_event.json +++ b/sdk/src/test/resources/mocks/webhook/webhook_event.json @@ -3,9 +3,14 @@ "tags": {}, "timestamp": 1708102555327, "event_id": "1708102555327.NLOjmg", + "source": "device", + "incremental_identification_status": "completed", "url": "https://www.example.com/login?hope{this{works[!", "ip_address": "61.127.217.15", "user_agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ....", + "device": "Other", + "os": "Windows", + "os_version": "7", "client_referrer": "https://example.com/blog/my-article", "browser_details": { "browser_name": "Chrome", @@ -26,14 +31,14 @@ "last_seen_at": 1708102555327 }, "supplementary_id_high_recall": { - "visitor_id": "3HNey93AkBW6CRbxV6xP", + "visitor_id": "0jnGMkPYXX37DqVa4ZIO3f_hr", "visitor_found": true, "confidence": { - "score": 0.97, - "version": "1.1" + "score": 0, + "version": "Not Supported" }, - "first_seen_at": 1708102555327, - "last_seen_at": 1708102555327 + "first_seen_at": 1778086556130, + "last_seen_at": 1778604975494 }, "proximity": { "id": "w1aTfd4MCvl", @@ -111,8 +116,10 @@ "last_seen_at": 1708102555327, "provider": "Massive" }, + "proxy_ml_score": 0.2, "vpn": false, "vpn_confidence": "high", + "vpn_ml_score": 0.2, "vpn_origin_timezone": "Europe/Berlin", "vpn_origin_country": "unknown", "vpn_methods": { @@ -120,10 +127,13 @@ "public_vpn": false, "auxiliary_mobile": false, "os_mismatch": false, - "relay": false + "relay": false, + "ml_prediction": false }, "incognito": false, "tampering": false, + "tampering_confidence": "high", + "tampering_ml_score": 0.3231, "tampering_details": { "anomaly_score": 0.1955, "anti_detect_browser": false @@ -143,6 +153,11 @@ "1_hour": 1, "24_hours": 1 }, + "distinct_linked_id": { + "5_minutes": 1, + "1_hour": 5, + "24_hours": 5 + }, "distinct_country": { "5_minutes": 1, "1_hour": 2, @@ -170,6 +185,11 @@ } }, "developer_tools": false, + "device_details": { + "device_manufacturer": "samsung", + "device_model": "SM-G991U", + "os_version": "13" + }, "mitm_attack": false, "sdk": { "platform": "js", @@ -187,8 +207,6 @@ }, "replayed": false, "high_activity_device": false, - "rare_device": false, - "rare_device_percentile_bucket": "