From c7059410887eddef2ab661e80a48da3aa8c2384e Mon Sep 17 00:00:00 2001 From: Aayush Kataria Date: Sat, 18 Sep 2021 14:15:04 -0400 Subject: [PATCH] Fixes JSON property name of ClientEncryptionKeyProperties to match backend (#24160) * Fixes JSON property name of ClientEncryptionKeyProperties to match backend * Adding overloaded methods for CRUD operations * Fixes JSON property name of ClientEncryptionKeyProperties to match backend * Adding overloaded methods for CRUD operations * Resolving comments Co-authored-by: Aayush Kataria --- .../CosmosEncryptionAsyncContainer.java | 342 +++++++++++++++--- .../encryption/CosmosEncryptionContainer.java | 183 +++++++--- .../encryption/DotNetCompatibleTest.java | 2 +- .../EncryptionAsyncApiCrudTest.java | 110 +++++- .../ClientEncryptionKey1.json | 2 +- .../ClientEncryptionKey2.json | 2 +- .../implementation/ClientEncryptionKey.java | 6 +- .../cosmos/implementation/Constants.java | 2 +- 8 files changed, 541 insertions(+), 108 deletions(-) diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionAsyncContainer.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionAsyncContainer.java index 07fa57363e121..e0c2eef64b534 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionAsyncContainer.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionAsyncContainer.java @@ -100,13 +100,54 @@ EncryptionProcessor getEncryptionProcessor() { } /** - * create item and encrypts the requested fields + * Creates an item. + *

+ * After subscription the operation will be performed. The {@link Mono} upon + * successful completion will contain a single resource response with the + * created Cosmos item. In case of failure the {@link Mono} will error. + * + * @param the type parameter. + * @param item the Cosmos item represented as a POJO or Cosmos item object. + * @return an {@link Mono} containing the single resource response with the + * created Cosmos item or an error. + */ + @SuppressWarnings("unchecked") + public Mono> createItem(T item) { + return createItem(item, new CosmosItemRequestOptions()); + } + + /** + * Creates a Cosmos item. + * + * @param the type parameter. + * @param item the item. + * @param requestOptions the item request options. + * @return an {@link Mono} containing the single resource response with the created Cosmos item or an error. + */ + @SuppressWarnings("unchecked") + public Mono> createItem(T item, + CosmosItemRequestOptions requestOptions) { + Preconditions.checkNotNull(item, "item"); + if (requestOptions == null) { + requestOptions = new CosmosItemRequestOptions(); + } + byte[] streamPayload = cosmosSerializerToStream(item); + return createItemHelper(streamPayload, null, requestOptions,(Class) item.getClass(), false ); + + } + + /** + * Creates an item. + *

+ * After subscription the operation will be performed. The {@link Mono} upon + * successful completion will contain a single resource response with the + * created Cosmos item. In case of failure the {@link Mono} will error. * - * @param item the Cosmos item represented as a POJO or Cosmos item object. - * @param partitionKey the partition key. - * @param requestOptions request option - * @param serialization class type - * @return a {@link Mono} containing the Cosmos item resource response. + * @param the type parameter. + * @param item the Cosmos item represented as a POJO or Cosmos item object. + * @param partitionKey the partition key. + * @param requestOptions the request options. + * @return an {@link Mono} containing the single resource response with the created Cosmos item or an error. */ @SuppressWarnings("unchecked") public Mono> createItem(T item, @@ -124,32 +165,124 @@ public Mono> createItem(T item, return createItemHelper(streamPayload, partitionKey, requestOptions, (Class) item.getClass(), false); } + /** + * Deletes an item. + *

+ * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain a single Cosmos item response for the deleted item. + * + * @param itemId the item id. + * @param partitionKey the partition key. + * @return an {@link Mono} containing the Cosmos item resource response. + */ + public Mono> deleteItem(String itemId, PartitionKey partitionKey) { + return deleteItem(itemId, partitionKey, new CosmosItemRequestOptions()); + } + /** * Deletes the item. *

- * After subscription the operation will be performed. The {@link Mono} upon successful completion will contain a - * single Cosmos item response with the deleted item. + * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain a single Cosmos item response for the deleted item. * - * @param itemId id of the item. + * @param itemId id of the item. * @param partitionKey partitionKey of the item. - * @param options the request options. - * @return a {@link Mono} containing the Cosmos item resource response. + * @param requestOptions the request options. + * @return an {@link Mono} containing the Cosmos item resource response. */ public Mono> deleteItem(String itemId, PartitionKey partitionKey, - CosmosItemRequestOptions options) { + CosmosItemRequestOptions requestOptions) { + + return container.deleteItem(itemId, partitionKey, requestOptions); + } + + /** + * Deletes the item. + *

+ * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain a single Cosmos item response for the deleted item. + * + * @param the type parameter. + * @param item item to be deleted. + * @param requestOptions the request options. + * @return an {@link Mono} containing the Cosmos item resource response. + */ + public Mono> deleteItem(T item, CosmosItemRequestOptions requestOptions) { + return container.deleteItem(item, requestOptions); + } + + /** + * Deletes all items in the Container with the specified partitionKey value. + * Starts an asynchronous Cosmos DB background operation which deletes all items in the Container with the specified value. + * The asynchronous Cosmos DB background operation runs using a percentage of user RUs. + * + * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain a single Cosmos item response for all the deleted items. + * + * @param partitionKey partitionKey of the item. + * @param requestOptions the request options. + * @return an {@link Mono} containing the Cosmos item resource response. + */ + @Beta(value = Beta.SinceVersion.V1, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public Mono> deleteAllItemsByPartitionKey(PartitionKey partitionKey, CosmosItemRequestOptions requestOptions) { + if (requestOptions == null) { + requestOptions = new CosmosItemRequestOptions(); + } + return container.deleteAllItemsByPartitionKey(partitionKey, requestOptions); + } - return container.deleteItem(itemId, partitionKey, options); + /** + * Upserts an item. + *

+ * After subscription the operation will be performed. The {@link Mono} upon + * successful completion will contain a single resource response with the + * upserted item. In case of failure the {@link Mono} will error. + * + * @param the type parameter. + * @param item the item represented as a POJO or Item object to upsert. + * @return an {@link Mono} containing the single resource response with the upserted item or an error. + */ + @SuppressWarnings("unchecked") + public Mono> upsertItem(T item) { + return upsertItem(item, new CosmosItemRequestOptions()); } /** - * upserts item and encrypts the requested fields + * Upserts an item. + *

+ * After subscription the operation will be performed. The {@link Mono} upon + * successful completion will contain a single resource response with the + * upserted item. In case of failure the {@link Mono} will error. * - * @param item the Cosmos item represented as a POJO or Cosmos item object. - * @param partitionKey the partition key. - * @param requestOptions request option - * @param serialization class type - * @return a {@link Mono} containing the Cosmos item resource response. + * @param the type parameter. + * @param item the item represented as a POJO or Item object to upsert. + * @param requestOptions the request options. + * @return an {@link Mono} containing the single resource response with the upserted item or an error. + */ + @SuppressWarnings("unchecked") + public Mono> upsertItem(T item, CosmosItemRequestOptions requestOptions) { + Preconditions.checkNotNull(item, "item"); + if (requestOptions == null) { + requestOptions = new CosmosItemRequestOptions(); + } + + byte[] streamPayload = cosmosSerializerToStream(item); + return upsertItemHelper(streamPayload, null, requestOptions, (Class) item.getClass(), false); + } + + /** + * Upserts an item. + *

+ * After subscription the operation will be performed. The {@link Mono} upon + * successful completion will contain a single resource response with the + * upserted item. In case of failure the {@link Mono} will error. + * + * @param the type parameter. + * @param item the item represented as a POJO or Item object to upsert. + * @param partitionKey the partition key. + * @param requestOptions the request options. + * @return an {@link Mono} containing the single resource response with the upserted item or an error. */ @SuppressWarnings("unchecked") public Mono> upsertItem(T item, @@ -169,14 +302,33 @@ public Mono> upsertItem(T item, } /** - * replaces item and encrypts the requested fields + * Replaces an item with the passed in item and encrypts the requested fields. + *

+ * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain a single Cosmos item response with the replaced item. * - * @param item the Cosmos item represented as a POJO or Cosmos item object. - * @param itemId the item id. - * @param partitionKey the partition key. - * @param requestOptions request option - * @param serialization class type - * @return a {@link Mono} containing the Cosmos item resource response. + * @param the type parameter. + * @param item the item to replace (containing the item id). + * @param itemId the item id. + * @param partitionKey the partition key. + * @return an {@link Mono} containing the Cosmos item resource response with the replaced item or an error. + */ + public Mono> replaceItem(T item, String itemId, PartitionKey partitionKey) { + return replaceItem(item, itemId, partitionKey, new CosmosItemRequestOptions()); + } + + /** + * Replaces an item with the passed in item and encrypts the requested fields. + *

+ * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain a single Cosmos item response with the replaced item. + * + * @param the type parameter. + * @param item the item to replace (containing the item id). + * @param itemId the item id. + * @param partitionKey the partition key. + * @param requestOptions the request comosItemRequestOptions. + * @return an {@link Mono} containing the Cosmos item resource response with the replaced item or an error. */ @SuppressWarnings("unchecked") public Mono> replaceItem(T item, @@ -197,14 +349,33 @@ public Mono> replaceItem(T item, } /** - * Reads item and decrypt the encrypted fields + * Reads an item. + *

+ * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain an item response with the read item. + * + * @param the type parameter. + * @param id the item id. + * @param partitionKey the partition key. + * @param classType the item type. + * @return an {@link Mono} containing the Cosmos item response with the read item or an error. + */ + public Mono> readItem(String id, PartitionKey partitionKey, Class classType) { + return readItem(id, partitionKey, ModelBridgeInternal.createCosmosItemRequestOptions(partitionKey), classType); + } + + /** + * Reads an item using a configured {@link CosmosItemRequestOptions}. + *

+ * After subscription the operation will be performed. + * The {@link Mono} upon successful completion will contain a Cosmos item response with the read item. * - * @param id item id - * @param partitionKey the partition key. - * @param requestOptions request options - * @param classType deserialization class type - * @param type - * @return a {@link Mono} containing the Cosmos item resource response. + * @param the type parameter. + * @param id the item id. + * @param partitionKey the partition key. + * @param requestOptions the request {@link CosmosItemRequestOptions}. + * @param classType the item type. + * @return an {@link Mono} containing the Cosmos item response with the read item or an error. */ public Mono> readItem(String id, PartitionKey partitionKey, @@ -221,44 +392,84 @@ public Mono> readItem(String id, .map(bytes -> this.responseFactory.createItemResponse(cosmosItemResponse, classType))); } + /** + * Query for items in the current container. + *

+ * After subscription the operation will be performed. The {@link CosmosPagedFlux} will + * contain one or several feed response of the obtained items. In case of + * failure the {@link CosmosPagedFlux} will error. + * + * @param the type parameter. + * @param query the query. + * @param classType the class type. + * @return a {@link CosmosPagedFlux} containing one or several feed response pages of the obtained items or an + * error. + */ + public CosmosPagedFlux queryItems(String query, Class classType) { + return this.queryItems(new SqlQuerySpec(query), classType); + } + /** * Query for items in the current container using a string. *

- * After subscription the operation will be performed. The {@link CosmosPagedFlux} will contain one or several feed - * response of the obtained items. In case of failure the {@link CosmosPagedFlux} will error. + * After subscription the operation will be performed. The {@link CosmosPagedFlux} will + * contain one or several feed response of the obtained items. In case of + * failure the {@link CosmosPagedFlux} will error. * - * @param the type parameter. - * @param query the query text. - * @param options the query request options. + * @param the type parameter. + * @param query the query. + * @param requestOptions the query request options. * @param classType the class type. * @return a {@link CosmosPagedFlux} containing one or several feed response pages of the obtained items or an * error. */ - public CosmosPagedFlux queryItems(String query, CosmosQueryRequestOptions options, + public CosmosPagedFlux queryItems(String query, CosmosQueryRequestOptions requestOptions, Class classType) { - return this.queryItems(new SqlQuerySpec(query), new CosmosQueryRequestOptions(), classType); + if (requestOptions == null) { + requestOptions = new CosmosQueryRequestOptions(); + } + + return this.queryItems(new SqlQuerySpec(query), requestOptions, classType); } /** * Query for items in the current container using a {@link SqlQuerySpec}. *

- * After subscription the operation will be performed. The {@link CosmosPagedFlux} will contain one or several feed - * response of the obtained items. In case of failure the {@link CosmosPagedFlux} will error. + * After subscription the operation will be performed. The {@link CosmosPagedFlux} will + * contain one or several feed response of the obtained items. In case of + * failure the {@link CosmosPagedFlux} will error. * - * @param the type parameter. - * @param query the query. - * @param options the query request options. + * @param the type parameter. + * @param querySpec the SQL query specification. * @param classType the class type. * @return a {@link CosmosPagedFlux} containing one or several feed response pages of the obtained items or an * error. */ - public CosmosPagedFlux queryItems(SqlQuerySpec query, CosmosQueryRequestOptions options, + public CosmosPagedFlux queryItems(SqlQuerySpec querySpec, Class classType) { + return queryItemsHelper(querySpec, new CosmosQueryRequestOptions(), classType, false); + } + + /** + * Query for items in the current container using a {@link SqlQuerySpec} and {@link CosmosQueryRequestOptions}. + *

+ * After subscription the operation will be performed. The {@link Flux} will + * contain one or several feed response of the obtained items. In case of + * failure the {@link CosmosPagedFlux} will error. + * + * @param the type parameter. + * @param query the SQL query specification. + * @param requestOptions the query request options. + * @param classType the class type. + * @return a {@link CosmosPagedFlux} containing one or several feed response pages of the obtained items or an + * error. + */ + public CosmosPagedFlux queryItems(SqlQuerySpec query, CosmosQueryRequestOptions requestOptions, Class classType) { - if (options == null) { - options = new CosmosQueryRequestOptions(); + if (requestOptions == null) { + requestOptions = new CosmosQueryRequestOptions(); } - return queryItemsHelper(query, options, classType,false); + return queryItemsHelper(query, requestOptions, classType,false); } /** @@ -297,6 +508,19 @@ public CosmosPagedFlux queryItemsOnEncryptedProperties(SqlQuerySpecWithEn } } + /** + * Query for items in the change feed of the current container using the {@link CosmosChangeFeedRequestOptions}. + *

+ * After subscription the operation will be performed. The {@link Flux} will + * contain one or several feed response of the obtained items. In case of + * failure the {@link CosmosPagedFlux} will error. + * + * @param the type parameter. + * @param options the change feed request options. + * @param classType the class type. + * @return a {@link CosmosPagedFlux} containing one or several feed response pages of the obtained + * items or an error. + */ @Beta(value = Beta.SinceVersion.V1, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) public CosmosPagedFlux queryChangeFeed(CosmosChangeFeedRequestOptions options, Class classType) { @@ -410,7 +634,7 @@ private Mono> createItemHelper(byte[] streamPayload, boolean isRetry) { this.setRequestHeaders(requestOptions); return this.encryptionProcessor.encrypt(streamPayload) - .flatMap(encryptedPayload -> this.container.createItem( + .flatMap(encryptedPayload -> createItemHelper( encryptedPayload, partitionKey, requestOptions) @@ -432,6 +656,14 @@ private Mono> createItemHelper(byte[] streamPayload, })); } + private Mono> createItemHelper(byte[] encryptedPayload, + PartitionKey partitionKey, + CosmosItemRequestOptions requestOptions) { + return partitionKey != null + ? this.container.createItem(encryptedPayload, partitionKey, requestOptions) + : this.container.createItem(encryptedPayload, requestOptions); + } + private Mono> upsertItemHelper(byte[] streamPayload, PartitionKey partitionKey, CosmosItemRequestOptions requestOptions, @@ -439,7 +671,7 @@ private Mono> upsertItemHelper(byte[] streamPayload, boolean isRetry) { this.setRequestHeaders(requestOptions); return this.encryptionProcessor.encrypt(streamPayload) - .flatMap(encryptedPayload -> this.container.upsertItem( + .flatMap(encryptedPayload -> upsertItemHelper( encryptedPayload, partitionKey, requestOptions) @@ -461,6 +693,14 @@ private Mono> upsertItemHelper(byte[] streamPayload, })); } + private Mono> upsertItemHelper(byte[] encryptedPayload, + PartitionKey partitionKey, + CosmosItemRequestOptions requestOptions) { + return partitionKey != null + ? this.container.upsertItem(encryptedPayload, partitionKey, requestOptions) + : this.container.upsertItem(encryptedPayload, requestOptions); + } + private Mono> replaceItemHelper(byte[] streamPayload, String itemId, PartitionKey partitionKey, diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionContainer.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionContainer.java index 7ebf4e8468b2b..c27731ceea3f6 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionContainer.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/encryption/CosmosEncryptionContainer.java @@ -39,13 +39,41 @@ public class CosmosEncryptionContainer { } /** - * create item and encrypts the requested fields + * Creates a new item synchronously and returns its respective Cosmos item response. * - * @param item the Cosmos item represented as a POJO or Cosmos item object. - * @param partitionKey the partition key. - * @param requestOptions request option - * @param serialization class type - * @return the Cosmos item resource response. + * @param the type parameter + * @param item the item + * @return the Cosmos item response + */ + public CosmosItemResponse createItem(T item) { + return this.blockItemResponse(this.cosmosEncryptionAsyncContainer.createItem(item)); + } + + /** + * Creates a new item synchronously and returns its respective Cosmos item response + * while specifying additional options. + *

+ * The partition key value will be automatically extracted from the item's content. + * + * @param the type parameter. + * @param item the item. + * @param options the options. + * @return the cosmos item response. + */ + + public CosmosItemResponse createItem(T item, CosmosItemRequestOptions options) { + return this.blockItemResponse(this.cosmosEncryptionAsyncContainer.createItem(item, options)); + } + + /** + * Creates a new item synchronously and returns its respective Cosmos item response + * while specifying additional options. + * + * @param the type parameter. + * @param item the item. + * @param partitionKey the partition key. + * @param requestOptions the options. + * @return the Cosmos item response. */ @SuppressWarnings("unchecked") public CosmosItemResponse createItem(T item, @@ -55,12 +83,12 @@ public CosmosItemResponse createItem(T item, } /** - * Deletes the item. + * Deletes an item in the current container. * - * @param itemId id of the item. - * @param partitionKey partitionKey of the item. - * @param requestOptions the request options. - * @return the Cosmos item resource response. + * @param itemId the item id. + * @param partitionKey the partition key. + * @param requestOptions the options. + * @return the Cosmos item response. */ public CosmosItemResponse deleteItem(String itemId, PartitionKey partitionKey, @@ -70,13 +98,62 @@ public CosmosItemResponse deleteItem(String itemId, } /** - * upserts item and encrypts the requested fields + * Deletes an item in the current container. + * + * @param the type parameter. + * @param item the item to be deleted. + * @param options the options. + * @return the Cosmos item response. + */ + public CosmosItemResponse deleteItem(T item, CosmosItemRequestOptions options) { + return this.blockDeleteItemResponse(this.cosmosEncryptionAsyncContainer.deleteItem(item, options)); + } + + /** + * Deletes all items in the Container with the specified partitionKey value. + * Starts an asynchronous Cosmos DB background operation which deletes all items in the Container with the specified value. + * The asynchronous Cosmos DB background operation runs using a percentage of user RUs. + * + * @param partitionKey the partition key. + * @param options the options. + * @return the Cosmos item response + */ + @Beta(value = Beta.SinceVersion.V1, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) + public CosmosItemResponse deleteAllItemsByPartitionKey(PartitionKey partitionKey, CosmosItemRequestOptions options) { + return this.blockDeleteItemResponse(this.cosmosEncryptionAsyncContainer.deleteAllItemsByPartitionKey(partitionKey, options)); + } + + /** + * Upserts an Cosmos item in the current container. * - * @param item the Cosmos item represented as a POJO or Cosmos item object. - * @param partitionKey the partition key. - * @param requestOptions request option - * @param serialization class type - * @return the Cosmos item resource response. + * @param the type parameter. + * @param item the item. + * @return the Cosmos item response. + */ + public CosmosItemResponse upsertItem(T item) { + return this.blockItemResponse(this.cosmosEncryptionAsyncContainer.upsertItem(item)); + } + + /** + * Upserts a item Cosmos sync item while specifying additional options. + * + * @param the type parameter. + * @param item the item. + * @param options the options. + * @return the Cosmos item response. + */ + public CosmosItemResponse upsertItem(T item, CosmosItemRequestOptions options) { + return this.blockItemResponse(this.cosmosEncryptionAsyncContainer.upsertItem(item, options)); + } + + /** + * Upserts a item Cosmos sync item while specifying additional options. + * + * @param the type parameter. + * @param item the item. + * @param partitionKey the partitionKey. + * @param requestOptions the options. + * @return the Cosmos item response. */ @SuppressWarnings("unchecked") public CosmosItemResponse upsertItem(T item, @@ -86,14 +163,14 @@ public CosmosItemResponse upsertItem(T item, } /** - * replaces item and encrypts the requested fields + * Replaces an item in the current container. * - * @param item the Cosmos item represented as a POJO or Cosmos item object. - * @param itemId the item id. - * @param partitionKey the partition key. - * @param requestOptions request option - * @param serialization class type - * @return the Cosmos item resource response. + * @param the type parameter. + * @param item the item. + * @param itemId the item id. + * @param partitionKey the partition key. + * @param requestOptions the options. + * @return the Cosmos item response. */ @SuppressWarnings("unchecked") public CosmosItemResponse replaceItem(T item, @@ -105,14 +182,30 @@ public CosmosItemResponse replaceItem(T item, } /** - * Reads item and decrypt the encrypted fields + * Reads an item in the current container. * - * @param id item id - * @param partitionKey the partition key. - * @param requestOptions request options - * @param classType deserialization class type - * @param type - * @return the Cosmos item resource response. + * @param the type parameter. + * @param id the item id. + * @param partitionKey the partition key. + * @param classType the class type of item. + * @return the Cosmos item response. + */ + public CosmosItemResponse readItem(String id, PartitionKey partitionKey, Class classType) { + return this.blockItemResponse(this.cosmosEncryptionAsyncContainer.readItem(id, + partitionKey, + new CosmosItemRequestOptions(), + classType)); + } + + /** + * Reads an item in the current container while specifying additional options. + * + * @param the type parameter. + * @param id the item id. + * @param partitionKey the partition key. + * @param requestOptions the options. + * @param classType the class type of item. + * @return the Cosmos item response. */ public CosmosItemResponse readItem(String id, PartitionKey partitionKey, @@ -123,33 +216,33 @@ public CosmosItemResponse readItem(String id, } /** - * Query for items in the current container using a string. + * Query items in the current container returning the results as {@link CosmosPagedIterable}. * - * @param the type parameter. - * @param query the query text. - * @param options the query request options. + * @param the type parameter. + * @param query the query. + * @param requestOptions the options. * @param classType the class type. - * @return a {@link CosmosPagedIterable}. + * @return the {@link CosmosPagedIterable}. */ - public CosmosPagedIterable queryItems(String query, CosmosQueryRequestOptions options, + public CosmosPagedIterable queryItems(String query, CosmosQueryRequestOptions requestOptions, Class classType) { - return getCosmosPagedIterable(this.cosmosEncryptionAsyncContainer.queryItems(query, options, classType)); + return getCosmosPagedIterable(this.cosmosEncryptionAsyncContainer.queryItems(query, requestOptions, classType)); } /** - * Query for items in the current container using a {@link SqlQuerySpec}. + * Query items in the current container returning the results as {@link CosmosPagedIterable}. * - * @param the type parameter. - * @param query the query. - * @param options the query request options. + * @param the type parameter. + * @param query the query spec. + * @param requestOptions the options. * @param classType the class type. - * @return a {@link CosmosPagedIterable}. + * @return the {@link CosmosPagedIterable}. */ public CosmosPagedIterable queryItems(SqlQuerySpec query, - CosmosQueryRequestOptions options, + CosmosQueryRequestOptions requestOptions, Class classType) { - return getCosmosPagedIterable(this.cosmosEncryptionAsyncContainer.queryItems(query, options, classType)); + return getCosmosPagedIterable(this.cosmosEncryptionAsyncContainer.queryItems(query, requestOptions, classType)); } /** diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/DotNetCompatibleTest.java b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/DotNetCompatibleTest.java index f386bbb7cd2a8..6fc4601a10077 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/DotNetCompatibleTest.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/DotNetCompatibleTest.java @@ -107,7 +107,7 @@ public void createItemEncrypt_readItemDecrypt() throws IOException { private CosmosClientEncryptionKeyProperties getEncryptionPropertiesFromJsonFile(String filePath) throws IOException { JsonNode node = MAPPER.readTree(new File(filePath)); String clientEncryptionKey = node.get("id").asText(); - String algorithm = node.get("encryptionAlgorithmId").asText(); + String algorithm = node.get("encryptionAlgorithm").asText(); byte[] wrappedDataEncryptionKey = MAPPER.treeToValue(node.get("wrappedDataEncryptionKey"), byte[].class); ObjectNode objectNode = (ObjectNode) node.get("keyWrapMetadata"); EncryptionKeyWrapMetadata keyWrapMetadata = MAPPER.convertValue(objectNode, EncryptionKeyWrapMetadata.class); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/EncryptionAsyncApiCrudTest.java b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/EncryptionAsyncApiCrudTest.java index 2e9ff01435012..3e692bed29210 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/EncryptionAsyncApiCrudTest.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/encryption/EncryptionAsyncApiCrudTest.java @@ -24,6 +24,7 @@ import com.azure.cosmos.models.SqlParameter; import com.azure.cosmos.models.SqlQuerySpec; import com.azure.cosmos.util.CosmosPagedFlux; +import com.azure.cosmos.util.CosmosPagedIterable; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.microsoft.data.encryption.cryptography.EncryptionKeyStoreProvider; @@ -35,12 +36,9 @@ import org.testng.annotations.Test; import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import java.util.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; +import static org.assertj.core.api.Assertions.*; public class EncryptionAsyncApiCrudTest extends TestSuiteBase { private CosmosAsyncClient client; @@ -579,6 +577,108 @@ public void batchExecutionWithOptionsApi() { validateResponse(batchResponse.getResults().get(3).getItem(EncryptionPojo.class), createPojo); } + @Test(groups = {"encryption"}, timeOut = TIMEOUT) + public void crudOnDifferentOverload() { + List actualProperties = new ArrayList<>(); + // Read item + EncryptionPojo properties = getItem(UUID.randomUUID().toString()); + CosmosItemResponse itemResponse = cosmosEncryptionAsyncContainer.createItem(properties).block(); + assertThat(itemResponse.getRequestCharge()).isGreaterThan(0); + EncryptionPojo responseItem = itemResponse.getItem(); + validateResponse(properties, responseItem); + actualProperties.add(properties); + + properties = getItem(UUID.randomUUID().toString()); + CosmosItemResponse itemResponse1 = cosmosEncryptionAsyncContainer.createItem(properties, new CosmosItemRequestOptions()).block(); + assertThat(itemResponse1.getRequestCharge()).isGreaterThan(0); + EncryptionPojo responseItem1 = itemResponse1.getItem(); + validateResponse(properties, responseItem1); + actualProperties.add(properties); + + //Upsert Item + properties = getItem(UUID.randomUUID().toString()); + CosmosItemResponse upsertResponse1 = cosmosEncryptionAsyncContainer.upsertItem(properties).block(); + assertThat(upsertResponse1.getRequestCharge()).isGreaterThan(0); + EncryptionPojo responseItem2 = upsertResponse1.getItem(); + validateResponse(properties, responseItem2); + actualProperties.add(properties); + + properties = getItem(UUID.randomUUID().toString()); + CosmosItemResponse upsertResponse2 = cosmosEncryptionAsyncContainer.upsertItem(properties, new CosmosItemRequestOptions()).block(); + assertThat(upsertResponse2.getRequestCharge()).isGreaterThan(0); + EncryptionPojo responseItem3 = upsertResponse2.getItem(); + validateResponse(properties, responseItem3); + actualProperties.add(properties); + + //Read Item + EncryptionPojo readItem = cosmosEncryptionAsyncContainer.readItem(actualProperties.get(0).getId(), + new PartitionKey(actualProperties.get(0).getMypk()), EncryptionPojo.class).block().getItem(); + validateResponse(actualProperties.get(0), readItem); + + //Query Item + String query = String.format("SELECT * from c where c.id = '%s'", actualProperties.get(1).getId()); + + CosmosPagedFlux feedResponseIterator = + cosmosEncryptionAsyncContainer.queryItems(query, EncryptionPojo.class); + List feedResponse = feedResponseIterator.byPage().blockFirst().getResults(); + assertThat(feedResponse.size()).isGreaterThanOrEqualTo(1); + for (EncryptionPojo pojo : feedResponse) { + if (pojo.getId().equals(actualProperties.get(1).getId())) { + validateResponse(pojo, responseItem1); + } + } + + CosmosQueryRequestOptions cosmosQueryRequestOptions1 = new CosmosQueryRequestOptions(); + + CosmosPagedFlux feedResponseIterator1 = + cosmosEncryptionAsyncContainer.queryItems(query, cosmosQueryRequestOptions1, EncryptionPojo.class); + List feedResponse1 = feedResponseIterator1.byPage().blockFirst().getResults(); + assertThat(feedResponse1.size()).isGreaterThanOrEqualTo(1); + for (EncryptionPojo pojo : feedResponse1) { + if (pojo.getId().equals(actualProperties.get(1).getId())) { + validateResponse(pojo, responseItem1); + } + } + + CosmosQueryRequestOptions cosmosQueryRequestOptions2 = new CosmosQueryRequestOptions(); + SqlQuerySpec querySpec = new SqlQuerySpec(query); + + CosmosPagedFlux feedResponseIterator2 = + cosmosEncryptionAsyncContainer.queryItems(querySpec, cosmosQueryRequestOptions2, EncryptionPojo.class); + List feedResponse2 = feedResponseIterator2.byPage().blockFirst().getResults(); + assertThat(feedResponse2.size()).isGreaterThanOrEqualTo(1); + for (EncryptionPojo pojo : feedResponse2) { + if (pojo.getId().equals(actualProperties.get(1).getId())) { + validateResponse(pojo, responseItem1); + } + } + + //Replace Item + CosmosItemResponse replaceResponse = + cosmosEncryptionAsyncContainer.replaceItem(actualProperties.get(2), actualProperties.get(2).getId(), + new PartitionKey(actualProperties.get(2).getMypk())).block(); + assertThat(upsertResponse1.getRequestCharge()).isGreaterThan(0); + responseItem = replaceResponse.getItem(); + validateResponse(actualProperties.get(2), responseItem); + + //Delete Item + CosmosItemResponse deleteResponse = cosmosEncryptionAsyncContainer.deleteItem(actualProperties.get(0).getId(), + new PartitionKey(actualProperties.get(0).getMypk())).block(); + assertThat(deleteResponse.getStatusCode()).isEqualTo(204); + + CosmosItemResponse deleteResponse1 = cosmosEncryptionAsyncContainer.deleteItem(actualProperties.get(1).getId(), + new PartitionKey(actualProperties.get(1).getMypk()), new CosmosItemRequestOptions()).block(); + assertThat(deleteResponse1.getStatusCode()).isEqualTo(204); + + CosmosItemResponse deleteResponse2 = cosmosEncryptionAsyncContainer.deleteItem(actualProperties.get(2), + new CosmosItemRequestOptions()).block(); + assertThat(deleteResponse2.getStatusCode()).isEqualTo(204); + + CosmosItemResponse deleteResponse3 = cosmosEncryptionAsyncContainer.deleteAllItemsByPartitionKey(new PartitionKey(actualProperties.get(3).getMypk()), + new CosmosItemRequestOptions()).block(); + assertThat(deleteResponse3.getStatusCode()).isEqualTo(200); + } + static void validateResponseWithOneFieldEncryption(EncryptionPojo originalItem, EncryptionPojo result) { assertThat(result.getId()).isEqualTo(originalItem.getId()); assertThat(result.getNonSensitive()).isEqualTo(originalItem.getNonSensitive()); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey1.json b/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey1.json index 526b9f45bd084..7cccecf1281ed 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey1.json +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey1.json @@ -1,6 +1,6 @@ { "id": "key1", - "encryptionAlgorithmId": "AEAD_AES_256_CBC_HMAC_SHA256", + "encryptionAlgorithm": "AEAD_AES_256_CBC_HMAC_SHA256", "wrappedDataEncryptionKey": "S84PieiyZNyHxeuUuX5IXSV2KOktpt02tQM4QLhm8dI=", "keyWrapMetadata": { "type": "TESTKEYSTORE_VAULT", diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey2.json b/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey2.json index 3c306fa5ad32c..ea95ed3a01720 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey2.json +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/resources/dotnetEncryption/ClientEncryptionKey2.json @@ -1,6 +1,6 @@ { "id": "key2", - "encryptionAlgorithmId": "AEAD_AES_256_CBC_HMAC_SHA256", + "encryptionAlgorithm": "AEAD_AES_256_CBC_HMAC_SHA256", "wrappedDataEncryptionKey": "ydjdH/ANRnjhldUgFGW9X/cohiFKuNom5tGm24aBgZU=", "keyWrapMetadata": { "type": "TESTKEYSTORE_VAULT", diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ClientEncryptionKey.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ClientEncryptionKey.java index 4f0d5a059f760..cb66d544a6f09 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ClientEncryptionKey.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ClientEncryptionKey.java @@ -34,8 +34,8 @@ public ClientEncryptionKey(String jsonString) { public String getEncryptionAlgorithm() { if (this.encryptionAlgorithm == null) { - if (super.has(Constants.Properties.ENCRYPTION_ALGORITHM_ID)) { - this.encryptionAlgorithm = super.getString(Constants.Properties.ENCRYPTION_ALGORITHM_ID); + if (super.has(Constants.Properties.ENCRYPTION_ALGORITHM)) { + this.encryptionAlgorithm = super.getString(Constants.Properties.ENCRYPTION_ALGORITHM); } } return this.encryptionAlgorithm; @@ -43,7 +43,7 @@ public String getEncryptionAlgorithm() { public void setEncryptionAlgorithm(String encryptionAlgorithm) { this.encryptionAlgorithm = encryptionAlgorithm; - BridgeInternal.setProperty(this, Constants.Properties.ENCRYPTION_ALGORITHM_ID, + BridgeInternal.setProperty(this, Constants.Properties.ENCRYPTION_ALGORITHM, encryptionAlgorithm); } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java index 6541d965c448d..d5b4e90265bac 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java @@ -198,7 +198,7 @@ public static final class Properties { public static final String LOGGING_HANDLER_NAME = "logging-handler"; // encryption - public static final String ENCRYPTION_ALGORITHM_ID = "encryptionAlgorithmId"; + public static final String ENCRYPTION_ALGORITHM = "encryptionAlgorithm"; public static final String KEY_WRAP_METADATA = "keyWrapMetadata"; public static final String WRAPPED_DATA_ENCRYPTION_KEY = "wrappedDataEncryptionKey"; public static final String CLIENT_ENCRYPTION_POLICY = "clientEncryptionPolicy";