From 4adddb49d98f35a854e40966f263acfc1a56102b Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 27 Oct 2016 16:50:18 +0900 Subject: [PATCH 1/9] Clear all paragraphs and remove note from main page --- .../zeppelin/socket/NotebookServer.java | 22 ++++++++ zeppelin-web/src/app/home/home.controller.js | 15 ++++-- zeppelin-web/src/app/home/home.html | 16 +++++- .../src/app/notebook/notebook-actionBar.html | 2 +- .../src/app/notebook/notebook.controller.js | 35 +++---------- .../noteAction/noteAction.service.js | 51 +++++++++++++++++++ .../websocketEvents/websocketMsg.service.js | 4 ++ zeppelin-web/src/index.html | 1 + .../org/apache/zeppelin/notebook/Note.java | 11 ++++ .../zeppelin/notebook/socket/Message.java | 5 +- .../interpreter/InterpreterFactoryTest.java | 1 - 11 files changed, 127 insertions(+), 36 deletions(-) create mode 100644 zeppelin-web/src/components/noteAction/noteAction.service.js diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java index a3dff401429..1711a67611e 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java @@ -215,6 +215,9 @@ public void onMessage(NotebookSocket conn, String msg) { case PARAGRAPH_CLEAR_OUTPUT: clearParagraphOutput(conn, userAndRoles, notebook, messagereceived); break; + case PARAGRAPH_CLEAR_ALL_OUTPUT: + clearAllParagraphOutput(conn, userAndRoles, notebook, messagereceived); + break; case NOTE_UPDATE: updateNote(conn, userAndRoles, notebook, messagereceived); break; @@ -780,6 +783,25 @@ private void cloneNote(NotebookSocket conn, HashSet userAndRoles, broadcastNoteList(subject, userAndRoles); } + private void clearAllParagraphOutput(NotebookSocket conn, HashSet userAndRoles, + Notebook notebook, Message fromMessage) + throws IOException { + final String noteId = (String) fromMessage.get("id"); + if (StringUtils.isBlank(noteId)) { + return; + } + Note note = notebook.getNote(noteId); + NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization(); + if (!notebookAuthorization.isOwner(noteId, userAndRoles)) { + permissionError(conn, "clear output", fromMessage.principal, + userAndRoles, notebookAuthorization.getOwners(noteId)); + return; + } + + note.clearAllParagraphOutput(); + broadcastNote(note); + } + protected Note importNote(NotebookSocket conn, HashSet userAndRoles, Notebook notebook, Message fromMessage) throws IOException { diff --git a/zeppelin-web/src/app/home/home.controller.js b/zeppelin-web/src/app/home/home.controller.js index 171a27585e8..1d11c79bfae 100644 --- a/zeppelin-web/src/app/home/home.controller.js +++ b/zeppelin-web/src/app/home/home.controller.js @@ -22,10 +22,12 @@ 'websocketMsgSrv', '$rootScope', 'arrayOrderingSrv', - 'ngToast' + 'ngToast', + 'noteActionSrv' ]; - function HomeCtrl($scope, noteListDataFactory, websocketMsgSrv, $rootScope, arrayOrderingSrv, ngToast) { + function HomeCtrl($scope, noteListDataFactory, websocketMsgSrv, $rootScope, arrayOrderingSrv, + ngToast, noteActionSrv) { ngToast.dismiss(); var vm = this; vm.notes = noteListDataFactory; @@ -85,6 +87,13 @@ vm.notebookHome = false; } }); - } + $scope.removeNote = function(noteId) { + noteActionSrv.removeNote(noteId, false); + }; + + $scope.clearAllParagraphOutput = function(noteId) { + noteActionSrv.clearAllParagraphOutput(noteId); + }; + } })(); diff --git a/zeppelin-web/src/app/home/home.html b/zeppelin-web/src/app/home/home.html index 0f8e9681b8e..a8d5e56088d 100644 --- a/zeppelin-web/src/app/home/home.html +++ b/zeppelin-web/src/app/home/home.html @@ -13,10 +13,24 @@ --> + diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index 7ad269701f5..66362bd7b99 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -326,6 +326,17 @@ public Paragraph clearParagraphOutput(String paragraphId) { return null; } + /** + * Clear all paragraph output of note + */ + public void clearAllParagraphOutput() { + synchronized (paragraphs) { + for (Paragraph p : paragraphs) { + p.setReturn(null, null); + } + } + } + /** * Move paragraph into the new index (order from 0 ~ n-1). * diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java index b78203cee50..4a4ddd1e956 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java @@ -48,7 +48,7 @@ public static enum OP { // @param id note id CLONE_NOTE, // [c-s] clone new notebook // @param id id of note to clone - // @param name name fpor the cloned note + // @param name name for the cloned note IMPORT_NOTE, // [c-s] import notebook // @param object notebook NOTE_UPDATE, @@ -96,7 +96,8 @@ public static enum OP { // @param notes serialized List object PARAGRAPH_REMOVE, - PARAGRAPH_CLEAR_OUTPUT, + PARAGRAPH_CLEAR_OUTPUT, // [c-s] clear output of paragraph + PARAGRAPH_CLEAR_ALL_OUTPUT, // [c-s] clear output of all paragraphs PARAGRAPH_APPEND_OUTPUT, // [s-c] append output PARAGRAPH_UPDATE_OUTPUT, // [s-c] update (replace) output PING, diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java index a2a799ae8a0..537313e6f5c 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java @@ -33,7 +33,6 @@ import org.apache.zeppelin.dep.DependencyResolver; import org.apache.zeppelin.interpreter.mock.MockInterpreter1; import org.apache.zeppelin.interpreter.mock.MockInterpreter2; -import org.apache.zeppelin.notebook.repo.zeppelinhub.security.Authentication; import org.apache.zeppelin.user.AuthenticationInfo; import org.apache.zeppelin.interpreter.remote.RemoteInterpreter; import org.apache.zeppelin.notebook.JobListenerFactory; From 98d7604a0f716912df8ab1749087b961933bf144 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 27 Oct 2016 17:07:29 +0900 Subject: [PATCH 2/9] Add clearAllParagraphOutput unit test --- .../apache/zeppelin/notebook/NoteTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java index a07727458f2..352a17f48c2 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java @@ -17,8 +17,10 @@ package org.apache.zeppelin.notebook; +import org.apache.zeppelin.helium.HeliumPackage; import org.apache.zeppelin.interpreter.Interpreter; import org.apache.zeppelin.interpreter.InterpreterFactory; +import org.apache.zeppelin.interpreter.InterpreterResult; import org.apache.zeppelin.notebook.repo.NotebookRepo; import org.apache.zeppelin.scheduler.Scheduler; import org.apache.zeppelin.search.SearchService; @@ -125,4 +127,23 @@ public void insertParagraphWithInvalidReplNameTest() { assertNull(p2.getText()); } + @Test + public void clearAllParagraphOutputTest() { + when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("md"))).thenReturn(interpreter); + when(interpreter.getScheduler()).thenReturn(scheduler); + + Note note = new Note(repo, interpreterFactory, jobListenerFactory, index, credentials, noteEventListener); + Paragraph p1 = note.addParagraph(); + InterpreterResult result = new InterpreterResult(InterpreterResult.Code.SUCCESS, InterpreterResult.Type.TEXT, "result"); + p1.setResult(result); + + Paragraph p2 = note.addParagraph(); + p2.setReturn(result, new Throwable()); + + note.clearAllParagraphOutput(); + + assertNull(p1.getReturn()); + assertNull(p2.getReturn()); + } + } From 3d191410ad7131e3a89a294011d65780c611c0da Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 27 Oct 2016 17:53:33 +0900 Subject: [PATCH 3/9] Add rest api for clear all paragraph result and add test --- .../apache/zeppelin/rest/NotebookRestApi.java | 24 ++++++++++ .../zeppelin/rest/NotebookRestApiTest.java | 44 +++++++++++++++++-- 2 files changed, 64 insertions(+), 4 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 ae66330785d..277870ae42e 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 @@ -461,6 +461,30 @@ public Response deleteParagraph(@PathParam("noteId") String noteId, return new JsonResponse(Status.OK, "").build(); } + /** + * Clear result of all paragraphs REST API + * + * @param noteId ID of Note + * @return JSON with status.ok + */ + @POST + @Path("{noteId}/clear") + @ZeppelinApi + public Response clearAllParagraphOutput(@PathParam("noteId") String noteId) + throws IOException { + LOG.info("clear all paragraph output of note {}", noteId); + + if (!noteId.isEmpty()) { + Note note = notebook.getNote(noteId); + if (note == null) { + return new JsonResponse(Status.NOT_FOUND, "note not found.").build(); + } + note.clearAllParagraphOutput(); + } + + return new JsonResponse(Status.OK, "").build(); + } + /** * Run note jobs REST API * diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java index 36b0f1c97b3..bcebbb8be7c 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java @@ -18,15 +18,14 @@ package org.apache.zeppelin.rest; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.zeppelin.interpreter.InterpreterResult; import org.apache.zeppelin.notebook.Note; -import org.apache.zeppelin.notebook.NotebookAuthorization; -import org.apache.zeppelin.notebook.NotebookAuthorizationInfoSaving; +import org.apache.zeppelin.notebook.Paragraph; import org.apache.zeppelin.server.ZeppelinServer; import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.AfterClass; @@ -37,12 +36,12 @@ import org.junit.runners.MethodSorters; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; /** @@ -179,6 +178,43 @@ public void testCloneNote() throws IOException { ZeppelinServer.notebook.removeNote(clonedNoteId, anonymous); } + + @Test + public void testClearAllParagraphOutput() throws IOException { + // Create note and set result explicitly + Note note = ZeppelinServer.notebook.createNote(anonymous); + Paragraph p1 = note.addParagraph(); + InterpreterResult result = new InterpreterResult(InterpreterResult.Code.SUCCESS, InterpreterResult.Type.TEXT, "result"); + p1.setResult(result); + + Paragraph p2 = note.addParagraph(); + p2.setReturn(result, new Throwable()); + + // clear paragraph result + PostMethod post = httpPost("/notebook/" + note.getId() + "/clear", ""); + LOG.info("test clear paragraph output response\n" + post.getResponseBodyAsString()); + assertThat(post, isAllowed()); + post.releaseConnection(); + + // check if paragraph results are cleared + GetMethod get = httpGet("/notebook/" + note.getId() + "/paragraph/" + p1.getId()); + assertThat(get, isAllowed()); + Map resp1 = gson.fromJson(get.getResponseBodyAsString(), new TypeToken>() { + }.getType()); + Map resp1Body = (Map) resp1.get("body"); + assertNull(resp1Body.get("result")); + + get = httpGet("/notebook/" + note.getId() + "/paragraph/" + p2.getId()); + assertThat(get, isAllowed()); + Map resp2 = gson.fromJson(get.getResponseBodyAsString(), new TypeToken>() { + }.getType()); + Map resp2Body = (Map) resp2.get("body"); + assertNull(resp2Body.get("result")); + get.releaseConnection(); + + //cleanup + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); + } } From d66600c83968658d709c6b1e5eba5a24022344d6 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 27 Oct 2016 18:10:58 +0900 Subject: [PATCH 4/9] Add rest api endpoint for clear paragraph result to document --- docs/rest-api/rest-notebook.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/rest-api/rest-notebook.md b/docs/rest-api/rest-notebook.md index 1e49d1ed912..c7743ff9583 100644 --- a/docs/rest-api/rest-notebook.md +++ b/docs/rest-api/rest-notebook.md @@ -493,7 +493,7 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple Description - This ```POST``` method runs the paragraph synchronously by given note and paragraph id. This API can return SUCCESS or ERROR depending on the outcome of the paragraph execution + This ```POST``` method runs the paragraph synchronously by given note and paragraph id. This API can return SUCCESS or ERROR depending on the outcome of the paragraph execution @@ -972,3 +972,31 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple + +
+### Clear all paragraph result + + + + + + + + + + + + + + + + + + + + + + + +
DescriptionThis ```POST``` method clear all paragraph results from note of given id. +
URL```http://[zeppelin-server]:[zeppelin-port]/api/notebook/[noteId]/clear```
Success code200
Fail code 500
sample JSON response
{"status": "OK"}
\ No newline at end of file From dea3ef6979c4240882824df3b3083e98a5208921 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 27 Oct 2016 18:14:42 +0900 Subject: [PATCH 5/9] Remove unused import --- .../src/test/java/org/apache/zeppelin/notebook/NoteTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java index 352a17f48c2..ed42144bf7a 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java @@ -17,7 +17,6 @@ package org.apache.zeppelin.notebook; -import org.apache.zeppelin.helium.HeliumPackage; import org.apache.zeppelin.interpreter.Interpreter; import org.apache.zeppelin.interpreter.InterpreterFactory; import org.apache.zeppelin.interpreter.InterpreterResult; From 7eb352159a1acd786c4b94cff1a0b83be7f4dd68 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Fri, 28 Oct 2016 14:09:09 +0900 Subject: [PATCH 6/9] Give writer permission to clear output --- .../main/java/org/apache/zeppelin/socket/NotebookServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java index 1711a67611e..bed7fbc67c8 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java @@ -792,7 +792,7 @@ private void clearAllParagraphOutput(NotebookSocket conn, HashSet userAn } Note note = notebook.getNote(noteId); NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization(); - if (!notebookAuthorization.isOwner(noteId, userAndRoles)) { + if (!notebookAuthorization.isWriter(noteId, userAndRoles)) { permissionError(conn, "clear output", fromMessage.principal, userAndRoles, notebookAuthorization.getOwners(noteId)); return; From f349dbf24012d1c02f790fc643820a325374c329 Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Wed, 2 Nov 2016 16:07:54 +0900 Subject: [PATCH 7/9] Change post to put --- docs/rest-api/rest-notebook.md | 4 ++-- .../java/org/apache/zeppelin/rest/NotebookRestApi.java | 2 +- .../org/apache/zeppelin/rest/NotebookRestApiTest.java | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/rest-api/rest-notebook.md b/docs/rest-api/rest-notebook.md index c7743ff9583..acf0e6c0159 100644 --- a/docs/rest-api/rest-notebook.md +++ b/docs/rest-api/rest-notebook.md @@ -979,7 +979,7 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple Description - This ```POST``` method clear all paragraph results from note of given id. + This ```PUT``` method clear all paragraph results from note of given id. @@ -999,4 +999,4 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple
{"status": "OK"}
- \ No newline at end of file + 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 277870ae42e..955b7192e08 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 @@ -467,7 +467,7 @@ public Response deleteParagraph(@PathParam("noteId") String noteId, * @param noteId ID of Note * @return JSON with status.ok */ - @POST + @PUT @Path("{noteId}/clear") @ZeppelinApi public Response clearAllParagraphOutput(@PathParam("noteId") String noteId) diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java index bcebbb8be7c..61a97e9c0fb 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java @@ -191,10 +191,10 @@ public void testClearAllParagraphOutput() throws IOException { p2.setReturn(result, new Throwable()); // clear paragraph result - PostMethod post = httpPost("/notebook/" + note.getId() + "/clear", ""); - LOG.info("test clear paragraph output response\n" + post.getResponseBodyAsString()); - assertThat(post, isAllowed()); - post.releaseConnection(); + PutMethod put = httpPut("/notebook/" + note.getId() + "/clear", ""); + LOG.info("test clear paragraph output response\n" + put.getResponseBodyAsString()); + assertThat(put, isAllowed()); + put.releaseConnection(); // check if paragraph results are cleared GetMethod get = httpGet("/notebook/" + note.getId() + "/paragraph/" + p1.getId()); From 2ee452ec0bc05181f6b895a194805f3688601a8b Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 3 Nov 2016 15:45:41 +0900 Subject: [PATCH 8/9] Add auth check before clearing all paragraph --- .../org/apache/zeppelin/rest/NotebookRestApi.java | 11 ++++------- .../org/apache/zeppelin/rest/NotebookRestApiTest.java | 1 - 2 files changed, 4 insertions(+), 8 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 1515b2d85a8..3e953a03bdf 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 @@ -528,14 +528,11 @@ public Response deleteParagraph(@PathParam("noteId") String noteId, public Response clearAllParagraphOutput(@PathParam("noteId") String noteId) throws IOException { LOG.info("clear all paragraph output of note {}", noteId); + checkIfUserCanWrite(noteId, "Insufficient privileges you cannot clear this note"); - if (!noteId.isEmpty()) { - Note note = notebook.getNote(noteId); - if (note == null) { - return new JsonResponse(Status.NOT_FOUND, "note not found.").build(); - } - note.clearAllParagraphOutput(); - } + Note note = notebook.getNote(noteId); + checkIfNoteIsNotNull(note); + note.clearAllParagraphOutput(); return new JsonResponse(Status.OK, "").build(); } diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java index 61a97e9c0fb..15b69030ce1 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java @@ -36,7 +36,6 @@ import org.junit.runners.MethodSorters; import java.io.IOException; -import java.util.List; import java.util.Map; import java.util.Set; From 1393ee960fd5433af6839e6eb352295982722ebb Mon Sep 17 00:00:00 2001 From: Mina Lee Date: Thu, 3 Nov 2016 23:49:54 +0900 Subject: [PATCH 9/9] Rename class name from UnauthorizedException to ForbiddenException Update clear output rest api doc response code --- docs/rest-api/rest-notebook.md | 12 ++++++++++-- .../apache/zeppelin/rest/NotebookRestApi.java | 8 ++++---- ...Exception.java => ForbiddenException.java} | 19 ++++++++++--------- .../zeppelin/rest/AbstractTestRestApi.java | 2 +- .../rest/NotebookSecurityRestApiTest.java | 8 ++++---- 5 files changed, 29 insertions(+), 20 deletions(-) rename zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/{UnauthorizedException.java => ForbiddenException.java} (71%) diff --git a/docs/rest-api/rest-notebook.md b/docs/rest-api/rest-notebook.md index acf0e6c0159..46f2cd1dd69 100644 --- a/docs/rest-api/rest-notebook.md +++ b/docs/rest-api/rest-notebook.md @@ -991,8 +991,16 @@ If you work with Apache Zeppelin and find a need for an additional REST API, ple 200 - Fail code - 500 + Forbidden code + 401 + + + Not Found code + 404 + + + Fail code + 500 sample JSON response 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 3e953a03bdf..52f7d116150 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 @@ -43,7 +43,7 @@ import org.apache.zeppelin.notebook.NotebookAuthorization; import org.apache.zeppelin.notebook.Paragraph; import org.apache.zeppelin.rest.exception.NotFoundException; -import org.apache.zeppelin.rest.exception.UnauthorizedException; +import org.apache.zeppelin.rest.exception.ForbiddenException; import org.apache.zeppelin.rest.message.CronRequest; import org.apache.zeppelin.rest.message.NewNoteRequest; import org.apache.zeppelin.rest.message.NewParagraphRequest; @@ -124,7 +124,7 @@ private void checkIfUserIsOwner(String noteId, String errorMsg) { userAndRoles.add(SecurityUtils.getPrincipal()); userAndRoles.addAll(SecurityUtils.getRoles()); if (!notebookAuthorization.isOwner(userAndRoles, noteId)) { - throw new UnauthorizedException(errorMsg); + throw new ForbiddenException(errorMsg); } } @@ -136,7 +136,7 @@ private void checkIfUserCanWrite(String noteId, String errorMsg) { userAndRoles.add(SecurityUtils.getPrincipal()); userAndRoles.addAll(SecurityUtils.getRoles()); if (!notebookAuthorization.hasWriteAuthorization(userAndRoles, noteId)) { - throw new UnauthorizedException(errorMsg); + throw new ForbiddenException(errorMsg); } } @@ -148,7 +148,7 @@ private void checkIfUserCanRead(String noteId, String errorMsg) { userAndRoles.add(SecurityUtils.getPrincipal()); userAndRoles.addAll(SecurityUtils.getRoles()); if (!notebookAuthorization.hasReadAuthorization(userAndRoles, noteId)) { - throw new UnauthorizedException(errorMsg); + throw new ForbiddenException(errorMsg); } } diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/UnauthorizedException.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/ForbiddenException.java similarity index 71% rename from zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/UnauthorizedException.java rename to zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/ForbiddenException.java index 7b968abaddc..04deb4227b5 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/UnauthorizedException.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/exception/ForbiddenException.java @@ -17,6 +17,7 @@ package org.apache.zeppelin.rest.exception; import static javax.ws.rs.core.Response.Status.FORBIDDEN; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -27,24 +28,24 @@ * UnauthorizedException handler for WebApplicationException. * */ -public class UnauthorizedException extends WebApplicationException { +public class ForbiddenException extends WebApplicationException { private static final long serialVersionUID = 4394749068760407567L; - private static final String UNAUTHORIZED_MSG = "Authorization required"; + private static final String FORBIDDEN_MSG = "Not allowed to access"; - public UnauthorizedException() { - super(unauthorizedJson(UNAUTHORIZED_MSG)); + public ForbiddenException() { + super(forbiddenJson(FORBIDDEN_MSG)); } - private static Response unauthorizedJson(String message) { + private static Response forbiddenJson(String message) { return ExceptionUtils.jsonResponseContent(FORBIDDEN, message); } - public UnauthorizedException(Throwable cause, String message) { - super(cause, unauthorizedJson(message)); + public ForbiddenException(Throwable cause, String message) { + super(cause, forbiddenJson(message)); } - public UnauthorizedException(String message) { - super(unauthorizedJson(message)); + public ForbiddenException(String message) { + super(forbiddenJson(message)); } } diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/AbstractTestRestApi.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/AbstractTestRestApi.java index 6d103372987..2ff8d40b3de 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/AbstractTestRestApi.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/AbstractTestRestApi.java @@ -539,7 +539,7 @@ public static void ps() { /** Status code matcher */ - protected Matcher isForbiden() { return responsesWith(403); } + protected Matcher isForbidden() { return responsesWith(403); } protected Matcher isAllowed() { return responsesWith(200); diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookSecurityRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookSecurityRestApiTest.java index 3c5978fd4d5..0c714fd4251 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookSecurityRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookSecurityRestApiTest.java @@ -82,10 +82,10 @@ public void testThatOtherUserCannotAccessNoteIfPermissionSet() throws IOExceptio //set permission String payload = "{ \"owners\": [\"admin\"], \"readers\": [\"user2\"], \"writers\": [\"user2\"] }"; PutMethod put = httpPut("/notebook/" + noteId + "/permissions", payload , "admin", "password1"); - assertThat("test set note premission method:", put, isAllowed()); + assertThat("test set note permission method:", put, isAllowed()); put.releaseConnection(); - userTryGetNote(noteId, "user1", "password2", isForbiden()); + userTryGetNote(noteId, "user1", "password2", isForbidden()); userTryGetNote(noteId, "user2", "password3", isAllowed()); @@ -99,10 +99,10 @@ public void testThatWriterCannotRemoveNote() throws IOException { //set permission String payload = "{ \"owners\": [\"admin\", \"user1\"], \"readers\": [\"user2\"], \"writers\": [\"user2\"] }"; PutMethod put = httpPut("/notebook/" + noteId + "/permissions", payload , "admin", "password1"); - assertThat("test set note premission method:", put, isAllowed()); + assertThat("test set note permission method:", put, isAllowed()); put.releaseConnection(); - userTryRemoveNote(noteId, "user2", "password3", isForbiden()); + userTryRemoveNote(noteId, "user2", "password3", isForbidden()); userTryRemoveNote(noteId, "user1", "password2", isAllowed()); Note deletedNote = ZeppelinServer.notebook.getNote(noteId);