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
2,101 changes: 1,343 additions & 758 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.skyflow</groupId>
<artifactId>skyflow-java</artifactId>
<version>2.0.0-beta.1</version>
<version>2.0.0-beta.1-dev.9f386ac</version>
<packaging>jar</packaging>

<name>${project.groupId}:${project.artifactId}</name>
Expand Down
40 changes: 32 additions & 8 deletions samples/src/main/java/com/example/vault/DetokenizeExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.skyflow.enums.Env;
import com.skyflow.enums.LogLevel;
import com.skyflow.errors.SkyflowException;
import com.skyflow.vault.tokens.DetokenizeData;
import com.skyflow.vault.tokens.DetokenizeRequest;
import com.skyflow.vault.tokens.DetokenizeResponse;

Expand Down Expand Up @@ -45,17 +46,40 @@ public static void main(String[] args) throws SkyflowException {

// Step 5: Detokenize tokens from the first vault
try {
ArrayList<String> tokens = new ArrayList<>();
tokens.add("<YOUR_TOKEN_VALUE_1>"); // Replace with the first token to detokenize
tokens.add("<YOUR_TOKEN_VALUE_2>"); // Replace with the second token to detokenize
ArrayList<DetokenizeData> detokenizeData1 = new ArrayList<>();
DetokenizeData detokenizeDataRecord1 = new DetokenizeData("<YOUR_TOKEN_VALUE_1>", RedactionType.MASKED); // Replace with a token to detokenize with MASKED redaction
DetokenizeData detokenizeDataRecord2 = new DetokenizeData("<YOUR_TOKEN_VALUE_2>"); // Replace with another token to detokenize with PLAIN_TEXT redaction
detokenizeData1.add(detokenizeDataRecord1);
detokenizeData1.add(detokenizeDataRecord2);

DetokenizeRequest detokenizeRequest = DetokenizeRequest.builder()
.tokens(tokens) // Specify the tokens to detokenize
.continueOnError(true) // Continue processing even if an error occurs for some tokens
DetokenizeRequest detokenizeRequest1 = DetokenizeRequest.builder()
.detokenizeData(detokenizeData1) // Specify the tokens to detokenize with specified redaction types
.continueOnError(true) // Continue processing even if an error occurs for some tokens
.build();

DetokenizeResponse detokenizeResponse = skyflowClient.vault().detokenize(detokenizeRequest); // Perform detokenization
System.out.println("Detokenize Response: " + detokenizeResponse);
DetokenizeResponse detokenizeResponse1 = skyflowClient.vault().detokenize(detokenizeRequest1); // Perform detokenization
System.out.println("Detokenize Response (Vault 1): " + detokenizeResponse1);
} catch (SkyflowException e) {
System.out.println("Error during detokenization in Vault 1:");
e.printStackTrace();
}

// Example 2: Detokenize tokens from the second vault
try {
ArrayList<DetokenizeData> detokenizeData2 = new ArrayList<>();
DetokenizeData detokenizeDataRecord3 = new DetokenizeData("<YOUR_TOKEN_VALUE_3>", RedactionType.DEFAULT); // Replace with a token to detokenize
DetokenizeData detokenizeDataRecord4 = new DetokenizeData("<YOUR_TOKEN_VALUE_4>"); // Replace with another token to detokenize
detokenizeData2.add(detokenizeDataRecord3);
detokenizeData2.add(detokenizeDataRecord4);

DetokenizeRequest detokenizeRequest2 = DetokenizeRequest.builder()
.detokenizeData(detokenizeData2) // Specify the tokens to detokenize with specified redaction types
.continueOnError(false) // Stop processing on the first error
.downloadURL(true) // Specify whether to return URLs for file data type
.build();

DetokenizeResponse detokenizeResponse2 = skyflowClient.vault("<YOUR_VAULT_ID_2>").detokenize(detokenizeRequest2); // Perform detokenization
System.out.println("Detokenize Response (Vault 2): " + detokenizeResponse2);
} catch (SkyflowException e) {
System.out.println("Error during detokenization in Vault: " + e);
}
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/com/skyflow/VaultClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.skyflow.vault.data.InsertRequest;
import com.skyflow.vault.data.UpdateRequest;
import com.skyflow.vault.tokens.ColumnValue;
import com.skyflow.vault.tokens.DetokenizeData;
import com.skyflow.vault.tokens.DetokenizeRequest;
import com.skyflow.vault.tokens.TokenizeRequest;
import io.github.cdimascio.dotenv.Dotenv;
Expand Down Expand Up @@ -85,10 +86,11 @@ protected void updateVaultConfig() throws SkyflowException {
protected V1DetokenizePayload getDetokenizePayload(DetokenizeRequest request) {
V1DetokenizePayload payload = new V1DetokenizePayload();
payload.setContinueOnError(request.getContinueOnError());
for (String token : request.getTokens()) {
payload.setDownloadURL(request.getDownloadURL());
for (DetokenizeData detokenizeDataRecord : request.getDetokenizeData()) {
V1DetokenizeRecordRequest recordRequest = new V1DetokenizeRecordRequest();
recordRequest.setToken(token);
recordRequest.setRedaction(request.getRedactionType().getRedaction());
recordRequest.setToken(detokenizeDataRecord.getToken());
recordRequest.setRedaction(detokenizeDataRecord.getRedactionType().getRedaction());
payload.addDetokenizationParametersItem(recordRequest);
}
return payload;
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/skyflow/errors/ErrorMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ public enum ErrorMessage {
BatchInsertFailure("%s0 Insert operation failed."),

// detokenize
InvalidDataTokens("%s0 Validation error. Invalid data tokens. Specify valid data tokens."),
EmptyDataTokens("%s0 Validation error. Invalid data tokens. Specify at least one data token."),
EmptyTokenInDataTokens("%s0 Validation error. Invalid data tokens. Specify a valid data token."),
InvalidDetokenizeData("%s0 Validation error. Invalid detokenize data. Specify valid detokenize data."),
EmptyDetokenizeData("%s0 Validation error. Invalid data tokens. Specify at least one data token."),
EmptyTokenInDetokenizeData("%s0 Validation error. Invalid data tokens. Specify a valid data token."),

// get interface
IdsKeyError("%s0 Validation error. 'ids' key is missing from the payload. Specify an 'ids' key."),
Expand Down
20 changes: 15 additions & 5 deletions src/main/java/com/skyflow/errors/SkyflowException.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ public SkyflowException(int httpCode, Throwable cause, Map<String, List<String>>
super(cause);
this.httpCode = httpCode;
setRequestId(responseHeaders);
setResponseBody(responseBody);
setResponseBody(responseBody, responseHeaders);
}

private void setResponseBody(String responseBody) {
private void setResponseBody(String responseBody, Map<String, List<String>> responseHeaders) {
try {
if (responseBody != null) {
this.responseBody = JsonParser.parseString(responseBody).getAsJsonObject();
if (this.responseBody.get("error") != null) {
setGrpcCode();
setHttpStatus();
setMessage();
setDetails();
setDetails(responseHeaders);
}
}
} catch (JsonSyntaxException e) {
Expand Down Expand Up @@ -86,9 +86,19 @@ private void setHttpStatus() {
this.httpStatus = statusElement == null ? null : statusElement.getAsString();
}

private void setDetails() {
private void setDetails(Map<String, List<String>> responseHeaders) {
JsonElement detailsElement = ((JsonObject) responseBody.get("error")).get("details");
this.details = detailsElement == null ? null : detailsElement.getAsJsonArray();
List<String> errorFromClientHeader = responseHeaders.get("error-from-client");
if (detailsElement != null) {
this.details = detailsElement.getAsJsonArray();
}
if (errorFromClientHeader != null) {
this.details = this.details == null ? new JsonArray() : this.details;
String errorFromClient = errorFromClientHeader.get(0);
JsonObject detailObject = new JsonObject();
detailObject.addProperty("errorFromClient", errorFromClient);
this.details.add(detailObject);
}
}

public int getHttpCode() {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/skyflow/logs/ErrorLogs.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ public enum ErrorLogs {
INSUFFICIENT_TOKENS_PASSED_FOR_TOKEN_MODE_ENABLE_STRICT("Invalid %s1 request. For tokenMode as ENABLE_STRICT, tokens should be passed for all fields."),
MISMATCH_OF_FIELDS_AND_TOKENS("Invalid %s1 request. Keys for values and tokens are not matching."),
INSERT_RECORDS_REJECTED("Insert request resulted in failure."),
TOKENS_REQUIRED("Invalid %s1 request. Tokens are required."),
EMPTY_OR_NULL_TOKEN_IN_TOKENS("Invalid %s1 request. Token can not be null or empty in tokens at index %s2."),
DETOKENIZE_DATA_REQUIRED("Invalid %s1 request. Detokenize data is required."),
EMPTY_DETOKENIZE_DATA("Invalid %s1 request. Detokenize data can not be empty."),
EMPTY_OR_NULL_TOKEN_IN_DETOKENIZE_DATA("Invalid %s1 request. Token can not be null or empty in detokenize data at index %s2."),
REDACTION_IS_REQUIRED("Invalid %s1 request. Redaction is required."),
DETOKENIZE_REQUEST_REJECTED("Detokenize request resulted in failure."),
IDS_IS_REQUIRED("Invalid %s1 request. Ids are required."),
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/skyflow/utils/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ public final class Constants {
public static final String SDK_METRIC_RUNTIME_DETAILS_PREFIX = "Java@";
public static final String SDK_AUTH_HEADER_KEY = "x-skyflow-authorization";
public static final String SDK_METRICS_HEADER_KEY = "sky-metadata";
public static final String REQUEST_ID_HEADER_KEY = "x-request-id";
}
23 changes: 12 additions & 11 deletions src/main/java/com/skyflow/utils/validations/Validations.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.skyflow.vault.connection.InvokeConnectionRequest;
import com.skyflow.vault.data.*;
import com.skyflow.vault.tokens.ColumnValue;
import com.skyflow.vault.tokens.DetokenizeData;
import com.skyflow.vault.tokens.DetokenizeRequest;
import com.skyflow.vault.tokens.TokenizeRequest;

Expand Down Expand Up @@ -212,26 +213,26 @@ public static void validateCredentials(Credentials credentials) throws SkyflowEx
}

public static void validateDetokenizeRequest(DetokenizeRequest detokenizeRequest) throws SkyflowException {
ArrayList<String> tokens = detokenizeRequest.getTokens();
if (tokens == null) {
ArrayList<DetokenizeData> detokenizeData = detokenizeRequest.getDetokenizeData();
if (detokenizeData == null) {
LogUtil.printErrorLog(Utils.parameterizedString(
ErrorLogs.TOKENS_REQUIRED.getLog(), InterfaceName.DETOKENIZE.getName()
ErrorLogs.DETOKENIZE_DATA_REQUIRED.getLog(), InterfaceName.DETOKENIZE.getName()
));
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidDataTokens.getMessage());
} else if (tokens.isEmpty()) {
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidDetokenizeData.getMessage());
} else if (detokenizeData.isEmpty()) {
LogUtil.printErrorLog(Utils.parameterizedString(
ErrorLogs.EMPTY_TOKENS.getLog(), InterfaceName.DETOKENIZE.getName()
ErrorLogs.EMPTY_DETOKENIZE_DATA.getLog(), InterfaceName.DETOKENIZE.getName()
));
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyDataTokens.getMessage());
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyDetokenizeData.getMessage());
} else {
for (int index = 0; index < tokens.size(); index++) {
String token = tokens.get(index);
for (int index = 0; index < detokenizeData.size(); index++) {
String token = detokenizeData.get(index).getToken();
if (token == null || token.trim().isEmpty()) {
LogUtil.printErrorLog(Utils.parameterizedString(
ErrorLogs.EMPTY_OR_NULL_TOKEN_IN_TOKENS.getLog(),
ErrorLogs.EMPTY_OR_NULL_TOKEN_IN_DETOKENIZE_DATA.getLog(),
InterfaceName.DETOKENIZE.getName(), Integer.toString(index)
));
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyTokenInDataTokens.getMessage());
throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyTokenInDetokenizeData.getMessage());
}
}
}
Expand Down
24 changes: 17 additions & 7 deletions src/main/java/com/skyflow/vault/controller/VaultController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import com.skyflow.enums.RedactionType;
import com.skyflow.errors.SkyflowException;
import com.skyflow.generated.rest.ApiException;
import com.skyflow.generated.rest.ApiResponse;
import com.skyflow.generated.rest.models.*;
import com.skyflow.logs.ErrorLogs;
import com.skyflow.logs.InfoLogs;
import com.skyflow.utils.Constants;
import com.skyflow.utils.logger.LogUtil;
import com.skyflow.utils.validations.Validations;
import com.skyflow.vault.data.*;
Expand All @@ -18,6 +20,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class VaultController extends VaultClient {
private static final Gson gson = new GsonBuilder().serializeNulls().create();
Expand Down Expand Up @@ -111,7 +114,7 @@ private static synchronized HashMap<String, Object> getFormattedQueryRecord(V1Fi
public InsertResponse insert(InsertRequest insertRequest) throws SkyflowException {
LogUtil.printInfoLog(InfoLogs.INSERT_TRIGGERED.getLog());
V1InsertRecordResponse bulkInsertResult = null;
V1BatchOperationResponse batchInsertResult = null;
ApiResponse<V1BatchOperationResponse> batchInsertResult = null;
ArrayList<HashMap<String, Object>> insertedFields = new ArrayList<>();
ArrayList<HashMap<String, Object>> errorFields = new ArrayList<>();
Boolean continueOnError = insertRequest.getContinueOnError();
Expand All @@ -121,15 +124,18 @@ public InsertResponse insert(InsertRequest insertRequest) throws SkyflowExceptio
setBearerToken();
if (continueOnError) {
RecordServiceBatchOperationBody insertBody = super.getBatchInsertRequestBody(insertRequest);
batchInsertResult = super.getRecordsApi().recordServiceBatchOperation(super.getVaultConfig().getVaultId(), insertBody);
batchInsertResult = super.getRecordsApi().recordServiceBatchOperationWithHttpInfo(super.getVaultConfig().getVaultId(), insertBody);
LogUtil.printInfoLog(InfoLogs.INSERT_REQUEST_RESOLVED.getLog());
List<Object> records = batchInsertResult.getResponses();
Map<String, List<String>> responseHeaders = batchInsertResult.getHeaders();
String requestId = responseHeaders.get(Constants.REQUEST_ID_HEADER_KEY).get(0);
List<Object> records = batchInsertResult.getData().getResponses();
for (int index = 0; index < records.size(); index++) {
Object record = records.get(index);
HashMap<String, Object> insertRecord = getFormattedBatchInsertRecord(record, index);
if (insertRecord.containsKey("skyflowId")) {
insertedFields.add(insertRecord);
} else {
insertRecord.put("requestId", requestId);
errorFields.add(insertRecord);
}
}
Expand All @@ -156,23 +162,27 @@ public InsertResponse insert(InsertRequest insertRequest) throws SkyflowExceptio

public DetokenizeResponse detokenize(DetokenizeRequest detokenizeRequest) throws SkyflowException {
LogUtil.printInfoLog(InfoLogs.DETOKENIZE_TRIGGERED.getLog());
V1DetokenizeResponse result = null;
ApiResponse<V1DetokenizeResponse> result = null;
ArrayList<DetokenizeRecordResponse> detokenizedFields = new ArrayList<>();
ArrayList<DetokenizeRecordResponse> errorRecords = new ArrayList<>();
try {
LogUtil.printInfoLog(InfoLogs.VALIDATE_DETOKENIZE_REQUEST.getLog());
Validations.validateDetokenizeRequest(detokenizeRequest);
setBearerToken();
V1DetokenizePayload payload = super.getDetokenizePayload(detokenizeRequest);
result = super.getTokensApi().recordServiceDetokenize(super.getVaultConfig().getVaultId(), payload);
result = super.getTokensApi().recordServiceDetokenizeWithHttpInfo(super.getVaultConfig().getVaultId(), payload);
LogUtil.printInfoLog(InfoLogs.DETOKENIZE_REQUEST_RESOLVED.getLog());
List<V1DetokenizeRecordResponse> records = result.getRecords();
Map<String, List<String>> responseHeaders = result.getHeaders();
String requestId = responseHeaders.get(Constants.REQUEST_ID_HEADER_KEY).get(0);
List<V1DetokenizeRecordResponse> records = result.getData().getRecords();

if (records != null) {
for (V1DetokenizeRecordResponse record : records) {
DetokenizeRecordResponse recordResponse = new DetokenizeRecordResponse(record);
if (record.getError() != null) {
DetokenizeRecordResponse recordResponse = new DetokenizeRecordResponse(record, requestId);
errorRecords.add(recordResponse);
} else {
DetokenizeRecordResponse recordResponse = new DetokenizeRecordResponse(record);
detokenizedFields.add(recordResponse);
}
}
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/skyflow/vault/tokens/DetokenizeData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.skyflow.vault.tokens;

import com.skyflow.enums.RedactionType;

public class DetokenizeData {
private final String token;
private final RedactionType redactionType;

public DetokenizeData(String token) {
this.token = token;
this.redactionType = RedactionType.PLAIN_TEXT;
}

public DetokenizeData(String token, RedactionType redactionType) {
this.token = token;
this.redactionType = redactionType == null ? RedactionType.PLAIN_TEXT : redactionType;
}

public String getToken() {
return this.token;
}

public RedactionType getRedactionType() {
return this.redactionType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@ public class DetokenizeRecordResponse {
private final String value;
private final String type;
private final String error;
private final String requestId;

public DetokenizeRecordResponse(V1DetokenizeRecordResponse record) {
this(record, null);
}

public DetokenizeRecordResponse(V1DetokenizeRecordResponse record, String requestId) {
this.token = record.getToken();
this.value = record.getValue().isEmpty() ? null : record.getValue();
this.type = record.getValueType().getValue().equals("NONE") ? null : record.getValueType().getValue();
this.error = record.getError();
this.requestId = requestId;
}

public String getError() {
Expand All @@ -30,4 +36,8 @@ public String getValue() {
public String getType() {
return type;
}

public String getRequestId() {
return requestId;
}
}
Loading