Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/add-event-source-field.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'java-sdk': minor
---

Add `source` field to `Event` to identify how the event was generated (`device` or `edge`)
2 changes: 1 addition & 1 deletion .schema-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v3.5.1
v3.6.0
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ Class | Method | HTTP request | Description
- [EventRuleActionAllow](docs/EventRuleActionAllow.md)
- [EventRuleActionBlock](docs/EventRuleActionBlock.md)
- [EventSearch](docs/EventSearch.md)
- [EventSource](docs/EventSource.md)
- [EventUpdate](docs/EventUpdate.md)
- [FontPreferences](docs/FontPreferences.md)
- [Geolocation](docs/Geolocation.md)
Expand Down
1 change: 1 addition & 0 deletions docs/Event.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Contains results from Fingerprint Identification and all active Smart Signals. S
|------------ | ------------- | ------------- | -------------|
|**eventId** | **String** | Unique identifier of the user's request. The first portion of the event_id is a unix epoch milliseconds timestamp. | |
|**timestamp** | **Long** | Timestamp of the event with millisecond precision in Unix time. | |
|**source** | [**EventSource**](EventSource.md) | | [optional] |
|**incrementalIdentificationStatus** | [**IncrementalIdentificationStatus**](IncrementalIdentificationStatus.md) | | [optional] |
|**linkedId** | **String** | A customer-provided id that was sent with the request. | [optional] |
|**environmentId** | **String** | Environment Id of the event. | [optional] |
Expand Down
19 changes: 19 additions & 0 deletions docs/EventSource.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@


# EventSource
Identifies how the event was generated.
- `device` - the event was generated by the JS agent or a mobile SDK running on an end-user device.
- `edge` - the event was generated by the Automation Intelligence API (`/edge` endpoint), analyzing a request intercepted at the edge.


## Enum


* `DEVICE` (value: `"device"`)

* `EDGE` (value: `"edge"`)

* `UNSUPPORTED_VALUE_SDK_UPGRADE_REQUIRED` (value: `"unsupported_value_sdk_upgrade_required"`)



Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,16 @@ public static void main(String... args) {
System.exit(1);
}

