Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conf/zeppelin-env.sh.template
Original file line number Diff line number Diff line change
Expand Up @@ -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 ####

Expand Down
6 changes: 6 additions & 0 deletions conf/zeppelin-site.xml.template
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@
<description>Location of jetty temporary directory</description>
</property>

<property>
<name>zeppelin.server.readonly</name>
<value>false</value>
<description>Read-only mode. Disabled editing or creating notebook when this value set to "true". default "false"</description>
</property>

<property>
<name>zeppelin.notebook.dir</name>
<value>notebook</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -53,15 +55,17 @@ public class InterpreterRestApi {
Logger logger = LoggerFactory.getLogger(InterpreterRestApi.class);

private InterpreterFactory interpreterFactory;
private ZeppelinConfiguration conf;

Gson gson = new Gson();

public InterpreterRestApi() {

}

public InterpreterRestApi(InterpreterFactory interpreterFactory) {
public InterpreterRestApi(InterpreterFactory interpreterFactory, ZeppelinConfiguration conf) {
this.interpreterFactory = interpreterFactory;
this.conf = conf;
}

/**
Expand All @@ -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();
Expand All @@ -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);
Expand Down Expand Up @@ -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();
}
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -270,7 +270,7 @@ public Set<Object> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -90,14 +90,30 @@ public static enum OP {
NOTES_INFO, // [s-c] list of note infos
// @param notes serialized List<NoteInfo> 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public class NotebookServer extends WebSocketServlet implements
Gson gson = new Gson();
final Map<String, List<NotebookSocket>> noteSocketMap = new HashMap<>();
final Queue<NotebookSocket> 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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this condition should be in runParagraph(...) too

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Xrixcis I think it is intended to make Zeppelin readonly(blocks notebook/paragraph CRUD), but let user still able to run.

p.setTitle((String) fromMessage.get("title"));
p.setText((String) fromMessage.get("paragraph"));
}
note.persist();
broadcast(note.id(), new Message(OP.PARAGRAPH).put("paragraph", p));
}
Expand Down Expand Up @@ -642,6 +659,14 @@ private void angularObjectUpdated(NotebookSocket conn, Notebook notebook,
}
}

private void sendSystemConf(NotebookSocket conn, Notebook notebook,
Message fromMessage) throws IOException {
Map<String, String> confProperty = new HashMap<String, String>();
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");
Expand Down Expand Up @@ -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<String, Object> params = (Map<String, Object>) fromMessage
.get("params");
p.settings.setParams(params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.*;


Expand Down Expand Up @@ -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.",
Expand All @@ -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"));
}

Expand Down
3 changes: 2 additions & 1 deletion zeppelin-web/.jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"nv": false,
"ace": false,
"d3": false,
"BootstrapDialog": false
"BootstrapDialog": false,
"$": false
}
}
3 changes: 2 additions & 1 deletion zeppelin-web/src/app/app.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
8 changes: 5 additions & 3 deletions zeppelin-web/src/app/home/home.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@
*/
'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;
vm.arrayOrderingSrv = arrayOrderingSrv;

vm.notebookHome = false;
vm.staticHome = false;


vm.systemConfDataFactory = systemConfDataFactory;

var initHome = function() {
websocketMsgSrv.getHomeNotebook();
};
Expand Down
4 changes: 2 additions & 2 deletions zeppelin-web/src/app/home/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ <h1 class="box-heading" id="welcome">
<h4>Notebook</h4>

<div>
<h5><a href="" data-toggle="modal" data-target="#noteImportModal" style="text-decoration: none;">
<h5 ng-hide="home.systemConfDataFactory.conf.readonly"><a href="" data-toggle="modal" data-target="#noteImportModal" style="text-decoration: none;">
<i style="font-size: 15px;" class="fa fa-upload"></i> Import note</a></h5>
<h5><a href="" data-toggle="modal" data-target="#noteNameModal" style="text-decoration: none;">
<h5 ng-hide="home.systemConfDataFactory.conf.readonly"><a href="" data-toggle="modal" data-target="#noteNameModal" style="text-decoration: none;">
<i style="font-size: 15px;" class="icon-notebook"></i> Create new note</a></h5>
<ul style="list-style-type: none;">
<li ng-repeat="note in home.notes.list | orderBy:home.arrayOrderingSrv.notebookListOrdering track by $index">
Expand Down
Loading