diff --git a/conf/zeppelin-env.sh.template b/conf/zeppelin-env.sh.template index b0b1a5b6e50..3a24b217282 100644 --- a/conf/zeppelin-env.sh.template +++ b/conf/zeppelin-env.sh.template @@ -33,7 +33,7 @@ # export ZEPPELIN_NOTEBOOK_S3_USER # User in bucket where notebook saved. For example bucket/user/notebook/2A94M5J1Z/note.json # export ZEPPELIN_IDENT_STRING # A string representing this instance of zeppelin. $USER by default. # export ZEPPELIN_NICENESS # The scheduling priority for daemons. Defaults to 0. - +# export ZEPPELIN_READ_ONLY # Read-only mode. Disabled editing or creating notebook when this value set to "true". default "false" #### Spark interpreter configuration #### diff --git a/conf/zeppelin-site.xml.template b/conf/zeppelin-site.xml.template index 74fa2e76053..9e3b787d2c6 100755 --- a/conf/zeppelin-site.xml.template +++ b/conf/zeppelin-site.xml.template @@ -43,6 +43,12 @@ Location of jetty temporary directory + + zeppelin.server.readonly + false + Read-only mode. Disabled editing or creating notebook when this value set to "true". default "false" + + zeppelin.notebook.dir notebook diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java index 54015438e64..a816efab2d9 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java @@ -33,6 +33,8 @@ import javax.ws.rs.core.Response.Status; import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.zeppelin.conf.ZeppelinConfiguration; +import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars; import org.apache.zeppelin.interpreter.*; import org.apache.zeppelin.interpreter.Interpreter.RegisteredInterpreter; import org.apache.zeppelin.rest.message.NewInterpreterSettingRequest; @@ -53,6 +55,7 @@ public class InterpreterRestApi { Logger logger = LoggerFactory.getLogger(InterpreterRestApi.class); private InterpreterFactory interpreterFactory; + private ZeppelinConfiguration conf; Gson gson = new Gson(); @@ -60,8 +63,9 @@ public InterpreterRestApi() { } - public InterpreterRestApi(InterpreterFactory interpreterFactory) { + public InterpreterRestApi(InterpreterFactory interpreterFactory, ZeppelinConfiguration conf) { this.interpreterFactory = interpreterFactory; + this.conf = conf; } /** @@ -86,6 +90,7 @@ public Response listSettings() { @POST @Path("setting") public Response newSettings(String message) throws InterpreterException, IOException { + NewInterpreterSettingRequest request = gson.fromJson(message, NewInterpreterSettingRequest.class); Properties p = new Properties(); @@ -103,6 +108,9 @@ public Response newSettings(String message) throws InterpreterException, IOExcep public Response updateSetting(String message, @PathParam("settingId") String settingId) { logger.info("Update interpreterSetting {}", settingId); + if (conf.getBoolean(ConfVars.ZEPPELIN_READ_ONLY)) { + return new JsonResponse(Status.FORBIDDEN).build(); + } try { UpdateInterpreterSettingRequest p = gson.fromJson(message, UpdateInterpreterSettingRequest.class); @@ -130,6 +138,9 @@ public Response updateSetting(String message, @PathParam("settingId") String set @Path("setting/{settingId}") public Response removeSetting(@PathParam("settingId") String settingId) throws IOException { logger.info("Remove interpreterSetting {}", settingId); + if (conf.getBoolean(ConfVars.ZEPPELIN_READ_ONLY)) { + return new JsonResponse(Status.FORBIDDEN).build(); + } interpreterFactory.remove(settingId); return new JsonResponse(Status.OK).build(); } @@ -141,6 +152,9 @@ public Response removeSetting(@PathParam("settingId") String settingId) throws I @Path("setting/restart/{settingId}") public Response restartSetting(@PathParam("settingId") String settingId) { logger.info("Restart interpreterSetting {}", settingId); + if (conf.getBoolean(ConfVars.ZEPPELIN_READ_ONLY)) { + return new JsonResponse(Status.FORBIDDEN).build(); + } try { interpreterFactory.restart(settingId); } catch (InterpreterException e) { diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java index fd115ee18cb..449e5b5bfbf 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java @@ -38,8 +38,8 @@ import org.apache.zeppelin.rest.NotebookRestApi; import org.apache.zeppelin.rest.ZeppelinRestApi; import org.apache.zeppelin.scheduler.SchedulerFactory; -import org.apache.zeppelin.search.SearchService; import org.apache.zeppelin.search.LuceneSearch; +import org.apache.zeppelin.search.SearchService; import org.apache.zeppelin.socket.NotebookServer; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.Handler; @@ -165,7 +165,7 @@ private static Server setupJettyServer(ZeppelinConfiguration conf) { } private static ServletContextHandler setupNotebookServer(ZeppelinConfiguration conf) { - notebookWsServer = new NotebookServer(); + notebookWsServer = new NotebookServer(conf); final ServletHolder servletHolder = new ServletHolder(notebookWsServer); servletHolder.setInitParameter("maxTextMessageSize", "1024000"); @@ -270,7 +270,7 @@ public Set getSingletons() { NotebookRestApi notebookApi = new NotebookRestApi(notebook, notebookWsServer, notebookIndex); singletons.add(notebookApi); - InterpreterRestApi interpreterApi = new InterpreterRestApi(replFactory); + InterpreterRestApi interpreterApi = new InterpreterRestApi(replFactory, notebook.getConf()); singletons.add(interpreterApi); return singletons; diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java index dc657bdda06..83d42273d15 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java @@ -43,10 +43,10 @@ public static enum OP { // @param id paragraph id // @param progress percentage progress - NEW_NOTE, // [c-s] create new notebook - DEL_NOTE, // [c-s] delete notebook + NEW_NOTE(true), // [c-s] create new notebook + DEL_NOTE(true), // [c-s] delete notebook // @param id note id - CLONE_NOTE, // [c-s] clone new notebook + CLONE_NOTE(true), // [c-s] clone new notebook // @param id id of note to clone // @param name name fpor the cloned note IMPORT_NOTE, // [c-s] import notebook @@ -69,11 +69,11 @@ public static enum OP { CANCEL_PARAGRAPH, // [c-s] cancel paragraph run // @param id paragraph id - MOVE_PARAGRAPH, // [c-s] move paragraph order + MOVE_PARAGRAPH(true), // [c-s] move paragraph order // @param id paragraph id // @param index index the paragraph want to go - INSERT_PARAGRAPH, // [c-s] create new paragraph below current paragraph + INSERT_PARAGRAPH(true), // [c-s] create new paragraph below current paragraph // @param target index COMPLETION, // [c-s] ask completion candidates @@ -90,14 +90,30 @@ public static enum OP { NOTES_INFO, // [s-c] list of note infos // @param notes serialized List object - PARAGRAPH_REMOVE, + PARAGRAPH_REMOVE(true), PARAGRAPH_CLEAR_OUTPUT, PING, ANGULAR_OBJECT_UPDATE, // [s-c] add/update angular object ANGULAR_OBJECT_REMOVE, // [s-c] add angular object del - ANGULAR_OBJECT_UPDATED // [c-s] angular object value updated + ANGULAR_OBJECT_UPDATED, // [c-s] angular object value updated + + GET_SYSTEM_CONF; // [c-s] client gets system configuration + + private final boolean modifyOp; + + private OP() { + this(false); + } + + private OP(boolean modifyOp) { + this.modifyOp = modifyOp; + } + + public boolean isModifyOp() { + return modifyOp; + } } public OP op; 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 554f68cf073..a9a47c5b4f7 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 @@ -61,6 +61,13 @@ public class NotebookServer extends WebSocketServlet implements Gson gson = new Gson(); final Map> noteSocketMap = new HashMap<>(); final Queue connectedSockets = new ConcurrentLinkedQueue<>(); + final boolean readOnlyMode; + final ZeppelinConfiguration conf; + + public NotebookServer(ZeppelinConfiguration conf) { + this.readOnlyMode = conf.getBoolean(ConfVars.ZEPPELIN_READ_ONLY); + this.conf = conf; + } private Notebook notebook() { return ZeppelinServer.notebook; @@ -96,6 +103,11 @@ public void onMessage(NotebookSocket conn, String msg) { try { Message messagereceived = deserializeMessage(msg); LOG.debug("RECEIVE << " + messagereceived.op); + if (readOnlyMode && messagereceived.op.isModifyOp()) { + LOG.warn("This server is readonly mode. but " + messagereceived.op + + " is modify op. This op will be ignored."); + return; + } /** Lets be elegant here */ switch (messagereceived.op) { case LIST_NOTES: @@ -151,6 +163,9 @@ public void onMessage(NotebookSocket conn, String msg) { case ANGULAR_OBJECT_UPDATED: angularObjectUpdated(conn, notebook, messagereceived); break; + case GET_SYSTEM_CONF: + sendSystemConf(conn, notebook, messagereceived); + break; default: broadcastNoteList(); break; @@ -446,8 +461,10 @@ private void updateParagraph(NotebookSocket conn, Notebook notebook, Paragraph p = note.getParagraph(paragraphId); p.settings.setParams(params); p.setConfig(config); - p.setTitle((String) fromMessage.get("title")); - p.setText((String) fromMessage.get("paragraph")); + if (!conf.getBoolean(ConfVars.ZEPPELIN_READ_ONLY)) { + p.setTitle((String) fromMessage.get("title")); + p.setText((String) fromMessage.get("paragraph")); + } note.persist(); broadcast(note.id(), new Message(OP.PARAGRAPH).put("paragraph", p)); } @@ -642,6 +659,14 @@ private void angularObjectUpdated(NotebookSocket conn, Notebook notebook, } } + private void sendSystemConf(NotebookSocket conn, Notebook notebook, + Message fromMessage) throws IOException { + Map confProperty = new HashMap(); + confProperty.put("readonly", + conf.getString(ConfVars.ZEPPELIN_READ_ONLY)); + conn.send(serializeMessage(new Message(OP.GET_SYSTEM_CONF).put("conf", confProperty))); + } + private void moveParagraph(NotebookSocket conn, Notebook notebook, Message fromMessage) throws IOException { final String paragraphId = (String) fromMessage.get("id"); @@ -689,8 +714,12 @@ private void runParagraph(NotebookSocket conn, Notebook notebook, final Note note = notebook.getNote(getOpenNoteId(conn)); Paragraph p = note.getParagraph(paragraphId); String text = (String) fromMessage.get("paragraph"); - p.setText(text); - p.setTitle((String) fromMessage.get("title")); + + if (!conf.getBoolean(ConfVars.ZEPPELIN_READ_ONLY)) { + p.setText(text); + p.setTitle((String) fromMessage.get("title")); + } + Map params = (Map) fromMessage .get("params"); p.settings.setParams(params); diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java index 67d12b7edf2..3f7d0eea829 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java @@ -19,10 +19,8 @@ */ package org.apache.zeppelin.socket; -import static org.junit.Assert.*; - -import java.io.IOException; - +import com.google.gson.Gson; +import org.apache.zeppelin.conf.ZeppelinConfiguration; import org.apache.zeppelin.interpreter.InterpreterGroup; import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.notebook.Note; @@ -34,14 +32,13 @@ import org.junit.BeforeClass; import org.junit.Test; -import com.google.gson.Gson; - -import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.List; -import javax.servlet.http.HttpServletRequest; - +import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -70,7 +67,7 @@ public static void destroy() throws Exception { @Test public void checkOrigin() throws UnknownHostException { - NotebookServer server = new NotebookServer(); + NotebookServer server = new NotebookServer(ZeppelinConfiguration.create()); String origin = "http://" + InetAddress.getLocalHost().getHostName() + ":8080"; assertTrue("Origin " + origin + " is not allowed. Please check your hostname.", @@ -79,7 +76,7 @@ public void checkOrigin() throws UnknownHostException { @Test public void checkInvalidOrigin(){ - NotebookServer server = new NotebookServer(); + NotebookServer server = new NotebookServer(ZeppelinConfiguration.create()); assertFalse(server.checkOrigin(new TestHttpServletRequest(), "http://evillocalhost:8080")); } diff --git a/zeppelin-web/.jshintrc b/zeppelin-web/.jshintrc index d15bbb95e58..e0a8b0e6939 100644 --- a/zeppelin-web/.jshintrc +++ b/zeppelin-web/.jshintrc @@ -31,6 +31,7 @@ "nv": false, "ace": false, "d3": false, - "BootstrapDialog": false + "BootstrapDialog": false, + "$": false } } diff --git a/zeppelin-web/src/app/app.controller.js b/zeppelin-web/src/app/app.controller.js index 2c302b542d9..5004d5c5d99 100644 --- a/zeppelin-web/src/app/app.controller.js +++ b/zeppelin-web/src/app/app.controller.js @@ -13,12 +13,13 @@ */ 'use strict'; -angular.module('zeppelinWebApp').controller('MainCtrl', function($scope, $rootScope, $window) { +angular.module('zeppelinWebApp').controller('MainCtrl', function($scope, $rootScope, websocketMsgSrv, $window) { $rootScope.compiledScope = $scope.$new(true, $rootScope); $scope.looknfeel = 'default'; var init = function() { $scope.asIframe = (($window.location.href.indexOf('asIframe') > -1) ? true : false); + websocketMsgSrv.getSystemConf(); }; init(); diff --git a/zeppelin-web/src/app/home/home.controller.js b/zeppelin-web/src/app/home/home.controller.js index 64ff8801557..2554a637ca5 100644 --- a/zeppelin-web/src/app/home/home.controller.js +++ b/zeppelin-web/src/app/home/home.controller.js @@ -13,8 +13,8 @@ */ 'use strict'; -angular.module('zeppelinWebApp').controller('HomeCtrl', function($scope, notebookListDataFactory, websocketMsgSrv, $rootScope, arrayOrderingSrv) { - +angular.module('zeppelinWebApp').controller('HomeCtrl', function($scope, notebookListDataFactory, websocketMsgSrv, $rootScope, arrayOrderingSrv, systemConfDataFactory) { + var vm = this; vm.notes = notebookListDataFactory; vm.websocketMsgSrv = websocketMsgSrv; @@ -22,7 +22,9 @@ angular.module('zeppelinWebApp').controller('HomeCtrl', function($scope, noteboo vm.notebookHome = false; vm.staticHome = false; - + + vm.systemConfDataFactory = systemConfDataFactory; + var initHome = function() { websocketMsgSrv.getHomeNotebook(); }; diff --git a/zeppelin-web/src/app/home/home.html b/zeppelin-web/src/app/home/home.html index da7f6fb3f9d..c69045a5c8f 100644 --- a/zeppelin-web/src/app/home/home.html +++ b/zeppelin-web/src/app/home/home.html @@ -29,9 +29,9 @@

