Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ static HttpPipeline buildPipeline(
httpHeaderList.add(new HttpHeader(header.getName(), header.getValue())));
}

// TODO: Remove the Accept header after making sure the JacksonAdapter can handle not setting such value.
policies.add(new AddHeadersPolicy(new HttpHeaders(httpHeaderList).set("Accept", "application/json")));

// Add per call additional policies.
policies.addAll(perCallAdditionalPolicies);
HttpPolicyProviders.addBeforeRetryPolicies(policies);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import com.azure.core.http.HttpRequest;
import com.azure.core.http.rest.PagedFlux;
import com.azure.core.http.rest.PagedResponse;
import com.azure.core.http.rest.PagedResponseBase;
import com.azure.core.http.rest.Response;
import com.azure.core.http.rest.SimpleResponse;
import com.azure.core.util.Context;
Expand Down Expand Up @@ -57,17 +56,15 @@
import reactor.core.publisher.Mono;

import java.net.URI;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.azure.core.util.CoreUtils.isNullOrEmpty;
import static com.azure.core.util.FluxUtil.fluxContext;
import static com.azure.core.util.FluxUtil.monoError;
import static com.azure.core.util.FluxUtil.pagedFluxError;
import static com.azure.core.util.FluxUtil.withContext;
import static com.azure.data.tables.implementation.TableUtils.swallowExceptionForStatusCode;
import static com.azure.data.tables.implementation.TableUtils.toTableServiceError;
Expand Down Expand Up @@ -845,41 +842,47 @@ <T extends TableEntity> Mono<Response<T>> getEntityWithResponse(String partition
* Retrieves details about any stored access policies specified on the table that may be used with Shared Access
* Signatures.
*
* @return A paged reactive result containing the HTTP response and the table's
* @return A reactive result containing the table's {@link TableSignedIdentifier access policies}.
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
public Mono<List<TableSignedIdentifier>> listAccessPolicies() {
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
return withContext(context -> listAccessPoliciesWithResponse(context)
.flatMap(response -> Mono.justOrEmpty(response.getValue())));
}

/**
* Retrieves details about any stored access policies specified on the table that may be used with Shared Access
* Signatures.
*
* @return A reactive result containing the HTTP response and the table's
* {@link TableSignedIdentifier access policies}.
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public PagedFlux<TableSignedIdentifier> listAccessPolicies() {
return (PagedFlux<TableSignedIdentifier>) fluxContext(this::listAccessPolicies);
public Mono<Response<List<TableSignedIdentifier>>> listAccessPoliciesWithResponse() {
return withContext(this::listAccessPoliciesWithResponse);
}

PagedFlux<TableSignedIdentifier> listAccessPolicies(Context context) {
Mono<Response<List<TableSignedIdentifier>>> listAccessPoliciesWithResponse(Context context) {
context = context == null ? Context.NONE : context;

try {
Context finalContext = context;
Function<String, Mono<PagedResponse<TableSignedIdentifier>>> retriever =
marker ->
tablesImplementation.getTables()
.getAccessPolicyWithResponseAsync(tableName, null, null, finalContext)
.map(response -> new PagedResponseBase<>(response.getRequest(),
response.getStatusCode(),
response.getHeaders(),
response.getValue().stream()
.map(this::toTableSignedIdentifier)
.collect(Collectors.toList()),
null,
response.getDeserializedHeaders()));

return new PagedFlux<>(() -> retriever.apply(null), retriever);
return tablesImplementation.getTables()
.getAccessPolicyWithResponseAsync(tableName, null, null, context)
.map(response -> {
List<SignedIdentifier> signedIdentifiers = response.getValue();

return new SimpleResponse<>(response,
signedIdentifiers == null ? null : signedIdentifiers.stream()
.map(this::toTableSignedIdentifier)
.collect(Collectors.toList()));
});
} catch (RuntimeException e) {
return pagedFluxError(logger, e);
return monoError(logger, e);
}
}

private TableSignedIdentifier toTableSignedIdentifier(SignedIdentifier signedIdentifier) {
return new TableSignedIdentifier()
.setId(signedIdentifier.getId())
return new TableSignedIdentifier(signedIdentifier.getId())
.setAccessPolicy(toTableAccessPolicy(signedIdentifier.getAccessPolicy()));
}

Expand Down Expand Up @@ -918,11 +921,34 @@ public Mono<Response<Void>> setAccessPoliciesWithResponse(List<TableSignedIdenti
Mono<Response<Void>> setAccessPoliciesWithResponse(List<TableSignedIdentifier> tableSignedIdentifiers,
Context context) {
context = context == null ? Context.NONE : context;
List<SignedIdentifier> signedIdentifiers = null;

/*
We truncate to seconds because the service only supports nanoseconds or seconds, but doing an
OffsetDateTime.now will only give back milliseconds (more precise fields are zeroed and not serialized). This
allows for proper serialization with no real detriment to users as sub-second precision on active time for
signed identifiers is not really necessary.
*/
if (tableSignedIdentifiers != null) {
signedIdentifiers = tableSignedIdentifiers.stream()
.map(this::toSignedIdentifier)
.collect(Collectors.toList());

for (SignedIdentifier identifier : signedIdentifiers) {
if (identifier.getAccessPolicy() != null && identifier.getAccessPolicy().getStart() != null) {
identifier.getAccessPolicy().setStart(
identifier.getAccessPolicy().getStart().truncatedTo(ChronoUnit.SECONDS));
}
if (identifier.getAccessPolicy() != null && identifier.getAccessPolicy().getExpiry() != null) {
identifier.getAccessPolicy().setExpiry(
identifier.getAccessPolicy().getExpiry().truncatedTo(ChronoUnit.SECONDS));
}
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
}
}

try {
return tablesImplementation.getTables()
.setAccessPolicyWithResponseAsync(tableName, null, null,
tableSignedIdentifiers.stream().map(this::toSignedIdentifier).collect(Collectors.toList()), context)
.setAccessPolicyWithResponseAsync(tableName, null, null, signedIdentifiers, context)
.map(response -> new SimpleResponse<>(response, response.getValue()));
} catch (RuntimeException e) {
return monoError(logger, e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,9 @@ public Response<TableEntity> getEntityWithResponse(String partitionKey, String r
* @return A reactive result containing the HTTP response and the table's
* {@link TableSignedIdentifier access policies}.
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public PagedIterable<TableSignedIdentifier> listAccessPolicies() {
return new PagedIterable<>(client.listAccessPolicies());
@ServiceMethod(returns = ReturnType.SINGLE)
public List<TableSignedIdentifier> listAccessPolicies() {
return client.listAccessPolicies().block();
}

/**
Expand All @@ -429,9 +429,9 @@ public PagedIterable<TableSignedIdentifier> listAccessPolicies() {
* @return A reactive result containing the HTTP response and the table's
* {@link TableSignedIdentifier access policies}.
*/
@ServiceMethod(returns = ReturnType.COLLECTION)
public PagedIterable<TableSignedIdentifier> listAccessPolicies(Duration timeout, Context context) {
return new PagedIterable<>(applyOptionalTimeout(client.listAccessPolicies(context), timeout));
@ServiceMethod(returns = ReturnType.SINGLE)
public Response<List<TableSignedIdentifier>> listAccessPoliciesWithResponse(Duration timeout, Context context) {
return blockWithOptionalTimeout(client.listAccessPoliciesWithResponse(context), timeout);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,6 @@ public Mono<Void> setProperties(TableServiceProperties tableServiceProperties) {
return this.setPropertiesWithResponse(tableServiceProperties).flatMap(FluxUtil::toMono);
}


/**
* Sets the properties of an account's Table service, including properties for Analytics and CORS (Cross-Origin
* Resource Sharing) rules.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.azure.data.tables.implementation.models.QueryOptions;
import com.azure.data.tables.implementation.models.ResponseFormat;
import com.azure.data.tables.implementation.models.SignedIdentifier;
import com.azure.data.tables.implementation.models.SignedIdentifiersWrapper;
import com.azure.data.tables.implementation.models.TableProperties;
import com.azure.data.tables.implementation.models.TableServiceErrorException;
import com.azure.data.tables.implementation.models.TablesCreateResponse;
Expand Down Expand Up @@ -238,7 +239,7 @@ Mono<TablesSetAccessPolicyResponse> setAccessPolicy(
@HeaderParam("x-ms-client-request-id") String requestId,
@PathParam("table") String table,
@QueryParam("comp") String comp,
@BodyParam("application/xml") List<SignedIdentifier> tableAcl,
@BodyParam("application/xml") SignedIdentifiersWrapper tableAcl,
@HeaderParam("Accept") String accept,
Context context);
}
Expand Down Expand Up @@ -725,14 +726,17 @@ public Mono<TablesSetAccessPolicyResponse> setAccessPolicyWithResponseAsync(
String table, Integer timeout, String requestId, List<SignedIdentifier> tableAcl, Context context) {
final String comp = "acl";
final String accept = "application/xml";

SignedIdentifiersWrapper tableAclConverted = new SignedIdentifiersWrapper(tableAcl);

return service.setAccessPolicy(
this.client.getUrl(),
timeout,
this.client.getVersion(),
requestId,
table,
comp,
tableAcl,
tableAclConverted,
accept,
context);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.data.tables.implementation.models;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

import java.util.List;

/** A wrapper around List&lt;SignedIdentifier&gt; which provides top-level metadata for serialization. */
@JacksonXmlRootElement(localName = "SignedIdentifiers")
public final class SignedIdentifiersWrapper {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an issue to get the code generator working correctly to generate this type?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I don't know how to get it to do that, so I added the class manually and was looking to add a transform later (once I learn enough about autorest).

@JacksonXmlProperty(localName = "SignedIdentifier")
private final List<SignedIdentifier> signedIdentifiers;

/**
* Creates an instance of SignedIdentifiersWrapper.
*
* @param signedIdentifiers the list.
*/
@JsonCreator
public SignedIdentifiersWrapper(@JsonProperty("SignedIdentifier") List<SignedIdentifier> signedIdentifiers) {
this.signedIdentifiers = signedIdentifiers;
}

/**
* Get the List&lt;BlobSignedIdentifier&gt; contained in this wrapper.
*
* @return the List&lt;BlobSignedIdentifier&gt;.
*/
public List<SignedIdentifier> items() {
return signedIdentifiers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import com.azure.core.annotation.Fluent;

import java.util.Objects;

/**
* A signed identifier.
*/
Expand All @@ -13,33 +15,31 @@ public final class TableSignedIdentifier {
/*
* A unique id
*/
private String id;
private final String id;

/*
* An access policy.
*/
private TableAccessPolicy accessPolicy;

/**
* Get the unique id.
* Create a {@link TableSignedIdentifier}.
*
* @return The id.
* @param id A unique id for this {@link TableSignedIdentifier}.
*/
public String getId() {
return this.id;
public TableSignedIdentifier(String id) {
Objects.requireNonNull(id, "'id' cannot be null");

this.id = id;
}

/**
* Set a unique id.
*
* @param id The id to set.
* Get the unique id.
*
* @return The updated {@link TableSignedIdentifier} object.
* @return The id.
*/
public TableSignedIdentifier setId(String id) {
this.id = id;

return this;
public String getId() {
return this.id;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
import com.azure.core.test.TestBase;
import com.azure.core.test.utils.TestResourceNamer;
import com.azure.data.tables.models.ListEntitiesOptions;
import com.azure.data.tables.models.TableAccessPolicy;
import com.azure.data.tables.models.TableEntity;
import com.azure.data.tables.models.TableEntityUpdateMode;
import com.azure.data.tables.models.TableSignedIdentifier;
import com.azure.data.tables.models.TableTransactionAction;
import com.azure.data.tables.models.TableTransactionActionResponse;
import com.azure.data.tables.models.TableTransactionActionType;
Expand All @@ -35,6 +37,7 @@
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -1009,4 +1012,30 @@ public void canUseSasTokenToCreateValidTableClient() {
.expectComplete()
.verify();
}

@Test
public void setAndListAccessPolicies() {
Comment thread
vcolin7 marked this conversation as resolved.
OffsetDateTime startTime = OffsetDateTime.of(2021, 12, 12, 0, 0, 0, 0, ZoneOffset.UTC);
OffsetDateTime expiryTime = OffsetDateTime.of(2022, 12, 12, 0, 0, 0, 0, ZoneOffset.UTC);
String permissions = "r";
TableAccessPolicy tableAccessPolicy = new TableAccessPolicy()
.setStartsOn(startTime)
.setExpiresOn(expiryTime)
.setPermissions(permissions);
String id = "testPolicy";
TableSignedIdentifier tableSignedIdentifier = new TableSignedIdentifier(id).setAccessPolicy(tableAccessPolicy);

Response<Void> response =
Comment thread
vcolin7 marked this conversation as resolved.
Outdated
tableClient.setAccessPoliciesWithResponse(Collections.singletonList(tableSignedIdentifier)).block();

assertEquals(204, response.getStatusCode());

TableSignedIdentifier signedIdentifier = tableClient.listAccessPolicies().block().get(0);
TableAccessPolicy accessPolicy = signedIdentifier.getAccessPolicy();

assertEquals(startTime, accessPolicy.getStartsOn());
assertEquals(expiryTime, accessPolicy.getExpiresOn());
assertEquals(permissions, accessPolicy.getPermissions());
assertEquals(id, signedIdentifier.getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import com.azure.data.tables.models.ListTablesOptions;
import com.azure.data.tables.models.TableEntity;
import com.azure.data.tables.models.TableServiceException;
import com.azure.data.tables.models.TableServiceProperties;
import com.azure.data.tables.models.TableServiceStatistics;
import com.azure.data.tables.sas.TableAccountSasPermission;
import com.azure.data.tables.sas.TableAccountSasResourceType;
import com.azure.data.tables.sas.TableAccountSasService;
Expand Down Expand Up @@ -415,4 +417,27 @@ public void canUseSasTokenToCreateValidTableClient() {
.expectComplete()
.verify();
}

@Test
public void getProperties() {
TableServiceProperties properties = serviceClient.getProperties().block();

assertNotNull(properties);
assertNotNull(properties.getCorsRules());
assertEquals(1, properties.getCorsRules().size());
assertNotNull(properties.getCorsRules().get(0));
assertNotNull(properties.getHourMetrics());
assertNotNull(properties.getMinuteMetrics());
assertNotNull(properties.getLogging());
}

@Test
public void getStatistics() {
TableServiceStatistics statistics = serviceClient.getStatistics().block();

assertNotNull(statistics);
assertNotNull(statistics.getGeoReplication());
assertNotNull(statistics.getGeoReplication().getStatus());
assertNotNull(statistics.getGeoReplication().getLastSyncTime());
}
}
Loading