api.getEvent(oldRequestId);
try {
api.getEvent(oldRequestId);
} catch (ApiException e) {
System.err.println(
"Exception when trying to request old event \""
+ oldRequestId
+ "\":"
+ e.getMessage());
System.exit(1);
}
System.out.println("Old events are good");
} catch (ApiException e) {
System.err.println("Exception when trying to read old data:" + e.getMessage());
Expand Down
19 changes: 19 additions & 0 deletions res/fingerprint-server-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,19 @@ components:
format: int64
examples:
- 1708102555327
EventSource:
type: string
description: >
Identifies how the event was generated.

- `device` - the event was generated by the JS agent or a mobile SDK
running on an end-user device.

- `edge` - the event was generated by the Automation Intelligence API
(`/edge` endpoint), analyzing a request intercepted at the edge.
enum:
- device
- edge
Url:
type: string
examples:
Expand Down Expand Up @@ -3084,6 +3097,12 @@ components:
- android
- ios
- browser
source:
$ref: '#/components/schemas/EventSource'
x-platforms:
- android
- ios
- browser
incremental_identification_status:
$ref: '#/components/schemas/IncrementalIdentificationStatus'
x-platforms:
Expand Down
29 changes: 29 additions & 0 deletions sdk/src/main/java/com/fingerprint/v4/model/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
@JsonPropertyOrder({
Event.JSON_PROPERTY_EVENT_ID,
Event.JSON_PROPERTY_TIMESTAMP,
Event.JSON_PROPERTY_SOURCE,
Event.JSON_PROPERTY_INCREMENTAL_IDENTIFICATION_STATUS,
Event.JSON_PROPERTY_LINKED_ID,
Event.JSON_PROPERTY_ENVIRONMENT_ID,
Expand Down Expand Up @@ -100,6 +101,9 @@ public class Event {
public static final String JSON_PROPERTY_TIMESTAMP = "timestamp";
@jakarta.annotation.Nonnull private Long timestamp;

public static final String JSON_PROPERTY_SOURCE = "source";
@jakarta.annotation.Nullable private EventSource source;

public static final String JSON_PROPERTY_INCREMENTAL_IDENTIFICATION_STATUS =
"incremental_identification_status";

Expand Down Expand Up @@ -337,6 +341,28 @@ public void setTimestamp(@jakarta.annotation.Nonnull Long timestamp) {
this.timestamp = timestamp;
}

public Event source(@jakarta.annotation.Nullable EventSource source) {
this.source = source;
return this;
}

/**
* Get source
* @return source
*/
@jakarta.annotation.Nullable
@JsonProperty(value = JSON_PROPERTY_SOURCE, required = false)
@JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public EventSource getSource() {
return source;
}

@JsonProperty(value = JSON_PROPERTY_SOURCE, required = false)
@JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public void setSource(@jakarta.annotation.Nullable EventSource source) {
this.source = source;
}

public Event incrementalIdentificationStatus(
@jakarta.annotation.Nullable
IncrementalIdentificationStatus incrementalIdentificationStatus) {
Expand Down Expand Up @@ -1751,6 +1777,7 @@ public boolean equals(Object o) {
Event event = (Event) o;
return Objects.equals(this.eventId, event.eventId)
&& Objects.equals(this.timestamp, event.timestamp)
&& Objects.equals(this.source, event.source)
&& Objects.equals(
this.incrementalIdentificationStatus, event.incrementalIdentificationStatus)
&& Objects.equals(this.linkedId, event.linkedId)
Expand Down Expand Up @@ -1821,6 +1848,7 @@ public int hashCode() {
return Objects.hash(
eventId,
timestamp,
source,
incrementalIdentificationStatus,
linkedId,
environmentId,
Expand Down Expand Up @@ -1891,6 +1919,7 @@ public String toString() {
sb.append("class Event {\n");
sb.append(" eventId: ").append(toIndentedString(eventId)).append("\n");
sb.append(" timestamp: ").append(toIndentedString(timestamp)).append("\n");
sb.append(" source: ").append(toIndentedString(source)).append("\n");
sb.append(" incrementalIdentificationStatus: ")
.append(toIndentedString(incrementalIdentificationStatus))
.append("\n");
Expand Down
53 changes: 53 additions & 0 deletions sdk/src/main/java/com/fingerprint/v4/model/EventSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Server API
* Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. The API also supports collection of Automation Intelligence for requests to your server in edge, pre-origin, or middleware contexts.
*
* The version of the OpenAPI document: 4
* Contact: support@fingerprint.com
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

package com.fingerprint.v4.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

/**
* Identifies how the event was generated. - `device` - the event was generated by the JS agent or a mobile SDK running on an end-user device. - `edge` - the event was generated by the Automation Intelligence API (`/edge` endpoint), analyzing a request intercepted at the edge.
*/
public enum EventSource {
DEVICE("device"),

EDGE("edge"),

UNSUPPORTED_VALUE_SDK_UPGRADE_REQUIRED("unsupported_value_sdk_upgrade_required");

private String value;

EventSource(String value) {
this.value = value;
}

@JsonValue
public String getValue() {
return value;
}

@Override
public String toString() {
return String.valueOf(value);
}

@JsonCreator
public static EventSource fromValue(String value) {
for (EventSource b : EventSource.values()) {
if (b.value.equals(value)) {
return b;
}
}
return UNSUPPORTED_VALUE_SDK_UPGRADE_REQUIRED;
}
}
111 changes: 100 additions & 11 deletions sdk/src/test/java/com/fingerprint/v4/SerializationTest.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
package com.fingerprint.v4;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
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 com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fingerprint.v4.model.ErrorCode;
import com.fingerprint.v4.model.ErrorResponse;
import com.fingerprint.v4.model.Event;
import com.fingerprint.v4.model.EventRuleAction;
import com.fingerprint.v4.sdk.JSON;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.TestInstance;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class SerializationTest {

private static final String ERRORS_DIR = "mocks/errors";
private static final String EVENTS_DIR = "mocks/events";

private InputStream getFileAsIOStream(final String fileName) {
InputStream ioStream = this.getClass().getClassLoader().getResourceAsStream(fileName);

Expand All @@ -35,17 +53,6 @@ private static ObjectMapper getMapper() {
return mapper;
}

@Test
public void deserializeSerializeEvent() throws IOException {
ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper();
Event event =
sdkObjectMapper.readValue(
getFileAsIOStream("mocks/events/get_event_200.json"), Event.class);

ObjectMapper springLikeObjectMapper = getMapper();
springLikeObjectMapper.writeValueAsString(event);
}

@Test
public void deserializeEventWithUnknownBotResultValue() throws IOException {
ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper();
Expand Down Expand Up @@ -96,4 +103,86 @@ public void deserializeEventWithUnknownRuleActionTypeValue() throws IOException

assertInstanceOf(EventRuleAction.UnknownEventRuleAction.class, event.getRuleAction());
}

@TestFactory
public Stream<DynamicTest> deserializeErrorResponses() {
ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper();

return listMockFileNames(ERRORS_DIR, name -> true).stream()
.map(
fileName ->
DynamicTest.dynamicTest(
fileName,
() -> {
String resource = ERRORS_DIR + "/" + fileName;

ObjectNode errorNode =
sdkObjectMapper.readValue(getFileAsIOStream(resource), ObjectNode.class);
ErrorResponse errorResponse =
sdkObjectMapper.readValue(
getFileAsIOStream(resource), ErrorResponse.class);

assertNotNull(errorResponse.getError());
assertNotEquals(
ErrorCode.UNSUPPORTED_VALUE_SDK_UPGRADE_REQUIRED,
errorResponse.getError().getCode(),
"Unknown error code in " + resource);
assertEquals(
errorNode.at("/error/code").asText(),
errorResponse.getError().getCode().getValue());
assertEquals(
errorNode.at("/error/message").asText(),
errorResponse.getError().getMessage());

getMapper().writeValueAsString(errorResponse);
}));
}

@TestFactory
public Stream<DynamicTest> deserializeSerializeEvents() {
ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper();

return listMockFileNames(EVENTS_DIR, name -> name.startsWith("get_event")).stream()
.map(
fileName ->
DynamicTest.dynamicTest(
fileName,
() -> {
String resource = EVENTS_DIR + "/" + fileName;

ObjectNode eventNode =
sdkObjectMapper.readValue(getFileAsIOStream(resource), ObjectNode.class);
Event event =
sdkObjectMapper.readValue(getFileAsIOStream(resource), Event.class);

assertEquals(eventNode.get("event_id").asText(), event.getEventId());
assertEquals(
eventNode.get("timestamp").asLong(), event.getTimestamp().longValue());

getMapper().writeValueAsString(event);
}));
}

private List<String> listMockFileNames(String directoryName, Predicate<String> fileNameFilter) {
URL directory = this.getClass().getClassLoader().getResource(directoryName);

if (directory == null) {
throw new IllegalStateException(directoryName + " is not found");
}

File[] files;
try {
files =
new File(directory.toURI())
.listFiles((dir, name) -> name.endsWith(".json") && fileNameFilter.test(name));
} catch (URISyntaxException e) {
throw new IllegalStateException(e);
}

if (files == null || files.length == 0) {
throw new IllegalStateException("No mocks found in " + directoryName);
}

return Arrays.stream(files).map(File::getName).sorted().collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"error": {
"code": "too_many_requests",
"message": "too many search requests"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"error": {
"code": "failed",
"message": "gateway timeout"
}
}
1 change: 1 addition & 0 deletions sdk/src/test/resources/mocks/events/get_event_200.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"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",
Expand Down
Loading