Notebook

-
+
Import note
-
+
Create new note
  • diff --git a/zeppelin-web/src/app/notebook/notebook-actionBar.html b/zeppelin-web/src/app/notebook/notebook-actionBar.html index 360b8f7d477..8270353a9f9 100644 --- a/zeppelin-web/src/app/notebook/notebook-actionBar.html +++ b/zeppelin-web/src/app/notebook/notebook-actionBar.html @@ -15,7 +15,7 @@

    -

    {{note.name || 'Note ' + note.id}}

    +

    {{note.name || 'Note ' + note.id}}

diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index 7a92cd00fc7..aed8e033a61 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -16,11 +16,12 @@ angular.module('zeppelinWebApp') .controller('ParagraphCtrl', function($scope,$rootScope, $route, $window, $element, $routeParams, $location, - $timeout, $compile, websocketMsgSrv) { + $timeout, $compile, websocketMsgSrv, systemConfDataFactory) { $scope.paragraph = null; $scope.originalText = ''; $scope.editor = null; + $scope.systemConfDataFactory = systemConfDataFactory; var editorModes = { 'ace/mode/scala': /^%spark/, @@ -593,6 +594,9 @@ angular.module('zeppelinWebApp') }; $scope.editor.on('focus', function() { + if(systemConfDataFactory.conf.readonly) { + $scope.editor.setReadOnly(systemConfDataFactory.conf.readonly); + } $scope.handleFocus(true); }); diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.html b/zeppelin-web/src/app/notebook/paragraph/paragraph.html index 043b6e81739..d9297fe9f55 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.html +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.html @@ -28,7 +28,7 @@ ng-blur="setTitle(); showTitleEditor = false" ng-enter="setTitle(); showTitleEditor = false" focus-if="showTitleEditor" /> -
@@ -45,7 +45,7 @@ require : ['ace/ext/language_tools'] }" ng-model="paragraph.text" - ng-class="{'disable': paragraph.status == 'RUNNING' || paragraph.status == 'PENDING', + ng-class="{'disable': systemConfDataFactory.conf.readonly || paragraph.status == 'RUNNING' || paragraph.status == 'PENDING', 'paragraph-text--dirty' : dirtyText !== originalText && dirtyText !== undefined}"> diff --git a/zeppelin-web/src/components/navbar/navbar.controller.js b/zeppelin-web/src/components/navbar/navbar.controller.js index 30e6ac27892..ec4dfe1eb14 100644 --- a/zeppelin-web/src/components/navbar/navbar.controller.js +++ b/zeppelin-web/src/components/navbar/navbar.controller.js @@ -15,7 +15,7 @@ 'use strict'; angular.module('zeppelinWebApp').controller('NavCtrl', function($scope, $rootScope, $routeParams, - $location, notebookListDataFactory, websocketMsgSrv, arrayOrderingSrv) { + $location, notebookListDataFactory, websocketMsgSrv, arrayOrderingSrv, systemConfDataFactory) { /** Current list of notes (ids) */ var vm = this; @@ -23,6 +23,7 @@ angular.module('zeppelinWebApp').controller('NavCtrl', function($scope, $rootSco vm.connected = websocketMsgSrv.isConnected(); vm.websocketMsgSrv = websocketMsgSrv; vm.arrayOrderingSrv = arrayOrderingSrv; + vm.systemConfDataFactory = systemConfDataFactory; angular.element('#notebook-list').perfectScrollbar({suppressScrollX: true}); @@ -43,6 +44,10 @@ angular.module('zeppelinWebApp').controller('NavCtrl', function($scope, $rootSco } }); + $scope.$on('setSystemConf', function(event, conf) { + systemConfDataFactory.setSystemConf(conf); + }); + $scope.search = function() { $location.url(/search/ + $scope.searchTerm); }; diff --git a/zeppelin-web/src/components/navbar/navbar.html b/zeppelin-web/src/components/navbar/navbar.html index 86a85122add..88e8d98d86f 100644 --- a/zeppelin-web/src/components/navbar/navbar.html +++ b/zeppelin-web/src/components/navbar/navbar.html @@ -20,7 +20,7 @@ - I'm zeppelin Zeppelin + I'm zeppelin Zeppelin @@ -29,8 +29,8 @@ -
  • +
  • Interpreter
  • diff --git a/zeppelin-web/src/components/systemConfDataFactory/systemConf.datafactory.js b/zeppelin-web/src/components/systemConfDataFactory/systemConf.datafactory.js new file mode 100644 index 00000000000..42b76b6deda --- /dev/null +++ b/zeppelin-web/src/components/systemConfDataFactory/systemConf.datafactory.js @@ -0,0 +1,31 @@ +/* + * Licensed 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. + */ +'use strict'; + +angular.module('zeppelinWebApp').factory('systemConfDataFactory', function() { + var vm = {}; + + vm.conf = {}; + + vm.setSystemConf = function(systemConf) { + for(var key in systemConf) { + if (systemConf[key] === 'true' || systemConf[key] === 'false') { + vm.conf[key] = systemConf[key] === 'true'; + } else { + vm.conf[key] = systemConf[key]; + } + } + }; + return vm; +}); diff --git a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js index dad2cb5545f..dfede131b55 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js +++ b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js @@ -13,7 +13,7 @@ */ 'use strict'; -angular.module('zeppelinWebApp').factory('websocketEvents', function($rootScope, $websocket, baseUrlSrv) { +angular.module('zeppelinWebApp').factory('websocketEvents', function($rootScope, $websocket, baseUrlSrv, systemConfDataFactory) { var websocketCalls = {}; websocketCalls.ws = $websocket(baseUrlSrv.getWebsocketUrl()); @@ -58,6 +58,8 @@ angular.module('zeppelinWebApp').factory('websocketEvents', function($rootScope, $rootScope.$broadcast('angularObjectUpdate', data); } else if (op === 'ANGULAR_OBJECT_REMOVE') { $rootScope.$broadcast('angularObjectRemove', data); + } else if (op === 'GET_SYSTEM_CONF') { + $rootScope.$broadcast('setSystemConf', data.conf); } }); diff --git a/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js b/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js index a10bc875242..db8ca1aaf01 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js +++ b/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js @@ -21,6 +21,10 @@ angular.module('zeppelinWebApp').service('websocketMsgSrv', function($rootScope, websocketEvents.sendNewEvent({op: 'GET_HOME_NOTE'}); }, + getSystemConf: function() { + websocketEvents.sendNewEvent({op:'GET_SYSTEM_CONF'}); + }, + createNotebook: function(noteName) { websocketEvents.sendNewEvent({op: 'NEW_NOTE',data: {name: noteName}}); }, diff --git a/zeppelin-web/src/index.html b/zeppelin-web/src/index.html index 2b114654355..96a40f94acc 100644 --- a/zeppelin-web/src/index.html +++ b/zeppelin-web/src/index.html @@ -147,6 +147,7 @@ + diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java index ed3b8c0db19..32210c64e78 100755 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java @@ -434,7 +434,8 @@ public static enum ConfVars { ZEPPELIN_CONF_DIR("zeppelin.conf.dir", "conf"), // Allows a way to specify a ',' separated list of allowed origins for rest and websockets // i.e. http://localhost:8080 - ZEPPELIN_ALLOWED_ORIGINS("zeppelin.server.allowed.origins", "*"); + ZEPPELIN_ALLOWED_ORIGINS("zeppelin.server.allowed.origins", "*"), + ZEPPELIN_READ_ONLY("zeppelin.server.readonly", "false"); private String varName; @SuppressWarnings("rawtypes")