From 0cd37ef87305d9f21d19a1355e6c65fbc3310bd4 Mon Sep 17 00:00:00 2001 From: scottinet Date: Thu, 1 Jun 2017 14:45:38 +0200 Subject: [PATCH] fix 33 --- .../java/io/kuzzle/sdk/security/User.java | 77 +++++++-- .../kuzzle/test/security/KuzzleUserTest.java | 147 +++++++++++++++--- 2 files changed, 192 insertions(+), 32 deletions(-) diff --git a/src/main/java/io/kuzzle/sdk/security/User.java b/src/main/java/io/kuzzle/sdk/security/User.java index 6dac591..d5cb6d7 100644 --- a/src/main/java/io/kuzzle/sdk/security/User.java +++ b/src/main/java/io/kuzzle/sdk/security/User.java @@ -7,9 +7,11 @@ import org.json.JSONObject; import java.util.Arrays; +import java.util.ArrayList; import io.kuzzle.sdk.core.Kuzzle; import io.kuzzle.sdk.core.Options; +import io.kuzzle.sdk.security.Profile; import io.kuzzle.sdk.listeners.ResponseListener; import io.kuzzle.sdk.listeners.OnQueryDoneListener; @@ -20,7 +22,7 @@ public class User extends AbstractSecurityDocument { /** * The Profiles Ids List. */ - private JSONArray profileIds = null; + private ArrayList profileIds = new ArrayList<>(); private JSONObject credentials = new JSONObject(); @@ -41,7 +43,11 @@ public User(final Kuzzle kuzzle, @NonNull final String id, final JSONObject cont this.content = new JSONObject(content.toString()); if (content.has("profileIds")) { - this.profileIds = content.getJSONArray("profileIds"); + JSONArray profiles = content.getJSONArray("profileIds"); + + for (int i = 0; i < profiles.length(); i++) { + this.profileIds.add(profiles.getString(i)); + } } } } @@ -57,7 +63,8 @@ public User setProfiles(@NonNull final String[] profileIds) { throw new IllegalArgumentException("User.setProfiles: you must provide an array of profiles IDs strings"); } - this.profileIds = new JSONArray(Arrays.asList(profileIds)); + this.profileIds.clear(); + this.profileIds.addAll(Arrays.asList(profileIds)); return this; } @@ -73,7 +80,7 @@ public User addProfile(@NonNull final String profile) { throw new IllegalArgumentException("User.addProfile: you must provide a string"); } - this.profileIds.put(profile); + this.profileIds.add(profile); return this; } @@ -278,8 +285,8 @@ public JSONObject serialize() throws JSONException { data = new JSONObject().put("_id", this.id), content = new JSONObject(this.content.toString()); - if (this.profileIds != null) { - content.put("profileIds", this.profileIds); + if (this.profileIds.size() > 0) { + content.put("profileIds", new JSONArray(this.profileIds)); } data.put("body", content); @@ -300,8 +307,8 @@ public JSONObject creationSerialize() throws JSONException { content = new JSONObject(this.content.toString()), credentials = new JSONObject(this.credentials.toString()); - if (this.profileIds != null) { - content.put("profileIds", this.profileIds); + if (this.profileIds.size() > 0) { + content.put("profileIds", new JSONArray(this.profileIds)); } body.put("content", content); @@ -316,8 +323,58 @@ public JSONObject creationSerialize() throws JSONException { * * @return an array of strings */ - public JSONArray getProfiles() { - return this.profileIds; + public String[] getProfileIds() { + return this.profileIds.toArray(new String[0]); + } + + /** + * Resolves to the associated profiles as Profile objects + */ + public void getProfiles(final ResponseListener listener) throws JSONException { + getProfiles(null, listener); + } + + public void getProfiles(final Options options, final ResponseListener listener) throws JSONException { + if (listener == null) { + throw new IllegalArgumentException("User.getProfiles: a valid ResponseListener object is required"); + } + + final Profile[] profiles = new Profile[this.profileIds.size()]; + + if (this.profileIds.size() == 0) { + listener.onSuccess(profiles); + return; + } + + // using an array to allow these variables to be final + // while keeping the possibility to change their value + final int[] fetched = {0}; + final boolean[] errored = {false}; + + for (int i = 0; i < this.profileIds.size(); i++) { + this.kuzzleSecurity.fetchProfile(this.profileIds.get(i), options, new ResponseListener() { + @Override + public void onSuccess(Profile response) { + profiles[fetched[0]] = response; + fetched[0]++; + + if (fetched[0] == User.this.profileIds.size()) { + listener.onSuccess(profiles); + } + } + + @Override + public void onError(JSONObject error) { + // prevents triggering the listener multiple times + if (errored[0]) { + return; + } + + errored[0] = true; + listener.onError(error); + } + }); + } } /** diff --git a/src/test/java/io/kuzzle/test/security/KuzzleUserTest.java b/src/test/java/io/kuzzle/test/security/KuzzleUserTest.java index fd87a0d..7e877c7 100644 --- a/src/test/java/io/kuzzle/test/security/KuzzleUserTest.java +++ b/src/test/java/io/kuzzle/test/security/KuzzleUserTest.java @@ -13,12 +13,14 @@ import io.kuzzle.sdk.core.Options; import io.kuzzle.sdk.listeners.ResponseListener; import io.kuzzle.sdk.listeners.OnQueryDoneListener; +import io.kuzzle.sdk.security.Profile; import io.kuzzle.sdk.security.Security; import io.kuzzle.sdk.security.User; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; @@ -30,24 +32,11 @@ public class KuzzleUserTest { private Kuzzle kuzzle; private User stubUser; - private ResponseListener listener; - private JSONObject stubProfile; @Before public void setUp() throws JSONException { - stubProfile = new JSONObject( - "{" + - "\"profile\": {" + - "\"_id\": \"bar\"," + - "\"_source\": {}" + - "}," + - "\"someuseless\": \"field\"" + - "}" - ); - kuzzle = mock(Kuzzle.class); kuzzle.security = new Security(kuzzle); - listener = mock(ResponseListener.class); stubUser = new User(kuzzle, "foo", null); } @@ -55,7 +44,7 @@ public void setUp() throws JSONException { public void testKuzzleUserConstructorNoContent() throws JSONException { User user = new User(kuzzle, "foo", null); assertEquals(user.id, "foo"); - assertEquals(user.getProfiles(), null); + assertEquals(user.getProfileIds().length, 0); assertThat(user.content, instanceOf(JSONObject.class)); } @@ -69,7 +58,7 @@ public void testKuzzleUserConstructorWithEmptyProfile() throws JSONException { ); User user = new User(kuzzle, "foo", stubProfile); assertEquals(user.id, "foo"); - assertEquals(user.getProfiles().getString(0), "bar"); + assertEquals(user.getProfileIds()[0], "bar"); assertThat(user.content, instanceOf(JSONObject.class)); assertEquals(user.content.getString("someuseless"), "field"); } @@ -79,8 +68,8 @@ public void testKuzzleUserConstructorProfileWithContent() throws JSONException { JSONObject stubProfile = new JSONObject("{\"profileIds\": [\"bar\"]}"); User user = new User(kuzzle, "foo", stubProfile); assertEquals(user.id, "foo"); - assertThat(user.getProfiles(), instanceOf(JSONArray.class)); - assertEquals(user.getProfiles().getString(0), "bar"); + assertThat(user.getProfileIds(), instanceOf(String[].class)); + assertEquals(user.getProfileIds()[0], "bar"); assertThat(user.content, instanceOf(JSONObject.class)); } @@ -89,7 +78,7 @@ public void testSetProfileWithKuzzleProfile() throws JSONException { String[] ids = new String[1]; ids[0] = "foo"; stubUser.setProfiles(ids); - assertEquals(stubUser.getProfiles().getString(0), "foo"); + assertEquals(stubUser.getProfileIds()[0], "foo"); } @Test(expected = IllegalArgumentException.class) @@ -257,16 +246,16 @@ public void testSerializeWithProfile() throws JSONException { JSONObject serialized = stubUser.serialize(); assertEquals(serialized.getString("_id"), stubUser.id); assertEquals(serialized.getJSONObject("body").getString("foo"), "bar"); - assertEquals(serialized.getJSONObject("body").getJSONArray("profileIds").getString(0), stubUser.getProfiles().getString(0)); + assertEquals(serialized.getJSONObject("body").getJSONArray("profileIds").getString(0), stubUser.getProfileIds()[0]); } @Test - public void testGetProfiles() throws JSONException { + public void testGetProfileIds() throws JSONException { JSONObject stubProfile = new JSONObject( "{\"profileIds\": [\"bar\"]}" ); User user = new User(kuzzle, "foo", stubProfile); - assertEquals(user.getProfiles().getString(0), "bar"); + assertEquals(user.getProfileIds()[0], "bar"); } @Test @@ -276,7 +265,7 @@ public void testAddProfile() throws JSONException { ); User user = new User(kuzzle, "foo", stubProfile); user.addProfile("new profile"); - assertEquals(user.getProfiles().getString(1), "new profile"); + assertEquals(user.getProfileIds()[1], "new profile"); } @Test(expected = IllegalArgumentException.class) @@ -288,4 +277,118 @@ public void testAddNullProfile() throws JSONException { user.addProfile(null); doThrow(IllegalArgumentException.class).when(user).addProfile(eq((String)null)); } + + @Test(expected = IllegalArgumentException.class) + public void testGetProfilesException() throws JSONException { + User user = new User(kuzzle, "foo", new JSONObject()); + user.getProfiles(null); + } + + @Test + public void testGetProfilesEmpty() throws JSONException { + User user = new User(kuzzle, "foo", new JSONObject()); + + user.getProfiles(new ResponseListener() { + @Override + public void onSuccess(Profile[] response) { + assertEquals(response.length, 0); + } + + @Override + public void onError(JSONObject error) { + fail("onError callback should not have been invoked"); + } + }); + } + + @Test + public void testGetProfiles() throws JSONException { + JSONArray profiles = new JSONArray().put("foo").put("bar").put("baz"); + User user = new User(kuzzle, "foo", new JSONObject().put("profileIds", profiles)); + + Answer mockAnswer = new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + ((OnQueryDoneListener) invocation + .getArguments()[3]) + .onSuccess(new JSONObject() + .put("result", new JSONObject() + .put("_id", "foobar") + .put("_source", new JSONObject() + .put("policies", new JSONArray()) + ) + ) + ); + return null; + } + }; + + doAnswer(mockAnswer) + .when(kuzzle) + .query( + any(io.kuzzle.sdk.core.Kuzzle.QueryArgs.class), + any(JSONObject.class), + any(Options.class), + any(OnQueryDoneListener.class) + ); + + user.getProfiles(new ResponseListener() { + @Override + public void onSuccess(Profile[] response) { + assertEquals(response.length, 3); + } + + @Override + public void onError(JSONObject error) { + fail("onError should not have been invoked"); + } + }); + + ArgumentCaptor argument = ArgumentCaptor.forClass(io.kuzzle.sdk.core.Kuzzle.QueryArgs.class); + verify(kuzzle, times(3)).query((io.kuzzle.sdk.core.Kuzzle.QueryArgs) argument.capture(), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + } + + @Test + public void testGetProfilesError() throws JSONException { + JSONArray profiles = new JSONArray().put("foo").put("bar").put("baz"); + User user = new User(kuzzle, "foo", new JSONObject().put("profileIds", profiles)); + final boolean[] invoked = {false}; + + Answer mockAnswer = new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + ((OnQueryDoneListener) invocation.getArguments()[3]).onError(mock(JSONObject.class)); + return null; + } + }; + + doAnswer(mockAnswer) + .when(kuzzle) + .query( + any(io.kuzzle.sdk.core.Kuzzle.QueryArgs.class), + any(JSONObject.class), + any(Options.class), + any(OnQueryDoneListener.class) + ); + + user.getProfiles(new ResponseListener() { + @Override + public void onSuccess(Profile[] response) { + fail("onSuccess should not have been invoked"); + } + + @Override + public void onError(JSONObject error) { + if (invoked[0] == true) { + fail("onError invoked more than once"); + return; + } + + invoked[0] = true; + } + }); + + ArgumentCaptor argument = ArgumentCaptor.forClass(io.kuzzle.sdk.core.Kuzzle.QueryArgs.class); + verify(kuzzle, times(3)).query((io.kuzzle.sdk.core.Kuzzle.QueryArgs) argument.capture(), any(JSONObject.class), any(Options.class), any(OnQueryDoneListener.class)); + } }