This is an automated email from the ASF dual-hosted git repository.

pdallig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new 2afa0ddd20 [ZEPPELIN-5750] Add tests for NoteAuth and polish up 
NoteAuth (#4378)
2afa0ddd20 is described below

commit 2afa0ddd20dc33a4eedce31b1d69afb6bd52c9b4
Author: Philipp Dallig <philipp.dal...@gmail.com>
AuthorDate: Thu Jun 9 15:30:23 2022 +0200

    [ZEPPELIN-5750] Add tests for NoteAuth and polish up NoteAuth (#4378)
---
 .../org/apache/zeppelin/rest/NotebookRestApi.java  |   4 +-
 .../service/ShiroAuthenticationServiceTest.java    |  13 +-
 .../zeppelin/notebook/AuthorizationService.java    |  20 ++-
 .../org/apache/zeppelin/notebook/NoteAuth.java     |  39 +++---
 .../org/apache/zeppelin/notebook/Notebook.java     |   2 +-
 .../notebook/NotebookAuthorizationInfoSaving.java  |   7 +-
 .../org/apache/zeppelin/notebook/Paragraph.java    |   2 +-
 .../org/apache/zeppelin/notebook/NoteAuthTest.java | 153 +++++++++++++++++++++
 8 files changed, 197 insertions(+), 43 deletions(-)

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 88004f480b..305b5588cd 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
@@ -295,7 +295,7 @@ public class NotebookRestApi extends AbstractRestApi {
                 authorizationService.getReaders(noteId), 
authorizationService.getRunners(noteId),
                 authorizationService.getWriters(noteId));
         AuthenticationInfo subject = new 
AuthenticationInfo(authenticationService.getPrincipal());
-        authorizationService.saveNoteAuth(noteId, subject);
+        authorizationService.saveNoteAuth();
         notebookServer.broadcastNote(note);
         notebookServer.broadcastNoteList(subject, userAndRoles);
         return new JsonResponse<>(Status.OK).build();
@@ -353,7 +353,7 @@ public class NotebookRestApi extends AbstractRestApi {
 
   /**
    * Save a revision for the a note
-   * 
+   *
    * @param message
    * @param noteId
    * @return
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/service/ShiroAuthenticationServiceTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/service/ShiroAuthenticationServiceTest.java
index 5ce009ae20..47af1131ab 100644
--- 
a/zeppelin-server/src/test/java/org/apache/zeppelin/service/ShiroAuthenticationServiceTest.java
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/service/ShiroAuthenticationServiceTest.java
@@ -26,7 +26,6 @@ import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.shiro.mgt.DefaultSecurityManager;
-import org.apache.shiro.subject.SimplePrincipalCollection;
 import org.apache.shiro.util.LifecycleUtils;
 import org.apache.shiro.util.ThreadContext;
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
@@ -80,15 +79,15 @@ public class ShiroAuthenticationServiceTest {
 
     KnoxJwtRealm realm = spy(new KnoxJwtRealm());
     LifecycleUtils.init(realm);
-    Set<String> testRoles = new HashSet<String>(){{
-        add("role1");
-        add("role2");
-    }};
+    Set<String> testRoles = new HashSet<String>();
+    testRoles.add("role1");
+    testRoles.add("role2");
+
     when(realm.mapGroupPrincipals("test")).thenReturn(testRoles);
-    
+
     DefaultSecurityManager securityManager = new DefaultSecurityManager(realm);
     ThreadContext.bind(securityManager);
-    
+
     Set<String> roles = shiroSecurityService.getAssociatedRoles();
     assertEquals(testRoles, roles);
   }
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/AuthorizationService.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/AuthorizationService.java
index 6cb7c071f5..2b50ec01a5 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/AuthorizationService.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/AuthorizationService.java
@@ -64,17 +64,17 @@ public class AuthorizationService implements 
ClusterEventListener {
       // init notesAuth by reading notebook-authorization.json
       NotebookAuthorizationInfoSaving authorizationInfoSaving = 
configStorage.loadNotebookAuthorization();
       if (authorizationInfoSaving != null) {
-        for (Map.Entry<String, Map<String, Set<String>>> entry : 
authorizationInfoSaving.authInfo.entrySet()) {
+        for (Map.Entry<String, Map<String, Set<String>>> entry : 
authorizationInfoSaving.getAuthInfo().entrySet()) {
           String noteId = entry.getKey();
           Map<String, Set<String>> permissions = entry.getValue();
-          notesAuth.put(noteId, new NoteAuth(noteId, permissions));
+          notesAuth.put(noteId, new NoteAuth(noteId, permissions, conf));
         }
       }
 
       // initialize NoteAuth for the notes without permission set explicitly.
       for (String noteId : noteManager.getNotesInfo().keySet()) {
         if (!notesAuth.containsKey(noteId)) {
-          notesAuth.put(noteId, new NoteAuth(noteId));
+          notesAuth.put(noteId, new NoteAuth(noteId, conf));
         }
       }
     } catch (IOException e) {
@@ -89,28 +89,26 @@ public class AuthorizationService implements 
ClusterEventListener {
    * @param subject
    * @throws IOException
    */
-  public void createNoteAuth(String noteId, AuthenticationInfo subject) throws 
IOException {
-    NoteAuth noteAuth =  new NoteAuth(noteId, subject);
+  public void createNoteAuth(String noteId, AuthenticationInfo subject) {
+    NoteAuth noteAuth = new NoteAuth(noteId, subject, conf);
     this.notesAuth.put(noteId, noteAuth);
   }
 
-  public void cloneNoteMeta(String noteId, String sourceNoteId, 
AuthenticationInfo subject) throws IOException {
-    NoteAuth noteAuth =  new NoteAuth(noteId, subject);
+  public void cloneNoteMeta(String noteId, String sourceNoteId, 
AuthenticationInfo subject) {
+    NoteAuth noteAuth = new NoteAuth(noteId, subject, conf);
     this.notesAuth.put(noteId, noteAuth);
   }
 
   /**
    * Persistent NoteAuth
    *
-   * @param noteId
-   * @param subject
    * @throws IOException
    */
-  public void saveNoteAuth(String noteId, AuthenticationInfo subject) throws 
IOException {
+  public void saveNoteAuth() throws IOException {
     configStorage.save(new NotebookAuthorizationInfoSaving(this.notesAuth));
   }
 
-  public void removeNoteAuth(String noteId) throws IOException {
+  public void removeNoteAuth(String noteId) {
     this.notesAuth.remove(noteId);
   }
 
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteAuth.java 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteAuth.java
index 7023b790f6..1840046b36 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteAuth.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteAuth.java
@@ -17,8 +17,6 @@
 
 package org.apache.zeppelin.notebook;
 
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
 import org.apache.zeppelin.user.AuthenticationInfo;
 
@@ -33,25 +31,35 @@ import java.util.Set;
  */
 public class NoteAuth {
 
-  private static Gson gson = new GsonBuilder().setPrettyPrinting().create();
+  private final String noteId;
+  private final ZeppelinConfiguration zconf;
 
-  private String noteId;
   private Set<String> readers = new HashSet<>();
   private Set<String> writers = new HashSet<>();
   private Set<String> runners = new HashSet<>();
   private Set<String> owners = new HashSet<>();
 
-  public NoteAuth(String noteId) {
-    this(noteId, AuthenticationInfo.ANONYMOUS);
+  public NoteAuth(String noteId, ZeppelinConfiguration zconf) {
+    this(noteId, AuthenticationInfo.ANONYMOUS, zconf);
   }
 
-  public NoteAuth(String noteId, AuthenticationInfo subject) {
+  public NoteAuth(String noteId, AuthenticationInfo subject, 
ZeppelinConfiguration zconf) {
     this.noteId = noteId;
+    this.zconf = zconf;
     initPermissions(subject);
   }
 
-  public NoteAuth(String noteId, Map<String, Set<String>> permissions) {
+  /**
+   * Creates a NoteAuth from a map loaded from notebook-authorization.json. At 
this point it is not possible to distinguish
+   * between a user and a group string, so checkCaseAndConvert must not be 
used.
+   *
+   * @param noteId
+   * @param permissions
+   * @param zconf
+   */
+  public NoteAuth(String noteId, Map<String, Set<String>> permissions, 
ZeppelinConfiguration zconf) {
     this.noteId = noteId;
+    this.zconf = zconf;
     this.readers = permissions.getOrDefault("readers", new HashSet<>());
     this.writers = permissions.getOrDefault("writers", new HashSet<>());
     this.runners = permissions.getOrDefault("runners", new HashSet<>());
@@ -61,7 +69,7 @@ public class NoteAuth {
   // used when creating new note
   public void initPermissions(AuthenticationInfo subject) {
     if (!AuthenticationInfo.isAnonymous(subject)) {
-      if (ZeppelinConfiguration.create().isNotebookPublic()) {
+      if (zconf.isNotebookPublic()) {
         // add current user to owners - can be public
         this.owners.add(checkCaseAndConvert(subject.getUser()));
       } else {
@@ -114,7 +122,7 @@ public class NoteAuth {
    * If case conversion is enforced, then change entity names to lower case
    */
   private Set<String> checkCaseAndConvert(Set<String> entities) {
-    if (ZeppelinConfiguration.create().isUsernameForceLowerCase()) {
+    if (zconf.isUsernameForceLowerCase()) {
       Set<String> set2 = new HashSet<>();
       for (String name : entities) {
         set2.add(name.toLowerCase());
@@ -126,7 +134,7 @@ public class NoteAuth {
   }
 
   private String checkCaseAndConvert(String entity) {
-    if (ZeppelinConfiguration.create().isUsernameForceLowerCase()) {
+    if (zconf.isUsernameForceLowerCase()) {
       return entity.toLowerCase();
     } else {
       return entity;
@@ -141,13 +149,4 @@ public class NoteAuth {
     map.put("owners", owners);
     return map;
   }
-
-  public String toJson() {
-    return gson.toJson(this);
-  }
-
-  public static NoteAuth fromJson(String json) {
-    return gson.fromJson(json, NoteAuth.class);
-  }
-
 }
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java
index ad285cce81..1081c4df03 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java
@@ -246,7 +246,7 @@ public class Notebook {
     noteManager.addNote(note, subject);
     // init noteMeta
     authorizationService.createNoteAuth(note.getId(), subject);
-    authorizationService.saveNoteAuth(note.getId(), subject);
+    authorizationService.saveNoteAuth();
     if (save) {
       noteManager.saveNote(note, subject);
     }
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookAuthorizationInfoSaving.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookAuthorizationInfoSaving.java
index 338a0f2356..6440fa4a97 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookAuthorizationInfoSaving.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NotebookAuthorizationInfoSaving.java
@@ -32,7 +32,7 @@ public class NotebookAuthorizationInfoSaving implements 
JsonSerializable {
 
   private static final Gson gson = new 
GsonBuilder().setPrettyPrinting().create();
 
-  public Map<String, Map<String, Set<String>>> authInfo;
+  private final Map<String, Map<String, Set<String>>> authInfo;
 
   public NotebookAuthorizationInfoSaving(Map<String, NoteAuth> notesAuth) {
     this.authInfo = new HashMap<>();
@@ -41,6 +41,11 @@ public class NotebookAuthorizationInfoSaving implements 
JsonSerializable {
     }
   }
 
+  public Map<String, Map<String, Set<String>>> getAuthInfo() {
+    return authInfo;
+  }
+
+  @Override
   public String toJson() {
     return gson.toJson(this);
   }
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
index bf7b02f0b6..2fd7b1668c 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
@@ -408,7 +408,7 @@ public class Paragraph extends 
JobWithProgressPoller<InterpreterResult> implemen
       }
       this.interpreter = getBindedInterpreter();
       if (this.interpreter == null) {
-        LOGGER.error("Can not find interpreter name " + intpText);
+        LOGGER.error("Can not find interpreter name {}", intpText);
         throw new RuntimeException("Can not find interpreter for " + intpText);
       }
       LOGGER.info("Run paragraph [paragraph_id: {}, interpreter: {}, note_id: 
{}, user: {}]",
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteAuthTest.java 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteAuthTest.java
new file mode 100644
index 0000000000..9536e21c3a
--- /dev/null
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteAuthTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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 org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.apache.zeppelin.user.AuthenticationInfo;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class NoteAuthTest {
+  private ZeppelinConfiguration conf = mock(ZeppelinConfiguration.class);
+
+  @Test
+  public void testAnonymous() {
+    NoteAuth auth = new NoteAuth("note1", conf);
+    assertEquals(0, auth.getOwners().size());
+    assertEquals(0, auth.getReaders().size());
+    assertEquals(0, auth.getRunners().size());
+    assertEquals(0, auth.getWriters().size());
+  }
+
+  @Test
+  public void testPublicNotes() {
+
+    when(conf.isNotebookPublic()).thenReturn(true);
+
+    NoteAuth auth = new NoteAuth("note1", new AuthenticationInfo("TestUser"), 
conf);
+    assertEquals("note1", auth.getNoteId());
+    assertEquals(1, auth.getOwners().size());
+    assertTrue(auth.getOwners().contains("TestUser"));
+
+    assertEquals(0, auth.getReaders().size());
+    assertEquals(0, auth.getRunners().size());
+    assertEquals(0, auth.getWriters().size());
+
+    /*
+     * simple Map check
+     */
+    assertEquals(4, auth.toMap().size());
+    assertTrue(auth.toMap().get("owners").contains("TestUser"));
+    assertTrue(auth.toMap().get("readers").isEmpty());
+    assertTrue(auth.toMap().get("runners").isEmpty());
+    assertTrue(auth.toMap().get("writers").isEmpty());
+  }
+
+  @Test
+  public void testNoPublicNotes() {
+
+    when(conf.isNotebookPublic()).thenReturn(false);
+
+    NoteAuth auth = new NoteAuth("note1", new AuthenticationInfo("TestUser"), 
conf);
+    assertEquals(1, auth.getOwners().size());
+    assertTrue(auth.getOwners().contains("TestUser"));
+
+    assertEquals(1, auth.getReaders().size());
+    assertTrue(auth.getReaders().contains("TestUser"));
+
+    assertEquals(1, auth.getRunners().size());
+    assertTrue(auth.getRunners().contains("TestUser"));
+
+    assertEquals(1, auth.getWriters().size());
+    assertTrue(auth.getWriters().contains("TestUser"));
+
+    /*
+     * simple Map check
+     */
+    assertEquals(4, auth.toMap().size());
+    assertTrue(auth.toMap().get("owners").contains("TestUser"));
+    assertTrue(auth.toMap().get("readers").contains("TestUser"));
+    assertTrue(auth.toMap().get("runners").contains("TestUser"));
+    assertTrue(auth.toMap().get("writers").contains("TestUser"));
+  }
+
+  @Test
+  public void testFoceLowerCaseUsers() {
+
+    when(conf.isNotebookPublic()).thenReturn(false);
+    when(conf.isUsernameForceLowerCase()).thenReturn(true);
+
+    NoteAuth auth = new NoteAuth("note1", new AuthenticationInfo("TestUser"), 
conf);
+    assertEquals(1, auth.getOwners().size());
+    assertTrue(auth.getOwners().contains("testuser"));
+
+    assertEquals(1, auth.getReaders().size());
+    assertTrue(auth.getReaders().contains("testuser"));
+
+    assertEquals(1, auth.getRunners().size());
+    assertTrue(auth.getRunners().contains("testuser"));
+
+    assertEquals(1, auth.getWriters().size());
+    assertTrue(auth.getWriters().contains("testuser"));
+  }
+
+  @Test
+  public void testMapConstructor() {
+    when(conf.isNotebookPublic()).thenReturn(false);
+
+    NoteAuth auth = new NoteAuth("note1", getTestMap("TestUser", "TestGroup"), 
conf);
+    assertEquals(2, auth.getOwners().size());
+    assertTrue(auth.getOwners().contains("TestUser"));
+    assertTrue(auth.getOwners().contains("TestGroup"));
+
+    assertEquals(2, auth.getReaders().size());
+    assertTrue(auth.getReaders().contains("TestUser"));
+    assertTrue(auth.getRunners().contains("TestGroup"));
+
+    assertEquals(2, auth.getRunners().size());
+    assertTrue(auth.getRunners().contains("TestUser"));
+    assertTrue(auth.getRunners().contains("TestGroup"));
+
+    assertEquals(2, auth.getWriters().size());
+    assertTrue(auth.getWriters().contains("TestUser"));
+    assertTrue(auth.getWriters().contains("TestGroup"));
+  }
+
+  private static Map<String, Set<String>> getTestMap(String user, String 
group) {
+    Map<String, Set<String>> map = new HashMap<>();
+    Set<String> readers = new HashSet<String>();
+    readers.add(user);
+    readers.add(group);
+    Set<String> writers = new HashSet<String>(readers);
+    Set<String> runners = new HashSet<String>(readers);
+    Set<String> owners = new HashSet<String>(readers);
+    map.put("readers", readers);
+    map.put("writers", writers);
+    map.put("runners", runners);
+    map.put("owners", owners);
+    return map;
+  }
+}

Reply via email to