Repository: zeppelin Updated Branches: refs/heads/master cf3127561 -> 2e3043e77
[ZEPPELIN-3580] Adds rename note method to rest api ### What is this PR for? Adds rename note method to rest api ### What type of PR is it? Improvement ### What is the Jira issue? issue on Jira: https://issues.apache.org/jira/browse/ZEPPELIN-3580 ### Questions: - Does the licenses files need update? No - Is there breaking changes for older versions? No - Does this needs documentation? No Author: oxygen311 <[email protected]> Closes #3049 from oxygen311/ZEPPELIN-3585 and squashes the following commits: 62d081c9d [oxygen311] Merge branch 'ZEPPELIN-3585' of https://github.com/TinkoffCreditSystems/zeppelin into ZEPPELIN-3585 57f6d2905 [oxygen311] Fix excess symbol bug ca1b0b397 [oxygen311] Fix codestyle bbbe26134 [oxygen311] Merge branch 'master' of https://github.com/apache/zeppelin into ZEPPELIN-3585 4df7c6dba [oxygen311] Add rename method to rest api ad880ed31 [oxygen311] Add rename method to rest api Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/2e3043e7 Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/2e3043e7 Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/2e3043e7 Branch: refs/heads/master Commit: 2e3043e774769592841db54e6952049e6936749c Parents: cf31275 Author: oxygen311 <[email protected]> Authored: Thu Jul 19 12:23:16 2018 +0300 Committer: Jongyoul Lee <[email protected]> Committed: Fri Jul 20 08:05:49 2018 +0900 ---------------------------------------------------------------------- docs/usage/rest_api/notebook.md | 36 ++++++ .../apache/zeppelin/rest/NotebookRestApi.java | 111 +++++++++++++------ .../rest/message/RenameNoteRequest.java | 35 ++++++ .../zeppelin/rest/NotebookRestApiTest.java | 18 +++ 4 files changed, 166 insertions(+), 34 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/2e3043e7/docs/usage/rest_api/notebook.md ---------------------------------------------------------------------- diff --git a/docs/usage/rest_api/notebook.md b/docs/usage/rest_api/notebook.md index 9879ad9..7a45d19 100644 --- a/docs/usage/rest_api/notebook.md +++ b/docs/usage/rest_api/notebook.md @@ -351,6 +351,42 @@ Notebooks REST API supports the following operations: List, Create, Get, Delete, </tr> </table> +<br/> +### Rename a note + <table class="table-configuration"> + <col width="200"> + <tr> + <td>Description</td> + <td>This ```PUT``` method renames a note by the given id using the given name. + </td> + </tr> + <tr> + <td>URL</td> + <td>```http://[zeppelin-server]:[zeppelin-port]/api/notebook/[noteId]/rename```</td> + </tr> + <tr> + <td>Success code</td> + <td>200</td> + </tr> + <tr> + <td>Bad Request code</td> + <td>400</td> + </tr> + <tr> + <td> Fail code</td> + <td> 500 </td> + </tr> + <tr> + <td> sample JSON input </td> + <td><pre>{"name": "new name of a note"}</pre></td> + </tr> + <tr> + <td> sample JSON response </td> + <td><pre>{"status":"OK"}</pre></td> + </tr> + </table> + + <br /> ### Export a note <table class="table-configuration"> http://git-wip-us.apache.org/repos/asf/zeppelin/blob/2e3043e7/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java ---------------------------------------------------------------------- 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 1a5894c..d032c3d 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 @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.zeppelin.rest; import com.google.common.collect.Sets; @@ -21,6 +22,12 @@ import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import org.apache.commons.lang3.StringUtils; +import org.apache.zeppelin.rest.message.CronRequest; +import org.apache.zeppelin.rest.message.NewNoteRequest; +import org.apache.zeppelin.rest.message.NewParagraphRequest; +import org.apache.zeppelin.rest.message.RenameNoteRequest; +import org.apache.zeppelin.rest.message.RunParagraphWithParametersRequest; +import org.apache.zeppelin.rest.message.UpdateParagraphRequest; import org.quartz.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -115,7 +122,7 @@ public class NotebookRestApi { } private String getBlockNotAuthenticatedUserErrorMsg() { - return "Only authenticated user can set the permission."; + return "Only authenticated user can set the permission."; } /* @@ -209,7 +216,7 @@ public class NotebookRestApi { @Path("{noteId}/permissions") @ZeppelinApi public Response putNotePermissions(@PathParam("noteId") String noteId, String req) - throws IOException { + throws IOException { String principal = SecurityUtils.getPrincipal(); HashSet<String> roles = SecurityUtils.getRoles(); HashSet<String> userAndRoles = new HashSet<>(); @@ -221,11 +228,12 @@ public class NotebookRestApi { ownerPermissionError(userAndRoles, notebookAuthorization.getOwners(noteId))); HashMap<String, HashSet<String>> permMap = - gson.fromJson(req, new TypeToken<HashMap<String, HashSet<String>>>() {}.getType()); + gson.fromJson(req, new TypeToken<HashMap<String, HashSet<String>>>() { + }.getType()); Note note = notebook.getNote(noteId); LOG.info("Set permissions {} {} {} {} {} {}", noteId, principal, permMap.get("owners"), - permMap.get("readers"), permMap.get("runners"), permMap.get("writers")); + permMap.get("readers"), permMap.get("runners"), permMap.get("writers")); HashSet<String> readers = permMap.get("readers"); HashSet<String> runners = permMap.get("runners"); @@ -264,8 +272,8 @@ public class NotebookRestApi { notebookAuthorization.setWriters(noteId, writers); notebookAuthorization.setOwners(noteId, owners); LOG.debug("After set permissions {} {} {} {}", notebookAuthorization.getOwners(noteId), - notebookAuthorization.getReaders(noteId), notebookAuthorization.getRunners(noteId), - notebookAuthorization.getWriters(noteId)); + notebookAuthorization.getReaders(noteId), notebookAuthorization.getRunners(noteId), + notebookAuthorization.getWriters(noteId)); AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal()); note.persist(subject); notebookServer.broadcastNote(note); @@ -437,7 +445,7 @@ public class NotebookRestApi { @Path("{noteId}") @ZeppelinApi public Response cloneNote(@PathParam("noteId") String noteId, String message) - throws IOException, CloneNotSupportedException, IllegalArgumentException { + throws IOException, CloneNotSupportedException, IllegalArgumentException { LOG.info("clone note by JSON {}", message); checkIfUserCanWrite(noteId, "Insufficient privileges you cannot clone this note"); NewNoteRequest request = NewNoteRequest.fromJson(message); @@ -453,6 +461,38 @@ public class NotebookRestApi { } /** + * Rename note REST API + * + * @param message - JSON containing new name + * @return JSON with status.OK + * @throws IOException + */ + @PUT + @Path("{noteId}/rename") + @ZeppelinApi + public Response renameNote(@PathParam("noteId") String noteId, + String message) throws IOException { + LOG.info("rename note by JSON {}", message); + RenameNoteRequest request = gson.fromJson(message, RenameNoteRequest.class); + AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal()); + + checkIfUserCanWrite(noteId, "Insufficient privileges you cannot rename this note"); + Note note = notebook.getNote(noteId); + checkIfNoteIsNotNull(note); + + String newName = request.getName(); + if (newName.isEmpty()) { + LOG.warn("Trying to rename notebook {} with empty name parameter", noteId); + throw new BadRequestException("name can not be empty"); + } + note.setName(newName); + + notebookServer.broadcastNote(note); + notebookServer.broadcastNoteList(subject, SecurityUtils.getRoles()); + return new JsonResponse(Status.OK, "").build(); + } + + /** * Insert paragraph REST API. * * @param message - JSON containing paragraph's information @@ -497,7 +537,7 @@ public class NotebookRestApi { @Path("{noteId}/paragraph/{paragraphId}") @ZeppelinApi public Response getParagraph(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId) throws IOException { + @PathParam("paragraphId") String paragraphId) throws IOException { LOG.info("get paragraph {} {}", noteId, paragraphId); Note note = notebook.getNote(noteId); @@ -520,7 +560,8 @@ public class NotebookRestApi { @Path("{noteId}/paragraph/{paragraphId}") @ZeppelinApi public Response updateParagraph(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId, String message) throws IOException { + @PathParam("paragraphId") String paragraphId, + String message) throws IOException { String user = SecurityUtils.getPrincipal(); LOG.info("{} will update paragraph {} {}", user, noteId, paragraphId); @@ -547,7 +588,8 @@ public class NotebookRestApi { @Path("{noteId}/paragraph/{paragraphId}/config") @ZeppelinApi public Response updateParagraphConfig(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId, String message) throws IOException { + @PathParam("paragraphId") String paragraphId, + String message) throws IOException { String user = SecurityUtils.getPrincipal(); LOG.info("{} will update paragraph config {} {}", user, noteId, paragraphId); @@ -575,8 +617,9 @@ public class NotebookRestApi { @Path("{noteId}/paragraph/{paragraphId}/move/{newIndex}") @ZeppelinApi public Response moveParagraph(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId, @PathParam("newIndex") String newIndex) - throws IOException { + @PathParam("paragraphId") String paragraphId, + @PathParam("newIndex") String newIndex) + throws IOException { LOG.info("move paragraph {} {} {}", noteId, paragraphId, newIndex); Note note = notebook.getNote(noteId); @@ -610,7 +653,7 @@ public class NotebookRestApi { @Path("{noteId}/paragraph/{paragraphId}") @ZeppelinApi public Response deleteParagraph(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId) throws IOException { + @PathParam("paragraphId") String paragraphId) throws IOException { LOG.info("delete paragraph {} {}", noteId, paragraphId); Note note = notebook.getNote(noteId); @@ -639,7 +682,7 @@ public class NotebookRestApi { @Path("{noteId}/clear") @ZeppelinApi public Response clearAllParagraphOutput(@PathParam("noteId") String noteId) - throws IOException { + throws IOException { LOG.info("clear all paragraph output of note {}", noteId); checkIfUserCanWrite(noteId, "Insufficient privileges you cannot clear this note"); @@ -693,7 +736,7 @@ public class NotebookRestApi { @Path("job/{noteId}") @ZeppelinApi public Response stopNoteJobs(@PathParam("noteId") String noteId) - throws IOException, IllegalArgumentException { + throws IOException, IllegalArgumentException { LOG.info("stop note jobs {} ", noteId); Note note = notebook.getNote(noteId); checkIfNoteIsNotNull(note); @@ -719,7 +762,7 @@ public class NotebookRestApi { @Path("job/{noteId}") @ZeppelinApi public Response getNoteJobStatus(@PathParam("noteId") String noteId) - throws IOException, IllegalArgumentException { + throws IOException, IllegalArgumentException { LOG.info("get note job status."); Note note = notebook.getNote(noteId); checkIfNoteIsNotNull(note); @@ -731,7 +774,7 @@ public class NotebookRestApi { /** * Get note paragraph job status REST API. * - * @param noteId ID of Note + * @param noteId ID of Note * @param paragraphId ID of Paragraph * @return JSON with status.OK * @throws IOException @@ -741,8 +784,8 @@ public class NotebookRestApi { @Path("job/{noteId}/{paragraphId}") @ZeppelinApi public Response getNoteParagraphJobStatus(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId) - throws IOException, IllegalArgumentException { + @PathParam("paragraphId") String paragraphId) + throws IOException, IllegalArgumentException { LOG.info("get note paragraph job status."); Note note = notebook.getNote(noteId); checkIfNoteIsNotNull(note); @@ -752,7 +795,7 @@ public class NotebookRestApi { checkIfParagraphIsNotNull(paragraph); return new JsonResponse<>(Status.OK, null, note.generateSingleParagraphInfo(paragraphId)). - build(); + build(); } /** @@ -768,8 +811,8 @@ public class NotebookRestApi { @Path("job/{noteId}/{paragraphId}") @ZeppelinApi public Response runParagraph(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId, String message) - throws IOException, IllegalArgumentException { + @PathParam("paragraphId") String paragraphId, String message) + throws IOException, IllegalArgumentException { LOG.info("run paragraph job asynchronously {} {} {}", noteId, paragraphId, message); Note note = notebook.getNote(noteId); @@ -793,11 +836,10 @@ public class NotebookRestApi { /** * Run synchronously a paragraph REST API. * - * @param noteId - noteId + * @param noteId - noteId * @param paragraphId - paragraphId - * @param message - JSON with params if user wants to update dynamic form's value - * null, empty string, empty json if user doesn't want to update - * + * @param message - JSON with params if user wants to update dynamic form's value + * null, empty string, empty json if user doesn't want to update * @return JSON with status.OK * @throws IOException * @throws IllegalArgumentException @@ -806,8 +848,9 @@ public class NotebookRestApi { @Path("run/{noteId}/{paragraphId}") @ZeppelinApi public Response runParagraphSynchronously(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId, String message) - throws IOException, IllegalArgumentException { + @PathParam("paragraphId") String paragraphId, + String message) + throws IOException, IllegalArgumentException { LOG.info("run paragraph synchronously {} {} {}", noteId, paragraphId, message); Note note = notebook.getNote(noteId); @@ -840,7 +883,7 @@ public class NotebookRestApi { /** * Stop(delete) paragraph job REST API. * - * @param noteId ID of Note + * @param noteId ID of Note * @param paragraphId ID of Paragraph * @return JSON with status.OK * @throws IOException @@ -850,8 +893,8 @@ public class NotebookRestApi { @Path("job/{noteId}/{paragraphId}") @ZeppelinApi public Response stopParagraph(@PathParam("noteId") String noteId, - @PathParam("paragraphId") String paragraphId) - throws IOException, IllegalArgumentException { + @PathParam("paragraphId") String paragraphId) + throws IOException, IllegalArgumentException { LOG.info("stop paragraph job {} ", noteId); Note note = notebook.getNote(noteId); checkIfNoteIsNotNull(note); @@ -874,7 +917,7 @@ public class NotebookRestApi { @Path("cron/{noteId}") @ZeppelinApi public Response registerCronJob(@PathParam("noteId") String noteId, String message) - throws IOException, IllegalArgumentException { + throws IOException, IllegalArgumentException { LOG.info("Register cron job note={} request cron msg={}", noteId, message); CronRequest request = CronRequest.fromJson(message); @@ -985,7 +1028,7 @@ public class NotebookRestApi { @Path("jobmanager/{lastUpdateUnixtime}/") @ZeppelinApi public Response getUpdatedJobListforNote(@PathParam("lastUpdateUnixtime") long lastUpdateUnixTime) - throws IOException, IllegalArgumentException { + throws IOException, IllegalArgumentException { LOG.info("Get updated note jobs lastUpdateTime {}", lastUpdateUnixTime); List<Map<String, Object>> noteJobs; @@ -1019,7 +1062,7 @@ public class NotebookRestApi { if (!notebookAuthorization.isOwner(noteId, userAndRoles) && !notebookAuthorization.isReader(noteId, userAndRoles) && !notebookAuthorization.isWriter(noteId, userAndRoles) && - !notebookAuthorization.isRunner(noteId, userAndRoles)) { + !notebookAuthorization.isRunner(noteId, userAndRoles)) { notesFound.remove(i); i--; } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/2e3043e7/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RenameNoteRequest.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RenameNoteRequest.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RenameNoteRequest.java new file mode 100644 index 0000000..72ee2a6 --- /dev/null +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/RenameNoteRequest.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.zeppelin.rest.message; + +/** + * RenameNoteRequest rest api request message + * + */ + +public class RenameNoteRequest { + String name; + + public RenameNoteRequest (){ + + } + + public String getName() { + return name; + } +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/2e3043e7/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java ---------------------------------------------------------------------- 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 f131ed1..66273c8 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 @@ -208,6 +208,24 @@ public class NotebookRestApiTest extends AbstractTestRestApi { } @Test + public void testRenameNote() throws IOException { + Note note = ZeppelinServer.notebook.createNote(anonymous); + String noteId = note.getId(); + + final String newName = "testName"; + String jsonRequest = "{\"name\": " + newName + "}"; + + PutMethod put = httpPut("/notebook/" + noteId + "/rename/", jsonRequest); + assertThat("test testRenameNote:", put, isAllowed()); + put.releaseConnection(); + + assertEquals(note.getName(), newName); + + //cleanup + ZeppelinServer.notebook.removeNote(noteId, anonymous); + } + + @Test public void testUpdateParagraphConfig() throws IOException { Note note = ZeppelinServer.notebook.createNote(anonymous); String noteId = note.getId();
