mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Merge branch 'master' of https://github.com/apache/incubator-zeppelin
This commit is contained in:
commit
35a6679bac
14 changed files with 383 additions and 129 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -21,6 +21,7 @@ conf/zeppelin-site.xml
|
|||
conf/keystore
|
||||
conf/truststore
|
||||
conf/interpreter.json
|
||||
conf/notebook-authorization.json
|
||||
|
||||
# other generated files
|
||||
spark/dependency-reduced-pom.xml
|
||||
|
|
|
|||
1
pom.xml
1
pom.xml
|
|
@ -477,6 +477,7 @@
|
|||
<exclude>**/licenses/**</exclude>
|
||||
<exclude>**/zeppelin-distribution/src/bin_license/**</exclude>
|
||||
<exclude>conf/interpreter.json</exclude>
|
||||
<exclude>conf/notebook-authorization.json</exclude>
|
||||
<exclude>conf/zeppelin-env.sh</exclude>
|
||||
<exclude>spark-*-bin*/**</exclude>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,7 @@
|
|||
package org.apache.zeppelin.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
|
|
@ -39,6 +35,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.apache.zeppelin.interpreter.InterpreterSetting;
|
||||
import org.apache.zeppelin.notebook.Note;
|
||||
import org.apache.zeppelin.notebook.Notebook;
|
||||
import org.apache.zeppelin.notebook.NotebookAuthorization;
|
||||
import org.apache.zeppelin.notebook.Paragraph;
|
||||
import org.apache.zeppelin.rest.message.CronRequest;
|
||||
import org.apache.zeppelin.rest.message.InterpreterSettingListForNoteBind;
|
||||
|
|
@ -69,6 +66,7 @@ public class NotebookRestApi {
|
|||
private Notebook notebook;
|
||||
private NotebookServer notebookServer;
|
||||
private SearchService notebookIndex;
|
||||
private NotebookAuthorization notebookAuthorization;
|
||||
|
||||
public NotebookRestApi() {}
|
||||
|
||||
|
|
@ -76,24 +74,25 @@ public class NotebookRestApi {
|
|||
this.notebook = notebook;
|
||||
this.notebookServer = notebookServer;
|
||||
this.notebookIndex = search;
|
||||
this.notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
}
|
||||
|
||||
/**
|
||||
* list note owners
|
||||
* get note authorization information
|
||||
*/
|
||||
@GET
|
||||
@Path("{noteId}/permissions")
|
||||
public Response getNotePermissions(@PathParam("noteId") String noteId) {
|
||||
Note note = notebook.getNote(noteId);
|
||||
HashMap<String, HashSet> permissionsMap = new HashMap<String, HashSet>();
|
||||
permissionsMap.put("owners", note.getOwners());
|
||||
permissionsMap.put("readers", note.getReaders());
|
||||
permissionsMap.put("writers", note.getWriters());
|
||||
HashMap<String, Set<String>> permissionsMap = new HashMap();
|
||||
permissionsMap.put("owners", notebookAuthorization.getOwners(noteId));
|
||||
permissionsMap.put("readers", notebookAuthorization.getReaders(noteId));
|
||||
permissionsMap.put("writers", notebookAuthorization.getWriters(noteId));
|
||||
return new JsonResponse<>(Status.OK, "", permissionsMap).build();
|
||||
}
|
||||
|
||||
String ownerPermissionError(HashSet<String> current,
|
||||
HashSet<String> allowed) throws IOException {
|
||||
String ownerPermissionError(Set<String> current,
|
||||
Set<String> allowed) throws IOException {
|
||||
LOG.info("Cannot change permissions. Connection owners {}. Allowed owners {}",
|
||||
current.toString(), allowed.toString());
|
||||
return "Insufficient privileges to change permissions.\n\n" +
|
||||
|
|
@ -102,7 +101,7 @@ public class NotebookRestApi {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set note owners
|
||||
* set note authorization information
|
||||
*/
|
||||
@PUT
|
||||
@Path("{noteId}/permissions")
|
||||
|
|
@ -124,15 +123,17 @@ public class NotebookRestApi {
|
|||
HashSet<String> userAndRoles = new HashSet<String>();
|
||||
userAndRoles.add(principal);
|
||||
userAndRoles.addAll(roles);
|
||||
if (!note.isOwner(userAndRoles)) {
|
||||
if (!notebookAuthorization.isOwner(noteId, userAndRoles)) {
|
||||
return new JsonResponse<>(Status.FORBIDDEN, ownerPermissionError(userAndRoles,
|
||||
note.getOwners())).build();
|
||||
notebookAuthorization.getOwners(noteId))).build();
|
||||
}
|
||||
note.setOwners(permMap.get("owners"));
|
||||
note.setReaders(permMap.get("readers"));
|
||||
note.setWriters(permMap.get("writers"));
|
||||
LOG.debug("After set permissions {} {} {}", note.getOwners(), note.getReaders(),
|
||||
note.getWriters());
|
||||
notebookAuthorization.setOwners(noteId, permMap.get("owners"));
|
||||
notebookAuthorization.setReaders(noteId, permMap.get("readers"));
|
||||
notebookAuthorization.setWriters(noteId, permMap.get("writers"));
|
||||
LOG.debug("After set permissions {} {} {}",
|
||||
notebookAuthorization.getOwners(noteId),
|
||||
notebookAuthorization.getReaders(noteId),
|
||||
notebookAuthorization.getWriters(noteId));
|
||||
note.persist();
|
||||
notebookServer.broadcastNote(note);
|
||||
return new JsonResponse<>(Status.OK).build();
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
|
|||
import org.apache.zeppelin.dep.DependencyResolver;
|
||||
import org.apache.zeppelin.interpreter.InterpreterFactory;
|
||||
import org.apache.zeppelin.notebook.Notebook;
|
||||
import org.apache.zeppelin.notebook.NotebookAuthorization;
|
||||
import org.apache.zeppelin.notebook.repo.NotebookRepo;
|
||||
import org.apache.zeppelin.notebook.repo.NotebookRepoSync;
|
||||
import org.apache.zeppelin.rest.*;
|
||||
|
|
@ -71,6 +72,7 @@ public class ZeppelinServer extends Application {
|
|||
private InterpreterFactory replFactory;
|
||||
private NotebookRepo notebookRepo;
|
||||
private SearchService notebookIndex;
|
||||
private NotebookAuthorization notebookAuthorization;
|
||||
private DependencyResolver depResolver;
|
||||
|
||||
public ZeppelinServer() throws Exception {
|
||||
|
|
@ -83,9 +85,10 @@ public class ZeppelinServer extends Application {
|
|||
notebookWsServer, depResolver);
|
||||
this.notebookRepo = new NotebookRepoSync(conf);
|
||||
this.notebookIndex = new LuceneSearch();
|
||||
|
||||
this.notebookAuthorization = new NotebookAuthorization(conf);
|
||||
notebook = new Notebook(conf,
|
||||
notebookRepo, schedulerFactory, replFactory, notebookWsServer, notebookIndex);
|
||||
notebookRepo, schedulerFactory, replFactory, notebookWsServer,
|
||||
notebookIndex, notebookAuthorization);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
|
|
|||
|
|
@ -371,8 +371,8 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
broadcastAll(new Message(OP.NOTES_INFO).put("notes", notesInfo));
|
||||
}
|
||||
|
||||
void permissionError(NotebookSocket conn, String op, HashSet<String> current,
|
||||
HashSet<String> allowed) throws IOException {
|
||||
void permissionError(NotebookSocket conn, String op, Set<String> current,
|
||||
Set<String> allowed) throws IOException {
|
||||
LOG.info("Cannot {}. Connection readers {}. Allowed readers {}",
|
||||
op, current, allowed);
|
||||
conn.send(serializeMessage(new Message(OP.AUTH_INFO).put("info",
|
||||
|
|
@ -395,9 +395,10 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
}
|
||||
|
||||
Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (note != null) {
|
||||
if (!note.isReader(userAndRoles)) {
|
||||
permissionError(conn, "read", userAndRoles, note.getReaders());
|
||||
if (!notebookAuthorization.isReader(noteId, userAndRoles)) {
|
||||
permissionError(conn, "read", userAndRoles, notebookAuthorization.getReaders(noteId));
|
||||
broadcastNoteList();
|
||||
return;
|
||||
}
|
||||
|
|
@ -417,8 +418,9 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
}
|
||||
|
||||
if (note != null) {
|
||||
if (!note.isReader(userAndRoles)) {
|
||||
permissionError(conn, "read", userAndRoles, note.getReaders());
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isReader(noteId, userAndRoles)) {
|
||||
permissionError(conn, "read", userAndRoles, notebookAuthorization.getReaders(noteId));
|
||||
broadcastNoteList();
|
||||
return;
|
||||
}
|
||||
|
|
@ -502,9 +504,9 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
}
|
||||
|
||||
Note note = notebook.getNote(noteId);
|
||||
|
||||
if (!note.isOwner(userAndRoles)) {
|
||||
permissionError(conn, "remove", userAndRoles, note.getOwners());
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isOwner(noteId, userAndRoles)) {
|
||||
permissionError(conn, "remove", userAndRoles, notebookAuthorization.getOwners(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -524,10 +526,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
.get("params");
|
||||
Map<String, Object> config = (Map<String, Object>) fromMessage
|
||||
.get("config");
|
||||
final Note note = notebook.getNote(getOpenNoteId(conn));
|
||||
|
||||
if (!note.isWriter(userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, note.getWriters());
|
||||
String noteId = getOpenNoteId(conn);
|
||||
final Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, notebookAuthorization.getWriters(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -572,11 +575,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
if (paragraphId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Note note = notebook.getNote(getOpenNoteId(conn));
|
||||
|
||||
if (!note.isWriter(userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, note.getWriters());
|
||||
String noteId = getOpenNoteId(conn);
|
||||
final Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, notebookAuthorization.getWriters(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -594,11 +597,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
if (paragraphId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Note note = notebook.getNote(getOpenNoteId(conn));
|
||||
|
||||
if (!note.isWriter(userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, note.getWriters());
|
||||
String noteId = getOpenNoteId(conn);
|
||||
final Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, notebookAuthorization.getWriters(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -722,10 +725,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
|
||||
final int newIndex = (int) Double.parseDouble(fromMessage.get("index")
|
||||
.toString());
|
||||
final Note note = notebook.getNote(getOpenNoteId(conn));
|
||||
|
||||
if (!note.isWriter(userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, note.getWriters());
|
||||
String noteId = getOpenNoteId(conn);
|
||||
final Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, notebookAuthorization.getWriters(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -738,10 +742,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
Notebook notebook, Message fromMessage) throws IOException {
|
||||
final int index = (int) Double.parseDouble(fromMessage.get("index")
|
||||
.toString());
|
||||
final Note note = notebook.getNote(getOpenNoteId(conn));
|
||||
|
||||
if (!note.isWriter(userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, note.getWriters());
|
||||
String noteId = getOpenNoteId(conn);
|
||||
final Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, notebookAuthorization.getWriters(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -757,10 +762,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
return;
|
||||
}
|
||||
|
||||
final Note note = notebook.getNote(getOpenNoteId(conn));
|
||||
|
||||
if (!note.isWriter(userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, note.getWriters());
|
||||
String noteId = getOpenNoteId(conn);
|
||||
final Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, notebookAuthorization.getWriters(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -775,10 +781,11 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
return;
|
||||
}
|
||||
|
||||
final Note note = notebook.getNote(getOpenNoteId(conn));
|
||||
|
||||
if (!note.isWriter(userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, note.getWriters());
|
||||
String noteId = getOpenNoteId(conn);
|
||||
final Note note = notebook.getNote(noteId);
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
permissionError(conn, "write", userAndRoles, notebookAuthorization.getWriters(noteId));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ public class WebDriverManager {
|
|||
}
|
||||
|
||||
String url;
|
||||
if (System.getProperty("url") != null) {
|
||||
url = System.getProperty("url");
|
||||
if (System.getenv("url") != null) {
|
||||
url = System.getenv("url");
|
||||
} else {
|
||||
url = "http://localhost:8080";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,6 +342,10 @@ public class ZeppelinConfiguration extends XMLConfiguration {
|
|||
return getRelativeDir(String.format("%s/interpreter.json", getConfDir()));
|
||||
}
|
||||
|
||||
public String getNotebookAuthorizationPath() {
|
||||
return getRelativeDir(String.format("%s/notebook-authorization.json", getConfDir()));
|
||||
}
|
||||
|
||||
public String getInterpreterRemoteRunnerPath() {
|
||||
return getRelativeDir(ConfVars.ZEPPELIN_INTERPRETER_REMOTE_RUNNER);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,9 +59,6 @@ public class Note implements Serializable, JobListener {
|
|||
|
||||
private String name = "";
|
||||
private String id;
|
||||
private HashSet<String> owners = new HashSet<String>();
|
||||
private HashSet<String> readers = new HashSet<String>();
|
||||
private HashSet<String> writers = new HashSet<String>();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<String, List<AngularObject>> angularObjects = new HashMap<>();
|
||||
|
|
@ -118,51 +115,6 @@ public class Note implements Serializable, JobListener {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public HashSet<String> getOwners() {
|
||||
return (new HashSet<String>(owners));
|
||||
}
|
||||
|
||||
public void setOwners(HashSet<String> owners) {
|
||||
this.owners = new HashSet<String>(owners);
|
||||
}
|
||||
|
||||
public HashSet<String> getReaders() {
|
||||
return (new HashSet<String>(readers));
|
||||
}
|
||||
|
||||
public void setReaders(HashSet<String> readers) {
|
||||
this.readers = new HashSet<String>(readers);
|
||||
}
|
||||
|
||||
public HashSet<String> getWriters() {
|
||||
return (new HashSet<String>(writers));
|
||||
}
|
||||
|
||||
public void setWriters(HashSet<String> writers) {
|
||||
this.writers = new HashSet<String>(writers);
|
||||
}
|
||||
|
||||
public boolean isOwner(HashSet<String> entities) {
|
||||
return isMember(entities, this.owners);
|
||||
}
|
||||
|
||||
public boolean isWriter(HashSet<String> entities) {
|
||||
return isMember(entities, this.writers) || isMember(entities, this.owners);
|
||||
}
|
||||
|
||||
public boolean isReader(HashSet<String> entities) {
|
||||
return isMember(entities, this.readers) ||
|
||||
isMember(entities, this.owners) ||
|
||||
isMember(entities, this.writers);
|
||||
}
|
||||
|
||||
// return true if b is empty or if (a intersection b) is non-empty
|
||||
private boolean isMember(HashSet<String> a, HashSet<String> b) {
|
||||
Set<String> intersection = new HashSet<String>(b);
|
||||
intersection.retainAll(a);
|
||||
return (b.isEmpty() || (intersection.size() > 0));
|
||||
}
|
||||
|
||||
public NoteInterpreterLoader getNoteReplLoader() {
|
||||
return replLoader;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ public class Notebook {
|
|||
private JobListenerFactory jobListenerFactory;
|
||||
private NotebookRepo notebookRepo;
|
||||
private SearchService notebookIndex;
|
||||
private NotebookAuthorization notebookAuthorization;
|
||||
|
||||
/**
|
||||
* Main constructor \w manual Dependency Injection
|
||||
|
|
@ -86,6 +87,7 @@ public class Notebook {
|
|||
* @param replFactory
|
||||
* @param jobListenerFactory
|
||||
* @param notebookIndex - (nullable) for indexing all notebooks on creating.
|
||||
* @param notebookAuthorization
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws SchedulerException
|
||||
|
|
@ -93,13 +95,15 @@ public class Notebook {
|
|||
public Notebook(ZeppelinConfiguration conf, NotebookRepo notebookRepo,
|
||||
SchedulerFactory schedulerFactory,
|
||||
InterpreterFactory replFactory, JobListenerFactory jobListenerFactory,
|
||||
SearchService notebookIndex) throws IOException, SchedulerException {
|
||||
SearchService notebookIndex,
|
||||
NotebookAuthorization notebookAuthorization) throws IOException, SchedulerException {
|
||||
this.conf = conf;
|
||||
this.notebookRepo = notebookRepo;
|
||||
this.schedulerFactory = schedulerFactory;
|
||||
this.replFactory = replFactory;
|
||||
this.jobListenerFactory = jobListenerFactory;
|
||||
this.notebookIndex = notebookIndex;
|
||||
this.notebookAuthorization = notebookAuthorization;
|
||||
quertzSchedFact = new org.quartz.impl.StdSchedulerFactory();
|
||||
quartzSched = quertzSchedFact.getScheduler();
|
||||
quartzSched.start();
|
||||
|
|
@ -281,6 +285,7 @@ public class Notebook {
|
|||
}
|
||||
replFactory.removeNoteInterpreterSettingBinding(id);
|
||||
notebookIndex.deleteIndexDocs(note);
|
||||
notebookAuthorization.removeNote(id);
|
||||
|
||||
// remove from all interpreter instance's angular object registry
|
||||
for (InterpreterSetting settings : replFactory.get()) {
|
||||
|
|
@ -575,6 +580,10 @@ public class Notebook {
|
|||
return replFactory;
|
||||
}
|
||||
|
||||
public NotebookAuthorization getNotebookAuthorization() {
|
||||
return notebookAuthorization;
|
||||
}
|
||||
|
||||
public ZeppelinConfiguration getConf() {
|
||||
return conf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* 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.notebook;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Contains authorization information for notes
|
||||
*/
|
||||
public class NotebookAuthorization {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NotebookAuthorization.class);
|
||||
|
||||
/*
|
||||
* { "note1": { "owners": ["u1"], "readers": ["u1", "u2"], "writers": ["u1"] }, "note2": ... } }
|
||||
*/
|
||||
private Map<String, Map<String, Set<String>>> authInfo = new HashMap<>();
|
||||
private ZeppelinConfiguration conf;
|
||||
private Gson gson;
|
||||
private String filePath;
|
||||
|
||||
public NotebookAuthorization(ZeppelinConfiguration conf) {
|
||||
this.conf = conf;
|
||||
filePath = conf.getNotebookAuthorizationPath();
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.setPrettyPrinting();
|
||||
gson = builder.create();
|
||||
try {
|
||||
loadFromFile();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error loading NotebookAuthorization");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFromFile() throws IOException {
|
||||
File settingFile = new File(filePath);
|
||||
LOG.info(settingFile.getAbsolutePath());
|
||||
if (!settingFile.exists()) {
|
||||
// nothing to read
|
||||
return;
|
||||
}
|
||||
FileInputStream fis = new FileInputStream(settingFile);
|
||||
InputStreamReader isr = new InputStreamReader(fis);
|
||||
BufferedReader bufferedReader = new BufferedReader(isr);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
isr.close();
|
||||
fis.close();
|
||||
|
||||
String json = sb.toString();
|
||||
NotebookAuthorizationInfoSaving info = gson.fromJson(json,
|
||||
NotebookAuthorizationInfoSaving.class);
|
||||
this.authInfo = info.authInfo;
|
||||
}
|
||||
|
||||
private void saveToFile() {
|
||||
String jsonString;
|
||||
|
||||
synchronized (authInfo) {
|
||||
NotebookAuthorizationInfoSaving info = new NotebookAuthorizationInfoSaving();
|
||||
info.authInfo = authInfo;
|
||||
jsonString = gson.toJson(info);
|
||||
}
|
||||
|
||||
try {
|
||||
File settingFile = new File(filePath);
|
||||
if (!settingFile.exists()) {
|
||||
settingFile.createNewFile();
|
||||
}
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(settingFile, false);
|
||||
OutputStreamWriter out = new OutputStreamWriter(fos);
|
||||
out.append(jsonString);
|
||||
out.close();
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error saving notebook authorization file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setOwners(String noteId, Set<String> entities) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
if (noteAuthInfo == null) {
|
||||
noteAuthInfo = new LinkedHashMap();
|
||||
noteAuthInfo.put("owners", new LinkedHashSet(entities));
|
||||
noteAuthInfo.put("readers", new LinkedHashSet());
|
||||
noteAuthInfo.put("writers", new LinkedHashSet());
|
||||
authInfo.put(noteId, noteAuthInfo);
|
||||
} else {
|
||||
Set<String> existingEntities = noteAuthInfo.get("owners");
|
||||
if (existingEntities == null) {
|
||||
noteAuthInfo.put("owners", new LinkedHashSet(entities));
|
||||
} else {
|
||||
existingEntities.addAll(entities);
|
||||
}
|
||||
}
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
public void setReaders(String noteId, Set<String> entities) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
if (noteAuthInfo == null) {
|
||||
noteAuthInfo = new LinkedHashMap();
|
||||
noteAuthInfo.put("owners", new LinkedHashSet());
|
||||
noteAuthInfo.put("readers", new LinkedHashSet(entities));
|
||||
noteAuthInfo.put("writers", new LinkedHashSet());
|
||||
authInfo.put(noteId, noteAuthInfo);
|
||||
} else {
|
||||
Set<String> existingEntities = noteAuthInfo.get("readers");
|
||||
if (existingEntities == null) {
|
||||
noteAuthInfo.put("readers", new LinkedHashSet(entities));
|
||||
} else {
|
||||
existingEntities.addAll(entities);
|
||||
}
|
||||
}
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
public void setWriters(String noteId, Set<String> entities) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
if (noteAuthInfo == null) {
|
||||
noteAuthInfo = new LinkedHashMap();
|
||||
noteAuthInfo.put("owners", new LinkedHashSet());
|
||||
noteAuthInfo.put("readers", new LinkedHashSet());
|
||||
noteAuthInfo.put("writers", new LinkedHashSet(entities));
|
||||
authInfo.put(noteId, noteAuthInfo);
|
||||
} else {
|
||||
Set<String> existingEntities = noteAuthInfo.get("writers");
|
||||
if (existingEntities == null) {
|
||||
noteAuthInfo.put("writers", new LinkedHashSet(entities));
|
||||
} else {
|
||||
existingEntities.addAll(entities);
|
||||
}
|
||||
}
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
public Set<String> getOwners(String noteId) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
Set<String> entities = null;
|
||||
if (noteAuthInfo == null) {
|
||||
entities = new HashSet<String>();
|
||||
} else {
|
||||
entities = noteAuthInfo.get("owners");
|
||||
if (entities == null) {
|
||||
entities = new HashSet<String>();
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public Set<String> getReaders(String noteId) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
Set<String> entities = null;
|
||||
if (noteAuthInfo == null) {
|
||||
entities = new HashSet<String>();
|
||||
} else {
|
||||
entities = noteAuthInfo.get("readers");
|
||||
if (entities == null) {
|
||||
entities = new HashSet<String>();
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public Set<String> getWriters(String noteId) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
Set<String> entities = null;
|
||||
if (noteAuthInfo == null) {
|
||||
entities = new HashSet<String>();
|
||||
} else {
|
||||
entities = noteAuthInfo.get("writers");
|
||||
if (entities == null) {
|
||||
entities = new HashSet<String>();
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public boolean isOwner(String noteId, Set<String> entities) {
|
||||
return isMember(entities, getOwners(noteId));
|
||||
}
|
||||
|
||||
public boolean isWriter(String noteId, Set<String> entities) {
|
||||
return isMember(entities, getWriters(noteId)) || isMember(entities, getOwners(noteId));
|
||||
}
|
||||
|
||||
public boolean isReader(String noteId, Set<String> entities) {
|
||||
return isMember(entities, getReaders(noteId)) ||
|
||||
isMember(entities, getOwners(noteId)) ||
|
||||
isMember(entities, getWriters(noteId));
|
||||
}
|
||||
|
||||
// return true if b is empty or if (a intersection b) is non-empty
|
||||
private boolean isMember(Set<String> a, Set<String> b) {
|
||||
Set<String> intersection = new HashSet<String>(b);
|
||||
intersection.retainAll(a);
|
||||
return (b.isEmpty() || (intersection.size() > 0));
|
||||
}
|
||||
|
||||
public void removeNote(String noteId) {
|
||||
authInfo.remove(noteId);
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.notebook;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Only used for saving NotebookAuthorization info
|
||||
*/
|
||||
public class NotebookAuthorizationInfoSaving {
|
||||
public Map<String, Map<String, Set<String>>> authInfo;
|
||||
}
|
||||
|
|
@ -87,7 +87,8 @@ public class NotebookTest implements JobListenerFactory{
|
|||
|
||||
SearchService search = mock(SearchService.class);
|
||||
notebookRepo = new VFSNotebookRepo(conf);
|
||||
notebook = new Notebook(conf, notebookRepo, schedulerFactory, factory, this, search);
|
||||
NotebookAuthorization notebookAuthorization = new NotebookAuthorization(conf);
|
||||
notebook = new Notebook(conf, notebookRepo, schedulerFactory, factory, this, search, notebookAuthorization);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
@ -171,7 +172,7 @@ public class NotebookTest implements JobListenerFactory{
|
|||
|
||||
Notebook notebook2 = new Notebook(
|
||||
conf, notebookRepo, schedulerFactory,
|
||||
new InterpreterFactory(conf, null, null, null, depResolver), this, null);
|
||||
new InterpreterFactory(conf, null, null, null, depResolver), this, null, null);
|
||||
assertEquals(1, notebook2.getAllNotes().size());
|
||||
}
|
||||
|
||||
|
|
@ -422,23 +423,36 @@ public class NotebookTest implements JobListenerFactory{
|
|||
public void testPermissions() throws IOException {
|
||||
// create a note and a paragraph
|
||||
Note note = notebook.createNote();
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
// empty owners, readers and writers means note is public
|
||||
assertEquals(note.isOwner(new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
assertEquals(note.isReader(new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
assertEquals(note.isWriter(new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isOwner(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isReader(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isWriter(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
|
||||
note.setOwners(new HashSet<String>(Arrays.asList("user1")));
|
||||
note.setReaders(new HashSet<String>(Arrays.asList("user1", "user2")));
|
||||
note.setWriters(new HashSet<String>(Arrays.asList("user1")));
|
||||
notebookAuthorization.setOwners(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user1")));
|
||||
notebookAuthorization.setReaders(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user1", "user2")));
|
||||
notebookAuthorization.setWriters(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user1")));
|
||||
|
||||
assertEquals(note.isOwner(new HashSet<String>(Arrays.asList("user2"))), false);
|
||||
assertEquals(note.isOwner(new HashSet<String>(Arrays.asList("user1"))), true);
|
||||
assertEquals(notebookAuthorization.isOwner(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user2"))), false);
|
||||
assertEquals(notebookAuthorization.isOwner(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user1"))), true);
|
||||
|
||||
assertEquals(note.isReader(new HashSet<String>(Arrays.asList("user3"))), false);
|
||||
assertEquals(note.isReader(new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isReader(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user3"))), false);
|
||||
assertEquals(notebookAuthorization.isReader(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user2"))), true);
|
||||
|
||||
assertEquals(note.isWriter(new HashSet<String>(Arrays.asList("user2"))), false);
|
||||
assertEquals(note.isWriter(new HashSet<String>(Arrays.asList("user1"))), true);
|
||||
assertEquals(notebookAuthorization.isWriter(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user2"))), false);
|
||||
assertEquals(notebookAuthorization.isWriter(note.id(),
|
||||
new HashSet<String>(Arrays.asList("user1"))), true);
|
||||
|
||||
notebook.removeNote(note.id());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
private InterpreterFactory factory;
|
||||
private DependencyResolver depResolver;
|
||||
private SearchService search;
|
||||
private NotebookAuthorization notebookAuthorization;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NotebookRepoSyncTest.class);
|
||||
|
||||
@Before
|
||||
|
|
@ -95,7 +96,8 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
|
||||
search = mock(SearchService.class);
|
||||
notebookRepoSync = new NotebookRepoSync(conf);
|
||||
notebookSync = new Notebook(conf, notebookRepoSync, schedulerFactory, factory, this, search);
|
||||
notebookAuthorization = new NotebookAuthorization(conf);
|
||||
notebookSync = new Notebook(conf, notebookRepoSync, schedulerFactory, factory, this, search, notebookAuthorization);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
@ -220,7 +222,7 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
ZeppelinConfiguration vConf = ZeppelinConfiguration.create();
|
||||
|
||||
NotebookRepoSync vRepoSync = new NotebookRepoSync(vConf);
|
||||
Notebook vNotebookSync = new Notebook(vConf, vRepoSync, schedulerFactory, factory, this, search);
|
||||
Notebook vNotebookSync = new Notebook(vConf, vRepoSync, schedulerFactory, factory, this, search, null);
|
||||
|
||||
// one git versioned storage initialized
|
||||
assertThat(vRepoSync.getRepoCount()).isEqualTo(1);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public class VFSNotebookRepoTest implements JobListenerFactory {
|
|||
|
||||
SearchService search = mock(SearchService.class);
|
||||
notebookRepo = new VFSNotebookRepo(conf);
|
||||
notebook = new Notebook(conf, notebookRepo, schedulerFactory, factory, this, search);
|
||||
notebook = new Notebook(conf, notebookRepo, schedulerFactory, factory, this, search, null);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
|
|||
Loading…
Reference in a new issue