From 9758d18c4f42f93eaadfa8f53c95cc8350aa3b6b Mon Sep 17 00:00:00 2001 From: Karan Kajla Date: Thu, 28 Sep 2023 16:49:42 -0700 Subject: [PATCH] Add support for Query API --- .../java/dev/warrant/WarrantBaseClient.java | 12 +++ .../java/dev/warrant/model/QueryResult.java | 52 +++++++++++ .../dev/warrant/model/QueryResultSet.java | 24 +++++ src/main/java/dev/warrant/model/Warrant.java | 29 ++++--- src/test/java/dev/warrant/LiveTest.java | 53 +++++++++++ .../java/dev/warrant/WarrantClientTest.java | 87 ++++++++++++------- 6 files changed, 213 insertions(+), 44 deletions(-) create mode 100644 src/main/java/dev/warrant/model/QueryResult.java create mode 100644 src/main/java/dev/warrant/model/QueryResultSet.java diff --git a/src/main/java/dev/warrant/WarrantBaseClient.java b/src/main/java/dev/warrant/WarrantBaseClient.java index 9b20fa2..9a4c4cd 100644 --- a/src/main/java/dev/warrant/WarrantBaseClient.java +++ b/src/main/java/dev/warrant/WarrantBaseClient.java @@ -17,6 +17,7 @@ import dev.warrant.exception.WarrantException; import dev.warrant.model.WarrantSubject; +import dev.warrant.model.QueryResultSet; import dev.warrant.model.UserSession; import dev.warrant.model.UserSessionSpec; import dev.warrant.model.Warrant; @@ -96,6 +97,17 @@ public Warrant[] listWarrants(WarrantFilters filters, ListParams listParams, Req return makeGetRequest("/v1/warrants", queryParams, Warrant[].class, requestOptions.asMap()); } + public QueryResultSet query(String query, ListParams listParams) throws WarrantException { + return query(query, listParams, new RequestOptions()); + } + + public QueryResultSet query(String query, ListParams listParams, RequestOptions requestOptions) + throws WarrantException { + Map queryParams = listParams.asMap(); + queryParams.put("q", query); + return makeGetRequest("/v1/query", queryParams, QueryResultSet.class, requestOptions.asMap()); + } + public boolean check(WarrantObject object, String relation, WarrantSubject subject) throws WarrantException { return check(object, relation, subject, Collections.emptyMap(), new RequestOptions()); } diff --git a/src/main/java/dev/warrant/model/QueryResult.java b/src/main/java/dev/warrant/model/QueryResult.java new file mode 100644 index 0000000..335ab8c --- /dev/null +++ b/src/main/java/dev/warrant/model/QueryResult.java @@ -0,0 +1,52 @@ +package dev.warrant.model; + +public class QueryResult { + + private String objectType; + private String objectId; + private Warrant warrant; + private Boolean isImplicit; + + public QueryResult() { + // For json serialization + } + + public QueryResult(String objectType, String objectId, Warrant warrant, Boolean isImplicit) { + this.objectType = objectType; + this.objectId = objectId; + this.warrant = warrant; + this.isImplicit = isImplicit; + } + + public String getObjectType() { + return this.objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public String getObjectId() { + return this.objectId; + } + + public void setObjectId(String objectId) { + this.objectId = objectId; + } + + public Warrant getWarrant() { + return this.warrant; + } + + public void setWarrant(Warrant warrant) { + this.warrant = warrant; + } + + public Boolean isImplicit() { + return this.isImplicit; + } + + public void setIsImplicit(Boolean isImplicit) { + this.isImplicit = isImplicit; + } +} diff --git a/src/main/java/dev/warrant/model/QueryResultSet.java b/src/main/java/dev/warrant/model/QueryResultSet.java new file mode 100644 index 0000000..645a640 --- /dev/null +++ b/src/main/java/dev/warrant/model/QueryResultSet.java @@ -0,0 +1,24 @@ +package dev.warrant.model; + +public class QueryResultSet { + + private QueryResult[] results; + private String lastId; + + public QueryResultSet() { + // For json serialization + } + + public QueryResultSet(QueryResult[] results, String lastId) { + this.results = results; + this.lastId = lastId; + } + + public QueryResult[] getResults() { + return this.results; + } + + public String getLastId() { + return this.lastId; + } +} diff --git a/src/main/java/dev/warrant/model/Warrant.java b/src/main/java/dev/warrant/model/Warrant.java index 62fd441..bb2fb4a 100644 --- a/src/main/java/dev/warrant/model/Warrant.java +++ b/src/main/java/dev/warrant/model/Warrant.java @@ -7,7 +7,6 @@ public class Warrant { private String relation; private WarrantSubject subject; private String policy; - private boolean isImplicit; public Warrant() { // For json serialization @@ -28,35 +27,43 @@ public Warrant(String objectType, String objectId, String relation, WarrantSubje this.policy = policy; } - public Warrant(String objectType, String objectId, String relation, WarrantSubject subject, boolean isImplicit) { - this.objectType = objectType; - this.objectId = objectId; - this.relation = relation; - this.subject = subject; - this.isImplicit = isImplicit; - } - public String getObjectType() { return objectType; } + public void setObjectType(String objectType) { + this.objectType = objectType; + } + public String getObjectId() { return objectId; } + public void setObjectId(String objectId) { + this.objectId = objectId; + } + public String getRelation() { return relation; } + public void setRelation(String relation) { + this.relation = relation; + } + public WarrantSubject getSubject() { return subject; } + public void setSubject(WarrantSubject subject) { + this.subject = subject; + } + public String getPolicy() { return policy; } - public boolean getIsImplicit() { - return isImplicit; + public void setPolicy(String policy) { + this.policy = policy; } } diff --git a/src/test/java/dev/warrant/LiveTest.java b/src/test/java/dev/warrant/LiveTest.java index df67229..75e45e9 100644 --- a/src/test/java/dev/warrant/LiveTest.java +++ b/src/test/java/dev/warrant/LiveTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; import dev.warrant.exception.WarrantException; +import dev.warrant.model.QueryResultSet; import dev.warrant.model.Warrant; import dev.warrant.model.WarrantCheck; import dev.warrant.model.WarrantSpec; @@ -558,4 +559,56 @@ public void testAllOfAnyOfBatchCheck() throws WarrantException { client.deletePermission(permission2); client.deletePermission(permission3); } + + @Test + public void testQuery() throws WarrantException { + User userA = client.createUser(new User("userA")); + User userB = client.createUser(new User("userB")); + Permission permission1 = client.createPermission( + new Permission("perm1", "Permission 1", "This is permission 1.")); + Permission permission2 = client.createPermission(new Permission("perm2")); + Permission permission3 = client.createPermission( + new Permission("perm3", "Permission 3", "This is permission 3.")); + Role role1 = client.createRole(new Role("role1", "Role 1", "This is role 1.")); + Role role2 = client.createRole(new Role("role2", "Role 2")); + + client.assignPermissionToRole("perm1", "role1"); + client.assignPermissionToRole("perm2", "role2"); + client.assignPermissionToRole("perm3", "role2"); + client.createWarrant(role2, "member", new WarrantSubject("role", "role1")); + client.assignRoleToUser("role1", "userA"); + client.assignRoleToUser("role2", "userB"); + + QueryResultSet resultSet = client.query("select role where user:userA is member", + new ListParams().withLimit(1)); + Assertions.assertEquals(1, resultSet.getResults().length); + Assertions.assertEquals("role", resultSet.getResults()[0].getObjectType()); + Assertions.assertEquals("role1", resultSet.getResults()[0].getObjectId()); + Assertions.assertFalse(resultSet.getResults()[0].isImplicit()); + Assertions.assertEquals("role", resultSet.getResults()[0].getWarrant().getObjectType()); + Assertions.assertEquals("role1", resultSet.getResults()[0].getWarrant().getObjectId()); + Assertions.assertEquals("member", resultSet.getResults()[0].getWarrant().getRelation()); + Assertions.assertEquals("user", resultSet.getResults()[0].getWarrant().getSubject().getObjectType()); + Assertions.assertEquals("userA", resultSet.getResults()[0].getWarrant().getSubject().getObjectId()); + + resultSet = client.query("select role where user:userA is member", + new ListParams().withLimit(1).withAfterId(resultSet.getLastId())); + Assertions.assertEquals(1, resultSet.getResults().length); + Assertions.assertEquals("role", resultSet.getResults()[0].getObjectType()); + Assertions.assertEquals("role2", resultSet.getResults()[0].getObjectId()); + Assertions.assertTrue(resultSet.getResults()[0].isImplicit()); + Assertions.assertEquals("role", resultSet.getResults()[0].getWarrant().getObjectType()); + Assertions.assertEquals("role2", resultSet.getResults()[0].getWarrant().getObjectId()); + Assertions.assertEquals("member", resultSet.getResults()[0].getWarrant().getRelation()); + Assertions.assertEquals("role", resultSet.getResults()[0].getWarrant().getSubject().getObjectType()); + Assertions.assertEquals("role1", resultSet.getResults()[0].getWarrant().getSubject().getObjectId()); + + client.deleteRole(role1); + client.deleteRole(role2); + client.deletePermission(permission3); + client.deletePermission(permission2); + client.deletePermission(permission1); + client.deleteUser(userB); + client.deleteUser(userA); + } } diff --git a/src/test/java/dev/warrant/WarrantClientTest.java b/src/test/java/dev/warrant/WarrantClientTest.java index 3970215..ffbe4aa 100644 --- a/src/test/java/dev/warrant/WarrantClientTest.java +++ b/src/test/java/dev/warrant/WarrantClientTest.java @@ -13,6 +13,8 @@ import dev.warrant.exception.WarrantException; import dev.warrant.model.WarrantSubject; +import dev.warrant.model.QueryResult; +import dev.warrant.model.QueryResultSet; import dev.warrant.model.Warrant; import dev.warrant.model.object.Tenant; import dev.warrant.model.object.User; @@ -90,37 +92,56 @@ public void testCreateTenantWithId() throws WarrantException { Assertions.assertNull(newTenant.getName()); } - // @Test - // public void testQueryWarrants() throws WarrantException { - // Mockito.when(httpResponse.statusCode()).thenReturn(200); - // Mockito.when(httpResponse.body()) - // .thenReturn( - // "[\n {\n \"objectType\": \"role\",\n \"objectId\": \"admin\",\n \"relation\": \"member\",\n \"subject\": {\n \"objectType\": \"user\",\n \"objectId\": \"6\"\n },\n \"isImplicit\": false\n },\n {\n \"objectType\": \"role\",\n \"objectId\": \"manager\",\n \"relation\": \"member\",\n \"subject\": {\n \"objectType\": \"user\",\n \"objectId\": \"6\"\n },\n \"isImplicit\": true\n }\n]"); - - // Query q = Query.selectWarrants() - // .forClause("subject=user:6") - // .where("subject=user:6"); - // WarrantClient warrantClient = new WarrantClient(WarrantConfig.withApiKey("sample_key"), httpClient); - // Warrant[] warrants = warrantClient.queryWarrants(q, 100, 1); - // Warrant[] expectedWarrants = { - // new Warrant("role", "admin", "member", new WarrantSubject("user", "6"), false), - // new Warrant("role", "manager", "member", new WarrantSubject("user", "6"), true) - // }; - - // Assertions.assertEquals(expectedWarrants[0].getObjectType(), warrants[0].getObjectType()); - // Assertions.assertEquals(expectedWarrants[0].getObjectId(), warrants[0].getObjectId()); - // Assertions.assertEquals(expectedWarrants[0].getRelation(), warrants[0].getRelation()); - // Assertions.assertEquals(expectedWarrants[0].getSubject().getObjectType(), - // warrants[0].getSubject().getObjectType()); - // Assertions.assertEquals(expectedWarrants[0].getSubject().getObjectId(), warrants[0].getSubject().getObjectId()); - // Assertions.assertEquals(expectedWarrants[0].getIsImplicit(), warrants[0].getIsImplicit()); - - // Assertions.assertEquals(expectedWarrants[1].getObjectType(), warrants[1].getObjectType()); - // Assertions.assertEquals(expectedWarrants[1].getObjectId(), warrants[1].getObjectId()); - // Assertions.assertEquals(expectedWarrants[1].getRelation(), warrants[1].getRelation()); - // Assertions.assertEquals(expectedWarrants[1].getSubject().getObjectType(), - // warrants[1].getSubject().getObjectType()); - // Assertions.assertEquals(expectedWarrants[1].getSubject().getObjectId(), warrants[1].getSubject().getObjectId()); - // Assertions.assertEquals(expectedWarrants[1].getIsImplicit(), warrants[1].getIsImplicit()); - // } + @Test + public void testQuery() throws WarrantException { + Mockito.when(httpResponse.statusCode()).thenReturn(200); + Mockito.when(httpResponse.body()) + .thenReturn( + "{\"results\":[{\"objectType\":\"role\",\"objectId\":\"admin\",\"warrant\":{\"objectType\":\"role\",\"objectId\":\"admin\",\"relation\":\"member\",\"subject\":{\"objectType\":\"user\",\"objectId\":\"6\"}},\"isImplicit\":false,\"meta\":{\"name\":\"Admin\"}},{\"objectType\":\"role\",\"objectId\":\"manager\",\"warrant\":{\"objectType\":\"role\",\"objectId\":\"manager\",\"relation\":\"member\",\"subject\":{\"objectType\":\"role\",\"objectId\":\"admin\"}},\"isImplicit\":true,\"meta\":{\"name\":\"Manager\"}}]}\n"); + + WarrantClient warrantClient = new WarrantClient(WarrantConfig.withApiKey("sample_key"), httpClient); + QueryResultSet queryResultSet = warrantClient.query("select role where user:6 is member", new ListParams(), + new RequestOptions()); + QueryResult[] expectedQueryResults = { + new QueryResult("role", "admin", + new Warrant("role", "admin", "member", new WarrantSubject("user", "6")), false), + new QueryResult("role", "manager", + new Warrant("role", "manager", "member", new WarrantSubject("role", "admin")), true) + }; + QueryResultSet expectedQueryResultSet = new QueryResultSet(expectedQueryResults, ""); + + Assertions.assertEquals(expectedQueryResultSet.getResults().length, queryResultSet.getResults().length); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].getObjectType(), + queryResultSet.getResults()[0].getObjectType()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].getObjectId(), + queryResultSet.getResults()[0].getObjectId()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].getWarrant().getObjectType(), + queryResultSet.getResults()[0].getWarrant().getObjectType()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].getWarrant().getObjectId(), + queryResultSet.getResults()[0].getWarrant().getObjectId()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].getWarrant().getRelation(), + queryResultSet.getResults()[0].getWarrant().getRelation()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].getWarrant().getSubject().getObjectType(), + queryResultSet.getResults()[0].getWarrant().getSubject().getObjectType()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].getWarrant().getSubject().getObjectId(), + queryResultSet.getResults()[0].getWarrant().getSubject().getObjectId()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[0].isImplicit(), + queryResultSet.getResults()[0].isImplicit()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].getObjectType(), + queryResultSet.getResults()[1].getObjectType()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].getObjectId(), + queryResultSet.getResults()[1].getObjectId()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].getWarrant().getObjectType(), + queryResultSet.getResults()[1].getWarrant().getObjectType()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].getWarrant().getObjectId(), + queryResultSet.getResults()[1].getWarrant().getObjectId()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].getWarrant().getRelation(), + queryResultSet.getResults()[1].getWarrant().getRelation()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].getWarrant().getSubject().getObjectType(), + queryResultSet.getResults()[1].getWarrant().getSubject().getObjectType()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].getWarrant().getSubject().getObjectId(), + queryResultSet.getResults()[1].getWarrant().getSubject().getObjectId()); + Assertions.assertEquals(expectedQueryResultSet.getResults()[1].isImplicit(), + queryResultSet.getResults()[1].isImplicit()); + } }