From 231a018f0e69f233d3795017876c18af4f478c3b Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Fri, 21 Sep 2018 14:01:47 +1000 Subject: [PATCH 1/7] Create/Update role mapping API This commit adds create/update role mapping API. --- .../elasticsearch/client/SecurityClient.java | 30 +++++ .../client/SecurityRequestConverters.java | 13 ++ .../security/PutRoleMappingRequest.java | 113 ++++++++++++++++++ .../security/PutRoleMappingResponse.java | 75 ++++++++++++ .../SecurityRequestConvertersTests.java | 32 +++++ .../SecurityDocumentationIT.java | 59 ++++++++- .../security/put-role-mapping.asciidoc | 53 ++++++++ .../high-level/supported-apis.asciidoc | 2 + 8 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java create mode 100644 docs/java-rest/high-level/security/put-role-mapping.asciidoc diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java index a4bc34004c247..d672f23e711fa 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java @@ -20,6 +20,8 @@ package org.elasticsearch.client; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.client.security.PutRoleMappingRequest; +import org.elasticsearch.client.security.PutRoleMappingResponse; import org.elasticsearch.client.security.DisableUserRequest; import org.elasticsearch.client.security.EnableUserRequest; import org.elasticsearch.client.security.PutUserRequest; @@ -70,6 +72,34 @@ public void putUserAsync(PutUserRequest request, RequestOptions options, ActionL PutUserResponse::fromXContent, listener, emptySet()); } + /** + * Create/Update a role mapping. + * See + * the docs for more. + * @param request the request with the role mapping information + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response from the put role mapping call + * @throws IOException in case there is a problem sending the request or parsing back the response + */ + public PutRoleMappingResponse putRoleMapping(PutRoleMappingRequest request, RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::putRoleMapping, options, + PutRoleMappingResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously create/update a role mapping. + * See + * the docs for more. + * @param request the request with the role mapping information + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + */ + public void putRoleMappingAsync(PutRoleMappingRequest request, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putRoleMapping, options, + PutRoleMappingResponse::fromXContent, listener, emptySet()); + } + /** * Enable a native realm or built-in user synchronously. * See diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java index 8533e0f1b4cd4..c2b87de541310 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java @@ -20,6 +20,7 @@ package org.elasticsearch.client; import org.apache.http.client.methods.HttpPut; +import org.elasticsearch.client.security.PutRoleMappingRequest; import org.elasticsearch.client.security.DisableUserRequest; import org.elasticsearch.client.security.EnableUserRequest; import org.elasticsearch.client.security.PutUserRequest; @@ -46,6 +47,18 @@ static Request putUser(PutUserRequest putUserRequest) throws IOException { return request; } + static Request putRoleMapping(final PutRoleMappingRequest putRoleMappingRequest) throws IOException { + final String endpoint = new RequestConverters.EndpointBuilder() + .addPathPartAsIs("_xpack/security/role_mapping") + .addPathPart(putRoleMappingRequest.getName()) + .build(); + final Request request = new Request(HttpPut.METHOD_NAME, endpoint); + request.setEntity(createEntity(putRoleMappingRequest, REQUEST_BODY_CONTENT_TYPE)); + final RequestConverters.Params params = new RequestConverters.Params(request); + params.withRefreshPolicy(putRoleMappingRequest.getRefreshPolicy()); + return request; + } + static Request enableUser(EnableUserRequest enableUserRequest) { return setUserEnabled(enableUserRequest); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java new file mode 100644 index 0000000000000..d536cf32006bd --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java @@ -0,0 +1,113 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.security; + +import org.elasticsearch.client.Validatable; +import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Request object to create or update a role mapping. + */ +public final class PutRoleMappingRequest implements Validatable, ToXContentObject { + + private String name; + private boolean enabled; + private List roles; + private RoleMapperExpression rules; + private Map metadata; + private RefreshPolicy refreshPolicy; + + public PutRoleMappingRequest(final String name, final boolean enabled, final List roles, final RoleMapperExpression rules, + final Map metadata, final RefreshPolicy refreshPolicy) { + super(); + this.name = Objects.requireNonNull(name, "role-mapping name is missing"); + this.enabled = enabled; + this.roles = Collections.unmodifiableList(Objects.requireNonNull(roles, "role-mapping roles are missing")); + this.rules = Objects.requireNonNull(rules, "role-mapping rules are missing"); + this.metadata = (metadata == null) ? Collections.emptyMap() : metadata; + this.refreshPolicy = (refreshPolicy == null) ? RefreshPolicy.getDefault() : refreshPolicy; + } + + public String getName() { + return name; + } + + public boolean isEnabled() { + return enabled; + } + + public List getRoles() { + return roles; + } + + public Map getMetadata() { + return metadata; + } + + public RefreshPolicy getRefreshPolicy() { + return refreshPolicy; + } + + @Override + public int hashCode() { + return Objects.hash(name, enabled, refreshPolicy, roles, rules, metadata); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final PutRoleMappingRequest other = (PutRoleMappingRequest) obj; + + return (enabled == other.enabled) && + (refreshPolicy == other.refreshPolicy) && + Objects.equals(name, other.name) && + Objects.equals(roles, other.roles) && + Objects.equals(rules, other.rules) && + Objects.equals(metadata, other.metadata); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field("enabled", enabled); + builder.field("roles", roles); + builder.field("rules", rules); + builder.field("metadata", metadata); + builder.endObject(); + return null; + } + +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java new file mode 100644 index 0000000000000..af7d29eebb3da --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.security; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; + +/** + * Response when adding/updating a role mapping. Returns a boolean field for + * whether the role mapping was created or updated. + */ +public final class PutRoleMappingResponse { + + private boolean created; + + public PutRoleMappingResponse(boolean created) { + super(); + this.created = created; + } + + public boolean isCreated() { + return created; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final PutRoleMappingResponse that = (PutRoleMappingResponse) o; + return created == that.created; + } + + @Override + public int hashCode() { + return Objects.hash(created); + } + + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( + "put_role_mapping_response", true, args -> new PutRoleMappingResponse((boolean) args[0])); + static { + PARSER.declareBoolean(constructorArg(), new ParseField("created")); + PARSER.declareObject((a,b) -> {}, (parser, context) -> null, new ParseField("role_mapping")); // ignore the role_mapping field! + } + + public static PutRoleMappingResponse fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java index 3670379cd9fee..e83765ed8b099 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java @@ -22,8 +22,12 @@ import org.apache.http.client.methods.HttpPut; import org.elasticsearch.client.security.DisableUserRequest; import org.elasticsearch.client.security.EnableUserRequest; +import org.elasticsearch.client.security.PutRoleMappingRequest; import org.elasticsearch.client.security.PutUserRequest; import org.elasticsearch.client.security.RefreshPolicy; +import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression; +import org.elasticsearch.client.security.support.expressiondsl.expressions.AnyRoleMapperExpression; +import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression; import org.elasticsearch.test.ESTestCase; import java.io.IOException; @@ -65,6 +69,34 @@ public void testPutUser() throws IOException { assertToXContentBody(putUserRequest, request.getEntity()); } + public void testPutRoleMapping() throws IOException { + final String username = randomAlphaOfLengthBetween(4, 7); + final String rolename = randomAlphaOfLengthBetween(4, 7); + final String roleMappingName = randomAlphaOfLengthBetween(4, 7); + final String groupname = "cn="+randomAlphaOfLengthBetween(4, 7)+",dc=example,dc=com"; + final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); + final Map expectedParams; + if (refreshPolicy != RefreshPolicy.NONE) { + expectedParams = Collections.singletonMap("refresh", refreshPolicy.getValue()); + } else { + expectedParams = Collections.emptyMap(); + } + + final RoleMapperExpression rules = AnyRoleMapperExpression.builder() + .addExpression(FieldRoleMapperExpression.ofUsername(username)) + .addExpression(FieldRoleMapperExpression.ofGroups(groupname)) + .build(); + final PutRoleMappingRequest putRoleMappingRequest = new PutRoleMappingRequest(roleMappingName, true, Collections.singletonList( + rolename), rules, null, refreshPolicy); + + final Request request = SecurityRequestConverters.putRoleMapping(putRoleMappingRequest); + + assertEquals(HttpPut.METHOD_NAME, request.getMethod()); + assertEquals("/_xpack/security/role_mapping/" + roleMappingName, request.getEndpoint()); + assertEquals(expectedParams, request.getParameters()); + assertToXContentBody(putRoleMappingRequest, request.getEntity()); + } + public void testEnableUser() { final String username = randomAlphaOfLengthBetween(1, 12); final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java index 103b031fc0e03..aaab2aa2d6256 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java @@ -25,11 +25,16 @@ import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.security.DisableUserRequest; +import org.elasticsearch.client.security.EmptyResponse; import org.elasticsearch.client.security.EnableUserRequest; +import org.elasticsearch.client.security.PutRoleMappingRequest; +import org.elasticsearch.client.security.PutRoleMappingResponse; import org.elasticsearch.client.security.PutUserRequest; import org.elasticsearch.client.security.PutUserResponse; import org.elasticsearch.client.security.RefreshPolicy; -import org.elasticsearch.client.security.EmptyResponse; +import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression; +import org.elasticsearch.client.security.support.expressiondsl.expressions.AnyRoleMapperExpression; +import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression; import java.util.Collections; import java.util.concurrent.CountDownLatch; @@ -85,6 +90,58 @@ public void onFailure(Exception e) { } } + public void testPutRoleMapping() throws Exception { + final RestHighLevelClient client = highLevelClient(); + + { + // tag::put-role-mapping-execute + final RoleMapperExpression rules = AnyRoleMapperExpression.builder() + .addExpression(FieldRoleMapperExpression.ofUsername("*")) + .addExpression(FieldRoleMapperExpression.ofGroups("cn=admins,dc=example,dc=com")) + .build(); + final PutRoleMappingRequest request = new PutRoleMappingRequest("mapping-example", true, Collections.singletonList("superuser"), + rules, null, RefreshPolicy.NONE); + final PutRoleMappingResponse response = client.security().putRoleMapping(request, RequestOptions.DEFAULT); + // end::put-role-mapping-execute + // tag::put-role-mapping-response + boolean isCreated = response.isCreated(); // <1> + // end::put-role-mapping-response + assertTrue(isCreated); + } + + { + final RoleMapperExpression rules = AnyRoleMapperExpression.builder() + .addExpression(FieldRoleMapperExpression.ofUsername("*")) + .addExpression(FieldRoleMapperExpression.ofGroups("cn=admins,dc=example,dc=com")) + .build(); + final PutRoleMappingRequest request = new PutRoleMappingRequest("mapping-example", true, Collections.singletonList("superuser"), + rules, null, RefreshPolicy.NONE); + // tag::put-role-mapping-execute-async + ActionListener listener = new ActionListener() { + @Override + public void onResponse(PutRoleMappingResponse response) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::put-role-mapping-execute-async + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::put-role-mapping-execute-listener + client.security().putRoleMappingAsync(request, RequestOptions.DEFAULT, listener); // <1> + // end::put-role-mapping-execute-listener + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + } + } + public void testEnableUser() throws Exception { RestHighLevelClient client = highLevelClient(); char[] password = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}; diff --git a/docs/java-rest/high-level/security/put-role-mapping.asciidoc b/docs/java-rest/high-level/security/put-role-mapping.asciidoc new file mode 100644 index 0000000000000..7f1bcb2839bde --- /dev/null +++ b/docs/java-rest/high-level/security/put-role-mapping.asciidoc @@ -0,0 +1,53 @@ +[[java-rest-high-security-put-role-mapping]] +=== Put Role Mapping API + +[[java-rest-high-security-put-role-mapping-execution]] +==== Execution + +Creating and updating a role mapping can be performed using the `security().putRoleMapping()` +method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[put-role-mapping-execute] +-------------------------------------------------- + +[[java-rest-high-security-put-role-mapping-response]] +==== Response + +The returned `PutRoleMappingResponse` contains a single field, `created`. This field +serves as an indication if a role mapping was created or if an existing entry was updated. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[put-role-mapping-response] +-------------------------------------------------- +<1> `created` is a boolean indicating whether the role mapping was created or updated + +[[java-rest-high-security-put-role-mapping-async]] +==== Asynchronous Execution + +This request can be executed asynchronously using the `security().putRoleMappingAsync()` +method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[put-role-mapping-execute-async] +-------------------------------------------------- +<1> The `PutRoleMappingResponse` to execute and the `ActionListener` to use when +the execution completes + +The asynchronous method does not block and returns immediately. Once the request +has completed the `ActionListener` is called back using the `onResponse` method +if the execution successfully completed or using the `onFailure` method if +it failed. + +A typical listener for a `PutRoleMappingResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/SecurityDocumentationIT.java[put-role-mapping-execute-listener] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument +<2> Called in case of failure. The raised exception is provided as an argument \ No newline at end of file diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 8e3e8f5812bd4..d42f2fbb734c0 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -291,10 +291,12 @@ The Java High Level REST Client supports the following Security APIs: * <> * <> * <> +* <> include::security/put-user.asciidoc[] include::security/enable-user.asciidoc[] include::security/disable-user.asciidoc[] +include::security/put-role-mapping.asciidoc[] == Watcher APIs From 8aa1db5290489ddebc62ba9aadf058b9b7862ba4 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Mon, 1 Oct 2018 17:53:12 +1000 Subject: [PATCH 2/7] review --- .../elasticsearch/client/SecurityClient.java | 6 +- .../security/PutRoleMappingRequest.java | 23 +++- .../security/PutRoleMappingRequestTests.java | 115 ++++++++++++++++++ 3 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java index d672f23e711fa..5dbdce750d94e 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java @@ -81,7 +81,7 @@ public void putUserAsync(PutUserRequest request, RequestOptions options, ActionL * @return the response from the put role mapping call * @throws IOException in case there is a problem sending the request or parsing back the response */ - public PutRoleMappingResponse putRoleMapping(PutRoleMappingRequest request, RequestOptions options) throws IOException { + public PutRoleMappingResponse putRoleMapping(final PutRoleMappingRequest request, final RequestOptions options) throws IOException { return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::putRoleMapping, options, PutRoleMappingResponse::fromXContent, emptySet()); } @@ -94,8 +94,8 @@ public PutRoleMappingResponse putRoleMapping(PutRoleMappingRequest request, Requ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion */ - public void putRoleMappingAsync(PutRoleMappingRequest request, RequestOptions options, - ActionListener listener) { + public void putRoleMappingAsync(final PutRoleMappingRequest request, final RequestOptions options, + final ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putRoleMapping, options, PutRoleMappingResponse::fromXContent, listener, emptySet()); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java index d536cf32006bd..405bc3577ae1d 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java @@ -21,6 +21,8 @@ import org.elasticsearch.client.Validatable; import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -39,15 +41,22 @@ public final class PutRoleMappingRequest implements Validatable, ToXContentObjec private boolean enabled; private List roles; private RoleMapperExpression rules; - private Map metadata; - private RefreshPolicy refreshPolicy; + + @Nullable private Map metadata; + @Nullable private RefreshPolicy refreshPolicy; public PutRoleMappingRequest(final String name, final boolean enabled, final List roles, final RoleMapperExpression rules, - final Map metadata, final RefreshPolicy refreshPolicy) { + @Nullable final Map metadata, @Nullable final RefreshPolicy refreshPolicy) { super(); - this.name = Objects.requireNonNull(name, "role-mapping name is missing"); + if (Strings.hasText(name) == false) { + throw new IllegalArgumentException("role-mapping name is missing"); + } + this.name = name; this.enabled = enabled; - this.roles = Collections.unmodifiableList(Objects.requireNonNull(roles, "role-mapping roles are missing")); + if (roles == null || roles.isEmpty()) { + throw new IllegalArgumentException("role-mapping roles are missing"); + } + this.roles = Collections.unmodifiableList(roles); this.rules = Objects.requireNonNull(rules, "role-mapping rules are missing"); this.metadata = (metadata == null) ? Collections.emptyMap() : metadata; this.refreshPolicy = (refreshPolicy == null) ? RefreshPolicy.getDefault() : refreshPolicy; @@ -65,6 +74,10 @@ public List getRoles() { return roles; } + public RoleMapperExpression getRules() { + return rules; + } + public Map getMetadata() { return metadata; } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java new file mode 100644 index 0000000000000..01f2b661a614b --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java @@ -0,0 +1,115 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.security; + +import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression; +import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression; +import org.elasticsearch.common.Strings; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.EqualsHashCodeTestUtils; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; + +public class PutRoleMappingRequestTests extends ESTestCase { + + public void testPutRoleMappingRequest() { + final String name = randomFrom(randomAlphaOfLength(5), null, ""); + final boolean enabled = randomBoolean(); + final boolean nullorEmptyRoles = randomBoolean(); + final List roles = nullorEmptyRoles ? (randomBoolean() ? null : Collections.emptyList()) + : Collections.singletonList("superuser"); + final RoleMapperExpression rules = randomFrom(FieldRoleMapperExpression.ofUsername("user"), null); + final boolean nullorEmptyMetadata = randomBoolean(); + final Map metadata; + if (nullorEmptyMetadata) { + metadata = randomBoolean() ? null : Collections.emptyMap(); + } else { + metadata = new HashMap<>(); + metadata.put("k1", "v1"); + } + final RefreshPolicy refreshPolicy = randomFrom(randomFrom(RefreshPolicy.values()), null); + + if (Strings.hasText(name) == false) { + final IllegalArgumentException ile = expectThrows(IllegalArgumentException.class, () -> new PutRoleMappingRequest(name, enabled, + roles, rules, metadata, refreshPolicy)); + assertThat(ile.getMessage(), equalTo("role-mapping name is missing")); + } else if (roles == null || roles.isEmpty()) { + final IllegalArgumentException ile = expectThrows(IllegalArgumentException.class, () -> new PutRoleMappingRequest(name, enabled, + roles, rules, metadata, refreshPolicy)); + assertThat(ile.getMessage(), equalTo("role-mapping roles are missing")); + } else if (rules == null) { + expectThrows(NullPointerException.class, () -> new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy)); + } else { + PutRoleMappingRequest putRoleMappingRequest = new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy); + assertNotNull(putRoleMappingRequest); + assertThat(putRoleMappingRequest.getName(), equalTo(name)); + assertThat(putRoleMappingRequest.isEnabled(), equalTo(enabled)); + assertThat(putRoleMappingRequest.getRefreshPolicy(), equalTo((refreshPolicy == null) ? RefreshPolicy.getDefault() + : refreshPolicy)); + assertThat(putRoleMappingRequest.getRules(), equalTo(rules)); + assertThat(putRoleMappingRequest.getRoles(), equalTo(roles)); + assertThat(putRoleMappingRequest.getMetadata(), equalTo((metadata == null) ? Collections.emptyMap() : metadata)); + } + } + + public void testEqualsHashCode() { + final String name = randomAlphaOfLength(5); + final boolean enabled = randomBoolean(); + final List roles = Collections.singletonList("superuser"); + final RoleMapperExpression rules = FieldRoleMapperExpression.ofUsername("user"); + final Map metadata = new HashMap<>(); + metadata.put("k1", "v1"); + final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); + + PutRoleMappingRequest putRoleMappingRequest = new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy); + assertNotNull(putRoleMappingRequest); + + EqualsHashCodeTestUtils.checkEqualsAndHashCode(putRoleMappingRequest, (original) -> { + return new PutRoleMappingRequest(original.getName(), original.isEnabled(), original.getRoles(), original.getRules(), original + .getMetadata(), original.getRefreshPolicy()); + }); + EqualsHashCodeTestUtils.checkEqualsAndHashCode(putRoleMappingRequest, (original) -> { + return new PutRoleMappingRequest(original.getName(), original.isEnabled(), original.getRoles(), original.getRules(), original + .getMetadata(), original.getRefreshPolicy()); + }, PutRoleMappingRequestTests::mutateTestItem); + } + + private static PutRoleMappingRequest mutateTestItem(PutRoleMappingRequest original) { + switch (randomIntBetween(0, 2)) { + case 0: + return new PutRoleMappingRequest(randomAlphaOfLength(5), original.isEnabled(), original.getRoles(), original.getRules(), + original.getMetadata(), original.getRefreshPolicy()); + case 1: + return new PutRoleMappingRequest(original.getName(), !original.isEnabled(), original.getRoles(), original.getRules(), original + .getMetadata(), original.getRefreshPolicy()); + case 2: + return new PutRoleMappingRequest(original.getName(), original.isEnabled(), original.getRoles(), FieldRoleMapperExpression + .ofGroups("group"), original.getMetadata(), original.getRefreshPolicy()); + default: + throw new IllegalArgumentException("unknown option"); + } + } + +} From 8f9ec110d038d46b5cf874d3a4983f01c036c97c Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Mon, 1 Oct 2018 18:34:50 +1000 Subject: [PATCH 3/7] review --- .../security/PutRoleMappingRequest.java | 3 +- .../security/PutRoleMappingRequestTests.java | 31 +++++++++++++++++++ .../RoleMapperExpressionDslTests.java | 2 +- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java index 405bc3577ae1d..26636fa492771 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java @@ -119,8 +119,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.field("roles", roles); builder.field("rules", rules); builder.field("metadata", metadata); - builder.endObject(); - return null; + return builder.endObject(); } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java index 01f2b661a614b..4c5cd999b2dd0 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java @@ -22,9 +22,13 @@ import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression; import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.EqualsHashCodeTestUtils; +import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -74,6 +78,33 @@ public void testPutRoleMappingRequest() { } } + public void testPutRoleMappingRequestToXContent() throws IOException { + final String name = randomAlphaOfLength(5); + final boolean enabled = randomBoolean(); + final List roles = Collections.singletonList("superuser"); + final RoleMapperExpression rules = FieldRoleMapperExpression.ofUsername("user"); + final Map metadata = new HashMap<>(); + metadata.put("k1", "v1"); + final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); + + final PutRoleMappingRequest putRoleMappingRequest = new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy); + + final XContentBuilder builder = XContentFactory.jsonBuilder(); + putRoleMappingRequest.toXContent(builder, ToXContent.EMPTY_PARAMS); + final String output = Strings.toString(builder); + final String expected = + "{"+ + "\"enabled\":" + enabled + "," + + "\"roles\":[\"superuser\"]," + + "\"rules\":{" + + "\"field\":{\"username\":[\"user\"]}" + + "}," + + "\"metadata\":{\"k1\":\"v1\"}" + + "}"; + + assertThat(output, equalTo(expected)); + } + public void testEqualsHashCode() { final String name = randomAlphaOfLength(5); final boolean enabled = randomBoolean(); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/support/expressiondsl/RoleMapperExpressionDslTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/support/expressiondsl/RoleMapperExpressionDslTests.java index df94640f172dd..6b067e08e0be2 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/support/expressiondsl/RoleMapperExpressionDslTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/support/expressiondsl/RoleMapperExpressionDslTests.java @@ -86,7 +86,7 @@ public void testRoleMapperExpressionToXContentType() throws IOException { "]"+ "}"; - assertThat(expected, equalTo(output)); + assertThat(output, equalTo(expected)); } public void testFieldRoleMapperExpressionThrowsExceptionForMissingMetadataPrefix() { From c5681463dcb6a7803245503eb1bde26956707a7b Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 2 Oct 2018 23:32:41 +1000 Subject: [PATCH 4/7] Address review comments --- .../elasticsearch/client/security/PutRoleMappingRequest.java | 1 - .../expressions/CompositeRoleMapperExpression.java | 2 +- .../support/expressiondsl/fields/FieldRoleMapperExpression.java | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java index 26636fa492771..7e6ac3458d7ae 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java @@ -47,7 +47,6 @@ public final class PutRoleMappingRequest implements Validatable, ToXContentObjec public PutRoleMappingRequest(final String name, final boolean enabled, final List roles, final RoleMapperExpression rules, @Nullable final Map metadata, @Nullable final RefreshPolicy refreshPolicy) { - super(); if (Strings.hasText(name) == false) { throw new IllegalArgumentException("role-mapping name is missing"); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/expressions/CompositeRoleMapperExpression.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/expressions/CompositeRoleMapperExpression.java index 2519c59b68846..3373f325bfcdb 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/expressions/CompositeRoleMapperExpression.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/expressions/CompositeRoleMapperExpression.java @@ -57,7 +57,7 @@ public abstract class CompositeRoleMapperExpression implements RoleMapperExpress } public String getName() { - return this.getName(); + return this.name; } public List getElements() { diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/fields/FieldRoleMapperExpression.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/fields/FieldRoleMapperExpression.java index c96ac3cc5b5ec..4111b9fa2a2c3 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/fields/FieldRoleMapperExpression.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/support/expressiondsl/fields/FieldRoleMapperExpression.java @@ -50,7 +50,7 @@ public FieldRoleMapperExpression(final String field, final Object... values) { throw new IllegalArgumentException("null or empty field name (" + field + ")"); } if (values == null || values.length == 0) { - throw new IllegalArgumentException("null or empty values (" + values + ")"); + throw new IllegalArgumentException("null or empty values for field (" + field + ")"); } this.field = field; this.values = Collections.unmodifiableList(Arrays.asList(values)); From 76549611f3e547e734610374108538bf2a526bbf Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Wed, 3 Oct 2018 00:17:39 +1000 Subject: [PATCH 5/7] Address review comments - also added few missing cases --- .../security/PutRoleMappingResponse.java | 1 - .../security/PutRoleMappingRequestTests.java | 24 ++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java index af7d29eebb3da..ba85c953265c0 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java @@ -37,7 +37,6 @@ public final class PutRoleMappingResponse { private boolean created; public PutRoleMappingResponse(boolean created) { - super(); this.created = created; } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java index 4c5cd999b2dd0..3706eb0037bd1 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java @@ -29,10 +29,12 @@ import org.elasticsearch.test.EqualsHashCodeTestUtils; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static org.hamcrest.Matchers.equalTo; @@ -128,18 +130,28 @@ public void testEqualsHashCode() { } private static PutRoleMappingRequest mutateTestItem(PutRoleMappingRequest original) { - switch (randomIntBetween(0, 2)) { + switch (randomIntBetween(0, 4)) { case 0: return new PutRoleMappingRequest(randomAlphaOfLength(5), original.isEnabled(), original.getRoles(), original.getRules(), original.getMetadata(), original.getRefreshPolicy()); case 1: - return new PutRoleMappingRequest(original.getName(), !original.isEnabled(), original.getRoles(), original.getRules(), original - .getMetadata(), original.getRefreshPolicy()); + return new PutRoleMappingRequest(original.getName(), !original.isEnabled(), original.getRoles(), original.getRules(), + original.getMetadata(), original.getRefreshPolicy()); case 2: - return new PutRoleMappingRequest(original.getName(), original.isEnabled(), original.getRoles(), FieldRoleMapperExpression - .ofGroups("group"), original.getMetadata(), original.getRefreshPolicy()); + return new PutRoleMappingRequest(original.getName(), original.isEnabled(), original.getRoles(), + FieldRoleMapperExpression.ofGroups("group"), original.getMetadata(), original.getRefreshPolicy()); + case 3: + return new PutRoleMappingRequest(original.getName(), original.isEnabled(), original.getRoles(), original.getRules(), + Collections.emptyMap(), original.getRefreshPolicy()); + case 4: + List values = Arrays.stream(RefreshPolicy.values()) + .filter(rp -> rp != original.getRefreshPolicy()) + .collect(Collectors.toList()); + return new PutRoleMappingRequest(original.getName(), original.isEnabled(), original.getRoles(), original.getRules(), original + .getMetadata(), randomFrom(values)); default: - throw new IllegalArgumentException("unknown option"); + return new PutRoleMappingRequest(randomAlphaOfLength(5), original.isEnabled(), original.getRoles(), original.getRules(), + original.getMetadata(), original.getRefreshPolicy()); } } From 998f28afbd2b0fcddbe275f10b75a222932de431 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Wed, 3 Oct 2018 10:18:02 +1000 Subject: [PATCH 6/7] Address review comments --- .../security/PutRoleMappingRequest.java | 12 +-- .../security/PutRoleMappingResponse.java | 2 +- .../security/PutRoleMappingRequestTests.java | 91 +++++++++++-------- 3 files changed, 62 insertions(+), 43 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java index 7e6ac3458d7ae..b8da17da72dad 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingRequest.java @@ -37,13 +37,13 @@ */ public final class PutRoleMappingRequest implements Validatable, ToXContentObject { - private String name; - private boolean enabled; - private List roles; - private RoleMapperExpression rules; + private final String name; + private final boolean enabled; + private final List roles; + private final RoleMapperExpression rules; - @Nullable private Map metadata; - @Nullable private RefreshPolicy refreshPolicy; + private final Map metadata; + private final RefreshPolicy refreshPolicy; public PutRoleMappingRequest(final String name, final boolean enabled, final List roles, final RoleMapperExpression rules, @Nullable final Map metadata, @Nullable final RefreshPolicy refreshPolicy) { diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java index ba85c953265c0..a0d7b673e3908 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java @@ -34,7 +34,7 @@ */ public final class PutRoleMappingResponse { - private boolean created; + private final boolean created; public PutRoleMappingResponse(boolean created) { this.created = created; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java index 3706eb0037bd1..f0a3f7572ef3b 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/PutRoleMappingRequestTests.java @@ -41,43 +41,62 @@ public class PutRoleMappingRequestTests extends ESTestCase { public void testPutRoleMappingRequest() { - final String name = randomFrom(randomAlphaOfLength(5), null, ""); + final String name = randomAlphaOfLength(5); final boolean enabled = randomBoolean(); - final boolean nullorEmptyRoles = randomBoolean(); - final List roles = nullorEmptyRoles ? (randomBoolean() ? null : Collections.emptyList()) - : Collections.singletonList("superuser"); - final RoleMapperExpression rules = randomFrom(FieldRoleMapperExpression.ofUsername("user"), null); - final boolean nullorEmptyMetadata = randomBoolean(); - final Map metadata; - if (nullorEmptyMetadata) { - metadata = randomBoolean() ? null : Collections.emptyMap(); - } else { - metadata = new HashMap<>(); - metadata.put("k1", "v1"); - } - final RefreshPolicy refreshPolicy = randomFrom(randomFrom(RefreshPolicy.values()), null); - - if (Strings.hasText(name) == false) { - final IllegalArgumentException ile = expectThrows(IllegalArgumentException.class, () -> new PutRoleMappingRequest(name, enabled, - roles, rules, metadata, refreshPolicy)); - assertThat(ile.getMessage(), equalTo("role-mapping name is missing")); - } else if (roles == null || roles.isEmpty()) { - final IllegalArgumentException ile = expectThrows(IllegalArgumentException.class, () -> new PutRoleMappingRequest(name, enabled, - roles, rules, metadata, refreshPolicy)); - assertThat(ile.getMessage(), equalTo("role-mapping roles are missing")); - } else if (rules == null) { - expectThrows(NullPointerException.class, () -> new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy)); - } else { - PutRoleMappingRequest putRoleMappingRequest = new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy); - assertNotNull(putRoleMappingRequest); - assertThat(putRoleMappingRequest.getName(), equalTo(name)); - assertThat(putRoleMappingRequest.isEnabled(), equalTo(enabled)); - assertThat(putRoleMappingRequest.getRefreshPolicy(), equalTo((refreshPolicy == null) ? RefreshPolicy.getDefault() - : refreshPolicy)); - assertThat(putRoleMappingRequest.getRules(), equalTo(rules)); - assertThat(putRoleMappingRequest.getRoles(), equalTo(roles)); - assertThat(putRoleMappingRequest.getMetadata(), equalTo((metadata == null) ? Collections.emptyMap() : metadata)); - } + final List roles = Collections.singletonList("superuser"); + final RoleMapperExpression rules = FieldRoleMapperExpression.ofUsername("user"); + final Map metadata = new HashMap<>(); + metadata.put("k1", "v1"); + final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); + + PutRoleMappingRequest putRoleMappingRequest = new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy); + assertNotNull(putRoleMappingRequest); + assertThat(putRoleMappingRequest.getName(), equalTo(name)); + assertThat(putRoleMappingRequest.isEnabled(), equalTo(enabled)); + assertThat(putRoleMappingRequest.getRefreshPolicy(), equalTo((refreshPolicy == null) ? RefreshPolicy.getDefault() : refreshPolicy)); + assertThat(putRoleMappingRequest.getRules(), equalTo(rules)); + assertThat(putRoleMappingRequest.getRoles(), equalTo(roles)); + assertThat(putRoleMappingRequest.getMetadata(), equalTo((metadata == null) ? Collections.emptyMap() : metadata)); + } + + public void testPutRoleMappingRequestThrowsExceptionForNullOrEmptyName() { + final String name = randomBoolean() ? null : ""; + final boolean enabled = randomBoolean(); + final List roles = Collections.singletonList("superuser"); + final RoleMapperExpression rules = FieldRoleMapperExpression.ofUsername("user"); + final Map metadata = new HashMap<>(); + metadata.put("k1", "v1"); + final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); + + final IllegalArgumentException ile = expectThrows(IllegalArgumentException.class, () -> new PutRoleMappingRequest(name, enabled, + roles, rules, metadata, refreshPolicy)); + assertThat(ile.getMessage(), equalTo("role-mapping name is missing")); + } + + public void testPutRoleMappingRequestThrowsExceptionForNullOrEmptyRoles() { + final String name = randomAlphaOfLength(5); + final boolean enabled = randomBoolean(); + final List roles = randomBoolean() ? null : Collections.emptyList(); + final RoleMapperExpression rules = FieldRoleMapperExpression.ofUsername("user"); + final Map metadata = new HashMap<>(); + metadata.put("k1", "v1"); + final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); + + final IllegalArgumentException ile = expectThrows(IllegalArgumentException.class, () -> new PutRoleMappingRequest(name, enabled, + roles, rules, metadata, refreshPolicy)); + assertThat(ile.getMessage(), equalTo("role-mapping roles are missing")); + } + + public void testPutRoleMappingRequestThrowsExceptionForNullRules() { + final String name = randomAlphaOfLength(5); + final boolean enabled = randomBoolean(); + final List roles = Collections.singletonList("superuser"); + final RoleMapperExpression rules = null; + final Map metadata = new HashMap<>(); + metadata.put("k1", "v1"); + final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values()); + + expectThrows(NullPointerException.class, () -> new PutRoleMappingRequest(name, enabled, roles, rules, metadata, refreshPolicy)); } public void testPutRoleMappingRequestToXContent() throws IOException { From 06944f4e46e95bf858c812f2516794f787eed3a1 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad Date: Tue, 16 Oct 2018 06:37:21 +1100 Subject: [PATCH 7/7] Add comment on how the parser ignores the role_mapping field --- .../client/security/PutRoleMappingResponse.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java index a0d7b673e3908..04cdb14163e3e 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java @@ -65,7 +65,10 @@ public int hashCode() { "put_role_mapping_response", true, args -> new PutRoleMappingResponse((boolean) args[0])); static { PARSER.declareBoolean(constructorArg(), new ParseField("created")); - PARSER.declareObject((a,b) -> {}, (parser, context) -> null, new ParseField("role_mapping")); // ignore the role_mapping field! + // To parse the "created" field we declare "role_mapping" field object. + // Once the nested field "created" is found parser constructs the target object and + // ignores the role_mapping object. + PARSER.declareObject((a,b) -> {}, (parser, context) -> null, new ParseField("role_mapping")); } public static PutRoleMappingResponse fromXContent(XContentParser parser) throws IOException {