mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
first draft
This commit is contained in:
parent
1e8559e651
commit
17e2d4c0c5
4 changed files with 141 additions and 19 deletions
|
|
@ -168,7 +168,8 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
unicastNoteList(conn, subject);
|
||||
break;
|
||||
case RELOAD_NOTES_FROM_REPO:
|
||||
broadcastReloadedNoteList(subject);
|
||||
//broadcastReloadedNoteList(subject);
|
||||
unicastNoteList(conn, subject);
|
||||
break;
|
||||
case GET_HOME_NOTE:
|
||||
sendHomeNote(conn, userAndRoles, notebook, messagereceived);
|
||||
|
|
@ -331,7 +332,9 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
private void broadcastToNoteBindedInterpreter(String interpreterGroupId,
|
||||
Message m) {
|
||||
Notebook notebook = notebook();
|
||||
List<Note> notes = notebook.getAllNotes();
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
List<Note> notes = notebook.getAllNotes(subject);
|
||||
for (Note note : notes) {
|
||||
List<String> ids = notebook.getInterpreterFactory().getInterpreters(note.getId());
|
||||
for (String id : ids) {
|
||||
|
|
@ -472,6 +475,7 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
LOG.error("Fail to reload notes from repository", e);
|
||||
}
|
||||
}
|
||||
|
||||
List<Note> notes = notebook.getAllNotes(subject);
|
||||
List<Map<String, String>> notesInfo = new LinkedList<>();
|
||||
for (Note note : notes) {
|
||||
|
|
@ -855,7 +859,9 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
|
||||
if (global) { // broadcast change to all web session that uses related
|
||||
// interpreter.
|
||||
for (Note n : notebook.getAllNotes()) {
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
for (Note n : notebook.getAllNotes(subject)) {
|
||||
List<InterpreterSetting> settings = notebook.getInterpreterFactory()
|
||||
.getInterpreterSettings(note.getId());
|
||||
for (InterpreterSetting setting : settings) {
|
||||
|
|
@ -1533,7 +1539,9 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
return;
|
||||
}
|
||||
|
||||
List<Note> notes = notebook.getAllNotes();
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
List<Note> notes = notebook.getAllNotes(subject );
|
||||
for (Note note : notes) {
|
||||
if (object.getNoteId() != null && !note.getId().equals(object.getNoteId())) {
|
||||
continue;
|
||||
|
|
@ -1558,7 +1566,9 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
@Override
|
||||
public void onRemove(String interpreterGroupId, String name, String noteId, String paragraphId) {
|
||||
Notebook notebook = notebook();
|
||||
List<Note> notes = notebook.getAllNotes();
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
List<Note> notes = notebook.getAllNotes(subject);
|
||||
for (Note note : notes) {
|
||||
if (noteId != null && !note.getId().equals(noteId)) {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import org.apache.zeppelin.notebook.Note;
|
|||
import org.apache.zeppelin.notebook.Paragraph;
|
||||
import org.apache.zeppelin.scheduler.Job.Status;
|
||||
import org.apache.zeppelin.server.ZeppelinServer;
|
||||
import org.apache.zeppelin.user.AuthenticationInfo;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.FixMethodOrder;
|
||||
|
|
@ -341,7 +342,9 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
|
||||
}.getType());
|
||||
List<Map<String, String>> body = (List<Map<String, String>>) resp.get("body");
|
||||
assertEquals("List notebooks are equal", ZeppelinServer.notebook.getAllNotes().size(), body.size());
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
assertEquals("List notebooks are equal", ZeppelinServer.notebook.getAllNotes(subject).size(), body.size());
|
||||
get.releaseConnection();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.zeppelin.notebook;
|
|||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
|
@ -31,9 +32,9 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
|
@ -484,11 +485,74 @@ public class Notebook implements NoteEventListener {
|
|||
}
|
||||
|
||||
List<NoteInfo> noteInfos = notebookRepo.list(subject);
|
||||
noteInfos = getAuthorizedNoteInfos(noteInfos, subject);
|
||||
|
||||
for (NoteInfo info : noteInfos) {
|
||||
loadNoteFromRepo(info.getId(), subject);
|
||||
}
|
||||
}
|
||||
|
||||
private List<NoteInfo> getAuthorizedNoteInfos(List<NoteInfo> notes, AuthenticationInfo subject) {
|
||||
Set<String> allIds = Sets.newHashSet();
|
||||
if (subject == null) {
|
||||
logger.warn("Subject for retrieving notes is null");
|
||||
return notes;
|
||||
}
|
||||
if ("anonymous".equals(subject.getUser())) {
|
||||
return notes;
|
||||
}
|
||||
for (NoteInfo note: notes) {
|
||||
allIds.add(note.getId());
|
||||
}
|
||||
Set<String> filteredIds = applyAuthorizationFilter(allIds, subject.getUser());
|
||||
List<NoteInfo> filteredNotes = Lists.newArrayList();
|
||||
for (NoteInfo note: notes) {
|
||||
if (filteredIds.contains(note.getId())){
|
||||
filteredNotes.add(note);
|
||||
}
|
||||
}
|
||||
return filteredNotes;
|
||||
}
|
||||
|
||||
//TODO(khalid): to change from processing everytime to keeping in memory view of each user
|
||||
public List<Note> getAuthorizedNotes(AuthenticationInfo subject) {
|
||||
List<Note> allNotes = new ArrayList<>(notes.values());
|
||||
Set<String> allIds = Sets.newHashSet();
|
||||
|
||||
if (subject == null) {
|
||||
logger.warn("Subject for retrieving notes is null");
|
||||
return allNotes;
|
||||
}
|
||||
if ("anonymous".equals(subject.getUser())) {
|
||||
return allNotes;
|
||||
}
|
||||
for (Note note: allNotes) {
|
||||
allIds.add(note.getId());
|
||||
}
|
||||
Set<String> filteredIds = applyAuthorizationFilter(allIds, subject.getUser());
|
||||
List<Note> filteredNotes = Lists.newArrayList();
|
||||
for (Note note: allNotes) {
|
||||
if (filteredIds.contains(note.getId())){
|
||||
filteredNotes.add(note);
|
||||
}
|
||||
}
|
||||
return filteredNotes;
|
||||
}
|
||||
|
||||
public Set<String> applyAuthorizationFilter(Set<String> ids, String user) {
|
||||
logger.info("applying filter for {}", user);
|
||||
Set<String> filteredIds = Sets.newHashSet();
|
||||
Set<String> userEntity = Sets.newHashSet((Arrays.asList(user)));
|
||||
NotebookAuthorization auth = getNotebookAuthorization();
|
||||
for (String id: ids) {
|
||||
if (auth.isOwner(id, userEntity) || auth.isReader(id, userEntity)
|
||||
|| auth.isWriter(id, userEntity)) {
|
||||
filteredIds.add(id);
|
||||
}
|
||||
}
|
||||
return filteredIds;
|
||||
}
|
||||
|
||||
private class SnapshotAngularObject {
|
||||
String intpGroupId;
|
||||
AngularObject angularObject;
|
||||
|
|
@ -514,9 +578,9 @@ public class Notebook implements NoteEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
public List<Note> getAllNotes() {
|
||||
public List<Note> getAllNotes(AuthenticationInfo subject) {
|
||||
synchronized (notes) {
|
||||
List<Note> noteList = new ArrayList<>(notes.values());
|
||||
List<Note> noteList = getAuthorizedNotes(subject);
|
||||
Collections.sort(noteList, new Comparator<Note>() {
|
||||
@Override
|
||||
public int compare(Note note1, Note note2) {
|
||||
|
|
@ -534,7 +598,7 @@ public class Notebook implements NoteEventListener {
|
|||
return noteList;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public List<Note> getAllNotes(AuthenticationInfo subject) {
|
||||
final Set<String> entities = Sets.newHashSet();
|
||||
if (subject != null) {
|
||||
|
|
@ -563,7 +627,7 @@ public class Notebook implements NoteEventListener {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
private Map<String, Object> getParagraphForJobManagerItem(Paragraph paragraph) {
|
||||
Map<String, Object> paragraphItem = new HashMap<>();
|
||||
|
||||
|
|
@ -696,7 +760,7 @@ public class Notebook implements NoteEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
List<Note> notes = getAllNotes();
|
||||
List<Note> notes = getAllNotes(subject);
|
||||
List<Map<String, Object>> notesInfo = new LinkedList<>();
|
||||
for (Note note : notes) {
|
||||
boolean isNotebookRunning = false;
|
||||
|
|
|
|||
|
|
@ -135,12 +135,15 @@ public class NotebookTest implements JobListenerFactory{
|
|||
File destDir = new File(notebookDir.getAbsolutePath() + "/2A94M5J1Z");
|
||||
FileUtils.copyDirectory(srcDir, destDir);
|
||||
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
|
||||
// when load
|
||||
notebook.reloadAllNotes(null);
|
||||
assertEquals(1, notebook.getAllNotes().size());
|
||||
assertEquals(1, notebook.getAllNotes(subject).size());
|
||||
|
||||
// then interpreter factory should be injected into all the paragraphs
|
||||
Note note = notebook.getAllNotes().get(0);
|
||||
Note note = notebook.getAllNotes(subject).get(0);
|
||||
assertNull(note.getParagraphs().get(0).getRepl(null));
|
||||
}
|
||||
|
||||
|
|
@ -163,14 +166,17 @@ public class NotebookTest implements JobListenerFactory{
|
|||
logger.error(e.toString(), e);
|
||||
}
|
||||
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
|
||||
// doesn't have copied notebook in memory before reloading
|
||||
List<Note> notes = notebook.getAllNotes();
|
||||
List<Note> notes = notebook.getAllNotes(subject);
|
||||
assertEquals(notes.size(), 0);
|
||||
|
||||
// load copied notebook on memory when reloadAllNotes() is called
|
||||
Note copiedNote = notebookRepo.get("2A94M5J1Z", null);
|
||||
notebook.reloadAllNotes(null);
|
||||
notes = notebook.getAllNotes();
|
||||
notes = notebook.getAllNotes(subject);
|
||||
assertEquals(notes.size(), 2);
|
||||
assertEquals(notes.get(1).getId(), copiedNote.getId());
|
||||
assertEquals(notes.get(1).getName(), copiedNote.getName());
|
||||
|
|
@ -183,15 +189,52 @@ public class NotebookTest implements JobListenerFactory{
|
|||
}
|
||||
|
||||
// keep notebook in memory before reloading
|
||||
notes = notebook.getAllNotes();
|
||||
notes = notebook.getAllNotes(subject);
|
||||
assertEquals(notes.size(), 2);
|
||||
|
||||
// delete notebook from notebook list when reloadAllNotes() is called
|
||||
notebook.reloadAllNotes(null);
|
||||
notes = notebook.getAllNotes();
|
||||
notes = notebook.getAllNotes(subject);
|
||||
assertEquals(notes.size(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReloadAuthorizedNotes() throws IOException {
|
||||
AuthenticationInfo user1 = new AuthenticationInfo("user1");
|
||||
AuthenticationInfo user2 = new AuthenticationInfo("user2");
|
||||
notebook.reloadAllNotes(user1);
|
||||
List<Note> notes1 = notebook.getAllNotes(user1);
|
||||
notebook.reloadAllNotes(user2);
|
||||
List<Note> notes2 = notebook.getAllNotes(user2);
|
||||
assertEquals(notes1.size(), 0);
|
||||
assertEquals(notes2.size(), 0);
|
||||
logger.info("Loaded {} notes", notes1.size());
|
||||
|
||||
Note note = notebook.createNote(user1);
|
||||
setNotePermissions(note.id(), user1.getUser(), true, true, true);
|
||||
notebook.reloadAllNotes(user1);
|
||||
notes1 = notebook.getAllNotes(user1);
|
||||
notebook.reloadAllNotes(user2);
|
||||
notes2 = notebook.getAllNotes(user2);
|
||||
assertEquals(notes1.size(), 1);
|
||||
assertEquals(notes2.size(), 0);
|
||||
}
|
||||
|
||||
//fails if all failed, otherwise true
|
||||
private boolean setNotePermissions(String noteId, String user, boolean isOwner, boolean isReader, boolean isWriter) {
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
Set<String> owners = notebookAuthorization.getOwners(noteId);
|
||||
Set<String> readers = notebookAuthorization.getReaders(noteId);
|
||||
Set<String> writers = notebookAuthorization.getWriters(noteId);
|
||||
boolean ownerSet = isOwner ? owners.add(user) : owners.remove(user);
|
||||
boolean readerSet = isReader ? readers.add(user) : readers.remove(user);
|
||||
boolean writerSet = isWriter ? writers.add(user) : writers.remove(user);
|
||||
notebookAuthorization.setOwners(noteId, owners);
|
||||
notebookAuthorization.setReaders(noteId, readers);
|
||||
notebookAuthorization.setWriters(noteId, writers);
|
||||
return ownerSet || readerSet || writerSet;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersist() throws IOException, SchedulerException, RepositoryException {
|
||||
Note note = notebook.createNote(null);
|
||||
|
|
@ -207,7 +250,9 @@ public class NotebookTest implements JobListenerFactory{
|
|||
Notebook notebook2 = new Notebook(
|
||||
conf, notebookRepo, schedulerFactory,
|
||||
new InterpreterFactory(conf, null, null, null, depResolver), this, null, null, null);
|
||||
assertEquals(1, notebook2.getAllNotes().size());
|
||||
//TODO(khalid): anonymous or specific user notes?
|
||||
AuthenticationInfo subject = new AuthenticationInfo("anonymous");
|
||||
assertEquals(1, notebook2.getAllNotes(subject).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in a new issue