From 2fe33e5468b8c617f6205aeef50c97b017a12c84 Mon Sep 17 00:00:00 2001 From: Ravi Ranjan Date: Wed, 13 Apr 2016 15:31:45 +0530 Subject: [PATCH 1/4] search should aware notebook permissions --- .../apache/zeppelin/rest/NotebookRestApi.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java index 2796500ac86..3cf42894650 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java @@ -650,8 +650,25 @@ public Response getCronJob(@PathParam("notebookId") String notebookId) throws @Path("search") public Response search(@QueryParam("q") String queryTerm) { LOG.info("Searching notebooks for: {}", queryTerm); + String principal = SecurityUtils.getPrincipal(); + HashSet roles = SecurityUtils.getRoles(); + HashSet userAndRoles = new HashSet(); + userAndRoles.add(principal); + userAndRoles.addAll(roles); List> notebooksFound = notebookIndex.query(queryTerm); - LOG.info("{} notbooks found", notebooksFound.size()); + for (int i = 0; i < notebooksFound.size(); i++) + { + String[] Id = notebooksFound.get(i).get("id").split("/", 2); + String noteId = Id[0]; + if (!notebookAuthorization.isOwner(noteId, userAndRoles) && + !notebookAuthorization.isReader(noteId, userAndRoles) && + !notebookAuthorization.isWriter(noteId, userAndRoles)) { + notebooksFound.remove(i); + i--; + } + LOG.info("noteId", noteId); + } + LOG.info("{} notebooks found", notebooksFound.size()); return new JsonResponse<>(Status.OK, notebooksFound).build(); } From 7a624d0b883f345f3439812f88b9144cf7e11c18 Mon Sep 17 00:00:00 2001 From: Ravi Ranjan Date: Sat, 23 Apr 2016 18:19:41 +0530 Subject: [PATCH 2/4] Add rest API test --- .../zeppelin/rest/ZeppelinRestApiTest.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java index 3c7c7d0e67e..a82c927ef5e 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java @@ -18,6 +18,7 @@ package org.apache.zeppelin.rest; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -690,5 +691,85 @@ public void testDeleteParagraph() throws IOException { ZeppelinServer.notebook.removeNote(note.getId()); } + + @Test + public void testSearch() throws IOException { + String jsonRequest; + PostMethod post; + PutMethod put; + GetMethod get; + Map resp; + Map body; + ArrayList searchBody; + Map permissions; + + get = httpGet("/security/ticket"); + get.addRequestHeader("Origin", "http://localhost"); + resp = gson.fromJson(get.getResponseBodyAsString(), + new TypeToken>() { + }.getType()); + body = (Map) resp.get("body"); + String username = body.get("principal"); + get.releaseConnection(); + + + Note note1 = ZeppelinServer.notebook.createNote(); + jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 1\"}"; + post = httpPost("/notebook/" + note1.getId() + "/paragraph", jsonRequest); + post.releaseConnection(); + + Note note2 = ZeppelinServer.notebook.createNote(); + jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 2\"}"; + post = httpPost("/notebook/" + note2.getId() + "/paragraph", jsonRequest); + post.releaseConnection(); + + Note note3 = ZeppelinServer.notebook.createNote(); + jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 3\"}"; + post = httpPost("/notebook/" + note3.getId() + "/paragraph", jsonRequest); + post.releaseConnection(); + + jsonRequest = "{\"owners\":[\"" + username + "\"],\"readers\":[\"" + username + "\"],\"writers\":[\"" + username + "\"]}"; + put = httpPut("/notebook/" + note1.getId() + "/permissions", jsonRequest); + put.releaseConnection(); + + jsonRequest = "{\"owners\":[\"admin\"],\"readers\":[\"admin\"],\"writers\":[\"admin\"]}"; + put = httpPut("/notebook/" + note2.getId() + "/permissions", jsonRequest); + put.releaseConnection(); + + jsonRequest = "{\"owners\":[\"" + username + "\"],\"readers\":[\"" + username + "\"],\"writers\":[\"" + username + "\"]}"; + put = httpPut("/notebook/" + note3.getId() + "/permissions", jsonRequest); + put.releaseConnection(); + + get = httpGet("/notebook/search?q='ThisIsToTestSearchMethodWithPermissions'"); + get.addRequestHeader("Origin", "http://localhost"); + Map res = gson.fromJson(get.getResponseBodyAsString(), + new TypeToken>() { + }.getType()); + searchBody = (ArrayList) res.get("body"); + + for (int i = 0; i < searchBody.size(); i++) { + Map searchResult = (Map) searchBody.get(i); + String userId = searchResult.get("id").split("/", 2)[0]; + GetMethod getPermission = httpGet("/notebook/" + userId + "/permissions"); + getPermission.addRequestHeader("Origin", "http://localhost"); + resp = gson.fromJson(getPermission.getResponseBodyAsString(), + new TypeToken>() { + }.getType()); + permissions = (Map) resp.get("body"); + ArrayList owners = permissions.get("owners"); + ArrayList readers = permissions.get("readers"); + ArrayList writers = permissions.get("writers"); + + if (owners.size() != 0 && readers.size() != 0 && writers.size() != 0) { + assertEquals("User has permissions ", true, (owners.contains(username) || readers.contains(username) || + writers.contains(username))); + } + getPermission.releaseConnection(); + } + get.releaseConnection(); + ZeppelinServer.notebook.removeNote(note1.getId()); + ZeppelinServer.notebook.removeNote(note2.getId()); + ZeppelinServer.notebook.removeNote(note3.getId()); + } } From c42573e8b4753f8f2183d81fa5fdee13e17a8cab Mon Sep 17 00:00:00 2001 From: Ravi Ranjan Date: Sun, 24 Apr 2016 11:38:56 +0530 Subject: [PATCH 3/4] Add check to see search searching all allowed notebook --- .../test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java index a82c927ef5e..1a71b7d204e 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java @@ -746,7 +746,7 @@ public void testSearch() throws IOException { new TypeToken>() { }.getType()); searchBody = (ArrayList) res.get("body"); - + assertEquals("At-least two search results are there", true ,searchBody.size()>=2); for (int i = 0; i < searchBody.size(); i++) { Map searchResult = (Map) searchBody.get(i); String userId = searchResult.get("id").split("/", 2)[0]; From a4a99994e2aaa55d43a22d950fdd181dc29fecba Mon Sep 17 00:00:00 2001 From: Ravi Ranjan Date: Tue, 26 Apr 2016 10:57:37 +0530 Subject: [PATCH 4/4] Make test more Readable --- .../apache/zeppelin/rest/NotebookRestApi.java | 6 +- .../zeppelin/rest/ZeppelinRestApiTest.java | 69 ++++++++----------- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java index 3cf42894650..005a14b0a78 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java @@ -644,7 +644,7 @@ public Response getCronJob(@PathParam("notebookId") String notebookId) throws } /** - * Search for a Notes + * Search for a Notes with permissions */ @GET @Path("search") @@ -656,8 +656,7 @@ public Response search(@QueryParam("q") String queryTerm) { userAndRoles.add(principal); userAndRoles.addAll(roles); List> notebooksFound = notebookIndex.query(queryTerm); - for (int i = 0; i < notebooksFound.size(); i++) - { + for (int i = 0; i < notebooksFound.size(); i++) { String[] Id = notebooksFound.get(i).get("id").split("/", 2); String noteId = Id[0]; if (!notebookAuthorization.isOwner(noteId, userAndRoles) && @@ -666,7 +665,6 @@ public Response search(@QueryParam("q") String queryTerm) { notebooksFound.remove(i); i--; } - LOG.info("noteId", noteId); } LOG.info("{} notebooks found", notebooksFound.size()); return new JsonResponse<>(Status.OK, notebooksFound).build(); diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java index 1a71b7d204e..2f2a36bc5b7 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java @@ -694,68 +694,53 @@ public void testDeleteParagraph() throws IOException { @Test public void testSearch() throws IOException { - String jsonRequest; - PostMethod post; - PutMethod put; - GetMethod get; - Map resp; Map body; - ArrayList searchBody; - Map permissions; - get = httpGet("/security/ticket"); - get.addRequestHeader("Origin", "http://localhost"); - resp = gson.fromJson(get.getResponseBodyAsString(), + GetMethod getSecurityTicket = httpGet("/security/ticket"); + getSecurityTicket.addRequestHeader("Origin", "http://localhost"); + Map respSecurityTicket = gson.fromJson(getSecurityTicket.getResponseBodyAsString(), new TypeToken>() { }.getType()); - body = (Map) resp.get("body"); + body = (Map) respSecurityTicket.get("body"); String username = body.get("principal"); - get.releaseConnection(); - + getSecurityTicket.releaseConnection(); Note note1 = ZeppelinServer.notebook.createNote(); - jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 1\"}"; - post = httpPost("/notebook/" + note1.getId() + "/paragraph", jsonRequest); - post.releaseConnection(); + String jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 1\"}"; + PostMethod postNotebookText = httpPost("/notebook/" + note1.getId() + "/paragraph", jsonRequest); + postNotebookText.releaseConnection(); Note note2 = ZeppelinServer.notebook.createNote(); jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 2\"}"; - post = httpPost("/notebook/" + note2.getId() + "/paragraph", jsonRequest); - post.releaseConnection(); - - Note note3 = ZeppelinServer.notebook.createNote(); - jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 3\"}"; - post = httpPost("/notebook/" + note3.getId() + "/paragraph", jsonRequest); - post.releaseConnection(); - - jsonRequest = "{\"owners\":[\"" + username + "\"],\"readers\":[\"" + username + "\"],\"writers\":[\"" + username + "\"]}"; - put = httpPut("/notebook/" + note1.getId() + "/permissions", jsonRequest); - put.releaseConnection(); + postNotebookText = httpPost("/notebook/" + note2.getId() + "/paragraph", jsonRequest); + postNotebookText.releaseConnection(); - jsonRequest = "{\"owners\":[\"admin\"],\"readers\":[\"admin\"],\"writers\":[\"admin\"]}"; - put = httpPut("/notebook/" + note2.getId() + "/permissions", jsonRequest); - put.releaseConnection(); + String jsonPermissions = "{\"owners\":[\"" + username + "\"],\"readers\":[\"" + username + "\"],\"writers\":[\"" + username + "\"]}"; + PutMethod putPermission = httpPut("/notebook/" + note1.getId() + "/permissions", jsonPermissions); + putPermission.releaseConnection(); - jsonRequest = "{\"owners\":[\"" + username + "\"],\"readers\":[\"" + username + "\"],\"writers\":[\"" + username + "\"]}"; - put = httpPut("/notebook/" + note3.getId() + "/permissions", jsonRequest); - put.releaseConnection(); + jsonPermissions = "{\"owners\":[\"admin\"],\"readers\":[\"admin\"],\"writers\":[\"admin\"]}"; + putPermission = httpPut("/notebook/" + note2.getId() + "/permissions", jsonPermissions); + putPermission.releaseConnection(); - get = httpGet("/notebook/search?q='ThisIsToTestSearchMethodWithPermissions'"); - get.addRequestHeader("Origin", "http://localhost"); - Map res = gson.fromJson(get.getResponseBodyAsString(), + GetMethod searchNotebook = httpGet("/notebook/search?q='ThisIsToTestSearchMethodWithPermissions'"); + searchNotebook.addRequestHeader("Origin", "http://localhost"); + Map respSearchResult = gson.fromJson(searchNotebook.getResponseBodyAsString(), new TypeToken>() { }.getType()); - searchBody = (ArrayList) res.get("body"); - assertEquals("At-least two search results are there", true ,searchBody.size()>=2); + ArrayList searchBody = (ArrayList) respSearchResult.get("body"); + + assertEquals("At-least one search results is there", true, searchBody.size() >= 1); + for (int i = 0; i < searchBody.size(); i++) { Map searchResult = (Map) searchBody.get(i); String userId = searchResult.get("id").split("/", 2)[0]; GetMethod getPermission = httpGet("/notebook/" + userId + "/permissions"); getPermission.addRequestHeader("Origin", "http://localhost"); - resp = gson.fromJson(getPermission.getResponseBodyAsString(), + Map resp = gson.fromJson(getPermission.getResponseBodyAsString(), new TypeToken>() { }.getType()); - permissions = (Map) resp.get("body"); + Map permissions = (Map) resp.get("body"); ArrayList owners = permissions.get("owners"); ArrayList readers = permissions.get("readers"); ArrayList writers = permissions.get("writers"); @@ -766,10 +751,10 @@ public void testSearch() throws IOException { } getPermission.releaseConnection(); } - get.releaseConnection(); + searchNotebook.releaseConnection(); ZeppelinServer.notebook.removeNote(note1.getId()); ZeppelinServer.notebook.removeNote(note2.getId()); - ZeppelinServer.notebook.removeNote(note3.getId()); } + }