mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Added new type of user
This commit is contained in:
parent
71d1305216
commit
5c43ca957a
12 changed files with 195 additions and 31 deletions
|
|
@ -36,13 +36,15 @@ As you can see, each Zeppelin notebooks has 3 entities :
|
|||
* Owners ( users or groups )
|
||||
* Readers ( users or groups )
|
||||
* Writers ( users or groups )
|
||||
* Runners ( users or groups )
|
||||
|
||||
<center><img src="{{BASE_PATH}}/assets/themes/zeppelin/img/docs-img/permission_setting.png"></center>
|
||||
|
||||
Fill out the each forms with comma seperated **users** and **groups** configured in `conf/shiro.ini` file.
|
||||
If the form is empty (*), it means that any users can perform that operation.
|
||||
|
||||
If someone who doesn't have **read** permission is trying to access the notebook or someone who doesn't have **write** permission is trying to edit the notebook, Zeppelin will ask to login or block the user.
|
||||
If someone who doesn't have **read** permission is trying to access the notebook or someone who doesn't have **write** permission is trying to edit the notebook,
|
||||
or someone who doesn't have **run** permission is trying to run a paragraph Zeppelin will ask to login or block the user.
|
||||
|
||||
<center><img src="{{BASE_PATH}}/assets/themes/zeppelin/img/docs-img/insufficient_privileges.png"></center>
|
||||
|
||||
|
|
@ -63,13 +65,13 @@ or set `zeppelin.notebook.public` property to `false` in `conf/zeppelin-site.xml
|
|||
</property>
|
||||
```
|
||||
|
||||
Behind the scenes, when you create a new note only the `owners` field is filled with current user, leaving `readers` and `writers` fields empty. All the notes with at least one empty authorization field are considered to be in `public` workspace. Thus when setting `zeppelin.notebook.public` (or corresponding `ZEPPELIN_NOTEBOOK_PUBLIC`) to false, newly created notes have `readers` and `writers` fields filled with current user, making note appear as in `private` workspace.
|
||||
Behind the scenes, when you create a new note only the `owners` field is filled with current user, leaving `readers`, `runners` and `writers` fields empty. All the notes with at least one empty authorization field are considered to be in `public` workspace. Thus when setting `zeppelin.notebook.public` (or corresponding `ZEPPELIN_NOTEBOOK_PUBLIC`) to false, newly created notes have `readers`, `runners`, `writers` fields filled with current user, making note appear as in `private` workspace.
|
||||
|
||||
## How it works
|
||||
In this section, we will explain the detail about how the notebook authorization works in backend side.
|
||||
|
||||
### NotebookServer
|
||||
The [NotebookServer](https://github.com/apache/zeppelin/blob/master/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java) classifies every notebook operations into three categories: **Read**, **Write**, **Manage**.
|
||||
The [NotebookServer](https://github.com/apache/zeppelin/blob/master/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java) classifies every notebook operations into three categories: **Read**, **Run**, **Write**, **Manage**.
|
||||
Before executing a notebook operation, it checks if the user and the groups associated with the `NotebookSocket` have permissions.
|
||||
For example, before executing a **Read** operation, it checks if the user and the groups have at least one entity that belongs to the **Reader** entities.
|
||||
|
||||
|
|
|
|||
|
|
@ -1215,6 +1215,9 @@ Notebooks REST API supports the following operations: List, Create, Get, Delete,
|
|||
"owners":[
|
||||
"user1"
|
||||
],
|
||||
"runners":[
|
||||
"user2"
|
||||
],
|
||||
"writers":[
|
||||
"user2"
|
||||
]
|
||||
|
|
@ -1259,6 +1262,9 @@ Notebooks REST API supports the following operations: List, Create, Get, Delete,
|
|||
"owners": [
|
||||
"user2"
|
||||
],
|
||||
"runners":[
|
||||
"user2"
|
||||
],
|
||||
"writers": [
|
||||
"user1"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ public class NotebookRestApi {
|
|||
permissionsMap.put("owners", notebookAuthorization.getOwners(noteId));
|
||||
permissionsMap.put("readers", notebookAuthorization.getReaders(noteId));
|
||||
permissionsMap.put("writers", notebookAuthorization.getWriters(noteId));
|
||||
permissionsMap.put("runners", notebookAuthorization.getRunners(noteId));
|
||||
return new JsonResponse<>(Status.OK, "", permissionsMap).build();
|
||||
}
|
||||
|
||||
|
|
@ -165,6 +166,18 @@ public class NotebookRestApi {
|
|||
throw new ForbiddenException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user can run the given note.
|
||||
*/
|
||||
private void checkIfUserCanRun(String noteId, String errorMsg) {
|
||||
Set<String> userAndRoles = Sets.newHashSet();
|
||||
userAndRoles.add(SecurityUtils.getPrincipal());
|
||||
userAndRoles.addAll(SecurityUtils.getRoles());
|
||||
if (!notebookAuthorization.hasRunAuthorization(userAndRoles, noteId)) {
|
||||
throw new ForbiddenException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIfNoteIsNotNull(Note note) {
|
||||
if (note == null) {
|
||||
|
|
@ -199,15 +212,31 @@ public class NotebookRestApi {
|
|||
HashMap<String, HashSet<String>> permMap =
|
||||
gson.fromJson(req, new TypeToken<HashMap<String, HashSet<String>>>() {}.getType());
|
||||
Note note = notebook.getNote(noteId);
|
||||
|
||||
LOG.info("Set permissions {} {} {} {} {}", noteId, principal, permMap.get("owners"),
|
||||
permMap.get("readers"), permMap.get("writers"));
|
||||
|
||||
LOG.info("Set permissions {} {} {} {} {} {}", noteId, principal, permMap.get("owners"),
|
||||
permMap.get("readers"), permMap.get("runners"), permMap.get("writers"));
|
||||
|
||||
HashSet<String> readers = permMap.get("readers");
|
||||
HashSet<String> runners = permMap.get("runners");
|
||||
HashSet<String> owners = permMap.get("owners");
|
||||
HashSet<String> writers = permMap.get("writers");
|
||||
// Set readers, if writers and owners is empty -> set to user requesting the change
|
||||
// Set readers, if runners, writers and owners is empty -> set to user requesting the change
|
||||
if (readers != null && !readers.isEmpty()) {
|
||||
if (runners.isEmpty()) {
|
||||
runners = Sets.newHashSet(SecurityUtils.getPrincipal());
|
||||
}
|
||||
if (writers.isEmpty()) {
|
||||
writers = Sets.newHashSet(SecurityUtils.getPrincipal());
|
||||
}
|
||||
if (owners.isEmpty()) {
|
||||
owners = Sets.newHashSet(SecurityUtils.getPrincipal());
|
||||
}
|
||||
}
|
||||
// Set runners, if writers and owners is empty -> set to user requesting the change
|
||||
if (runners != null && !runners.isEmpty()) {
|
||||
if (writers.isEmpty()) {
|
||||
writers = Sets.newHashSet(SecurityUtils.getPrincipal());
|
||||
}
|
||||
if (owners.isEmpty()) {
|
||||
owners = Sets.newHashSet(SecurityUtils.getPrincipal());
|
||||
}
|
||||
|
|
@ -220,10 +249,12 @@ public class NotebookRestApi {
|
|||
}
|
||||
|
||||
notebookAuthorization.setReaders(noteId, readers);
|
||||
notebookAuthorization.setRunners(noteId, runners);
|
||||
notebookAuthorization.setWriters(noteId, writers);
|
||||
notebookAuthorization.setOwners(noteId, owners);
|
||||
LOG.debug("After set permissions {} {} {}", notebookAuthorization.getOwners(noteId),
|
||||
notebookAuthorization.getReaders(noteId), notebookAuthorization.getWriters(noteId));
|
||||
LOG.debug("After set permissions {} {} {} {}", notebookAuthorization.getOwners(noteId),
|
||||
notebookAuthorization.getReaders(noteId), notebookAuthorization.getRunners(noteId),
|
||||
notebookAuthorization.getWriters(noteId));
|
||||
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
|
||||
note.persist(subject);
|
||||
notebookServer.broadcastNote(note);
|
||||
|
|
@ -589,7 +620,7 @@ public class NotebookRestApi {
|
|||
Note note = notebook.getNote(noteId);
|
||||
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
|
||||
checkIfNoteIsNotNull(note);
|
||||
checkIfUserCanWrite(noteId, "Insufficient privileges you cannot run job for this note");
|
||||
checkIfUserCanRun(noteId, "Insufficient privileges you cannot run job for this note");
|
||||
|
||||
try {
|
||||
note.runAll(subject);
|
||||
|
|
@ -616,7 +647,7 @@ public class NotebookRestApi {
|
|||
LOG.info("stop note jobs {} ", noteId);
|
||||
Note note = notebook.getNote(noteId);
|
||||
checkIfNoteIsNotNull(note);
|
||||
checkIfUserCanWrite(noteId, "Insufficient privileges you cannot stop this job for this note");
|
||||
checkIfUserCanRun(noteId, "Insufficient privileges you cannot stop this job for this note");
|
||||
|
||||
for (Paragraph p : note.getParagraphs()) {
|
||||
if (!p.isTerminated()) {
|
||||
|
|
@ -690,7 +721,7 @@ public class NotebookRestApi {
|
|||
|
||||
Note note = notebook.getNote(noteId);
|
||||
checkIfNoteIsNotNull(note);
|
||||
checkIfUserCanWrite(noteId, "Insufficient privileges you cannot run job for this note");
|
||||
checkIfUserCanRun(noteId, "Insufficient privileges you cannot run job for this note");
|
||||
Paragraph paragraph = note.getParagraph(paragraphId);
|
||||
checkIfParagraphIsNotNull(paragraph);
|
||||
|
||||
|
|
@ -728,7 +759,7 @@ public class NotebookRestApi {
|
|||
|
||||
Note note = notebook.getNote(noteId);
|
||||
checkIfNoteIsNotNull(note);
|
||||
checkIfUserCanWrite(noteId, "Insufficient privileges you cannot run paragraph");
|
||||
checkIfUserCanRun(noteId, "Insufficient privileges you cannot run paragraph");
|
||||
Paragraph paragraph = note.getParagraph(paragraphId);
|
||||
checkIfParagraphIsNotNull(paragraph);
|
||||
|
||||
|
|
@ -766,7 +797,7 @@ public class NotebookRestApi {
|
|||
LOG.info("stop paragraph job {} ", noteId);
|
||||
Note note = notebook.getNote(noteId);
|
||||
checkIfNoteIsNotNull(note);
|
||||
checkIfUserCanWrite(noteId, "Insufficient privileges you cannot stop paragraph");
|
||||
checkIfUserCanRun(noteId, "Insufficient privileges you cannot stop paragraph");
|
||||
Paragraph p = note.getParagraph(paragraphId);
|
||||
checkIfParagraphIsNotNull(p);
|
||||
p.abort();
|
||||
|
|
@ -791,7 +822,7 @@ public class NotebookRestApi {
|
|||
|
||||
Note note = notebook.getNote(noteId);
|
||||
checkIfNoteIsNotNull(note);
|
||||
checkIfUserCanWrite(noteId, "Insufficient privileges you cannot set a cron job for this note");
|
||||
checkIfUserCanRun(noteId, "Insufficient privileges you cannot set a cron job for this note");
|
||||
|
||||
if (!CronExpression.isValidExpression(request.getCronString())) {
|
||||
return new JsonResponse<>(Status.BAD_REQUEST, "wrong cron expressions.").build();
|
||||
|
|
@ -922,7 +953,8 @@ public class NotebookRestApi {
|
|||
String noteId = Id[0];
|
||||
if (!notebookAuthorization.isOwner(noteId, userAndRoles) &&
|
||||
!notebookAuthorization.isReader(noteId, userAndRoles) &&
|
||||
!notebookAuthorization.isWriter(noteId, userAndRoles)) {
|
||||
!notebookAuthorization.isWriter(noteId, userAndRoles) &&
|
||||
!notebookAuthorization.isRunner(noteId, userAndRoles)) {
|
||||
notesFound.remove(i);
|
||||
i--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -751,6 +751,25 @@ public class NotebookServer extends WebSocketServlet
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false if user doesn't have runner permission for this paragraph
|
||||
*/
|
||||
private boolean hasParagraphRunnerPermission(NotebookSocket conn,
|
||||
Notebook notebook, String noteId,
|
||||
HashSet<String> userAndRoles,
|
||||
String principal, String op)
|
||||
throws IOException {
|
||||
|
||||
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
|
||||
if (!notebookAuthorization.isRunner(noteId, userAndRoles)) {
|
||||
permissionError(conn, op, principal, userAndRoles,
|
||||
notebookAuthorization.getOwners(noteId));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false if user doesn't have writer permission for this paragraph
|
||||
*/
|
||||
|
|
@ -1618,7 +1637,7 @@ public class NotebookServer extends WebSocketServlet
|
|||
|
||||
String noteId = getOpenNoteId(conn);
|
||||
|
||||
if (!hasParagraphWriterPermission(conn, notebook, noteId,
|
||||
if (!hasParagraphRunnerPermission(conn, notebook, noteId,
|
||||
userAndRoles, fromMessage.principal, "write")) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1636,7 +1655,7 @@ public class NotebookServer extends WebSocketServlet
|
|||
return;
|
||||
}
|
||||
|
||||
if (!hasParagraphWriterPermission(conn, notebook, noteId,
|
||||
if (!hasParagraphRunnerPermission(conn, notebook, noteId,
|
||||
userAndRoles, fromMessage.principal, "run all paragraphs")) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1729,7 +1748,7 @@ public class NotebookServer extends WebSocketServlet
|
|||
|
||||
String noteId = getOpenNoteId(conn);
|
||||
|
||||
if (!hasParagraphWriterPermission(conn, notebook, noteId,
|
||||
if (!hasParagraphRunnerPermission(conn, notebook, noteId,
|
||||
userAndRoles, fromMessage.principal, "write")) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -2057,7 +2076,7 @@ public class NotebookServer extends WebSocketServlet
|
|||
Set<String> userAndRoles = Sets.newHashSet();
|
||||
userAndRoles.add(SecurityUtils.getPrincipal());
|
||||
userAndRoles.addAll(SecurityUtils.getRoles());
|
||||
if (!notebookIns.getNotebookAuthorization().hasWriteAuthorization(userAndRoles, noteId)) {
|
||||
if (!notebookIns.getNotebookAuthorization().hasRunAuthorization(userAndRoles, noteId)) {
|
||||
throw new ForbiddenException(String.format("can't execute note %s", noteId));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -200,6 +200,8 @@ public class AuthenticationIT extends AbstractZeppelinIT {
|
|||
MAX_BROWSER_TIMEOUT_SEC).sendKeys("finance ");
|
||||
pollingWait(By.xpath(".//*[@id='selectReaders']/following::span//input"),
|
||||
MAX_BROWSER_TIMEOUT_SEC).sendKeys("finance ");
|
||||
pollingWait(By.xpath(".//*[@id='selectRunners']/following::span//input"),
|
||||
MAX_BROWSER_TIMEOUT_SEC).sendKeys("finance ");
|
||||
pollingWait(By.xpath(".//*[@id='selectWriters']/following::span//input"),
|
||||
MAX_BROWSER_TIMEOUT_SEC).sendKeys("finance ");
|
||||
pollingWait(By.xpath("//button[@ng-click='savePermissions()']"), MAX_BROWSER_TIMEOUT_SEC)
|
||||
|
|
|
|||
|
|
@ -700,6 +700,7 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
|
|||
$scope.setIamOwner()
|
||||
angular.element('#selectOwners').select2(selectJson)
|
||||
angular.element('#selectReaders').select2(selectJson)
|
||||
angular.element('#selectRunners').select2(selectJson)
|
||||
angular.element('#selectWriters').select2(selectJson)
|
||||
if (callback) {
|
||||
callback()
|
||||
|
|
@ -739,6 +740,7 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
|
|||
function convertPermissionsToArray () {
|
||||
$scope.permissions.owners = angular.element('#selectOwners').val()
|
||||
$scope.permissions.readers = angular.element('#selectReaders').val()
|
||||
$scope.permissions.runners = angular.element('#selectRunners').val()
|
||||
$scope.permissions.writers = angular.element('#selectWriters').val()
|
||||
angular.element('.permissionsForm select').find('option:not([is-select2="false"])').remove()
|
||||
}
|
||||
|
|
@ -1017,7 +1019,8 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
|
|||
closable: true,
|
||||
title: 'Permissions Saved Successfully',
|
||||
message: 'Owners : ' + $scope.permissions.owners + '\n\n' + 'Readers : ' +
|
||||
$scope.permissions.readers + '\n\n' + 'Writers : ' + $scope.permissions.writers
|
||||
$scope.permissions.readers + '\n\n' + 'Runners : ' + $scope.permissions.runners +
|
||||
'\n\n' + 'Writers : ' + $scope.permissions.writers
|
||||
})
|
||||
$scope.showPermissions = false
|
||||
})
|
||||
|
|
@ -1062,6 +1065,7 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
|
|||
$scope.closePermissions()
|
||||
angular.element('#selectOwners').select2({})
|
||||
angular.element('#selectReaders').select2({})
|
||||
angular.element('#selectRunners').select2({})
|
||||
angular.element('#selectWriters').select2({})
|
||||
} else {
|
||||
$scope.openPermissions()
|
||||
|
|
|
|||
|
|
@ -219,6 +219,11 @@
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.permissions .runners {
|
||||
width:60px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.permissions .writers {
|
||||
width:60px;
|
||||
display: inline-block;
|
||||
|
|
|
|||
|
|
@ -81,13 +81,19 @@ limitations under the License.
|
|||
<select id="selectOwners" multiple="multiple">
|
||||
<option is-select2="false" ng-repeat="owner in permissions.owners" selected="selected">{{owner}}</option>
|
||||
</select>
|
||||
Owners can change permissions,read and write the note.
|
||||
Owners can change permissions,read, run and write the note.
|
||||
</p>
|
||||
<p><span class="writers">Writers </span>
|
||||
<select id="selectWriters" multiple="multiple">
|
||||
<option is-select2="false" ng-repeat="writers in permissions.writers" selected="selected">{{writers}}</option>
|
||||
</select>
|
||||
Writers can read and write the note.
|
||||
Writers can read, run and write the note.
|
||||
</p>
|
||||
<p><span class="runners">Runners </span>
|
||||
<select id="selectRunners" multiple="multiple">
|
||||
<option is-select2="false" ng-repeat="runners in permissions.runners" selected="selected">{{runners}}</option>
|
||||
</select>
|
||||
Writers can read, run and write the note.
|
||||
</p>
|
||||
<p><span class="readers">Readers </span>
|
||||
<select id="selectReaders" multiple="multiple">
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ public class NotebookAuthorization {
|
|||
private static final Logger LOG = LoggerFactory.getLogger(NotebookAuthorization.class);
|
||||
private static NotebookAuthorization instance = null;
|
||||
/*
|
||||
* { "note1": { "owners": ["u1"], "readers": ["u1", "u2"], "writers": ["u1"] }, "note2": ... } }
|
||||
* { "note1": { "owners": ["u1"], "readers": ["u1", "u2"], "runners": ["u2"],
|
||||
* "writers": ["u1"] }, "note2": ... } }
|
||||
*/
|
||||
private static Map<String, Map<String, Set<String>>> authInfo = new HashMap<>();
|
||||
/*
|
||||
|
|
@ -177,6 +178,7 @@ public class NotebookAuthorization {
|
|||
noteAuthInfo = new LinkedHashMap();
|
||||
noteAuthInfo.put("owners", new LinkedHashSet(entities));
|
||||
noteAuthInfo.put("readers", new LinkedHashSet());
|
||||
noteAuthInfo.put("runners", new LinkedHashSet());
|
||||
noteAuthInfo.put("writers", new LinkedHashSet());
|
||||
} else {
|
||||
noteAuthInfo.put("owners", new LinkedHashSet(entities));
|
||||
|
|
@ -192,6 +194,7 @@ public class NotebookAuthorization {
|
|||
noteAuthInfo = new LinkedHashMap();
|
||||
noteAuthInfo.put("owners", new LinkedHashSet());
|
||||
noteAuthInfo.put("readers", new LinkedHashSet(entities));
|
||||
noteAuthInfo.put("runners", new LinkedHashSet());
|
||||
noteAuthInfo.put("writers", new LinkedHashSet());
|
||||
} else {
|
||||
noteAuthInfo.put("readers", new LinkedHashSet(entities));
|
||||
|
|
@ -200,6 +203,23 @@ public class NotebookAuthorization {
|
|||
saveToFile();
|
||||
}
|
||||
|
||||
public void setRunners(String noteId, Set<String> entities) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
entities = validateUser(entities);
|
||||
if (noteAuthInfo == null) {
|
||||
noteAuthInfo = new LinkedHashMap();
|
||||
noteAuthInfo.put("owners", new LinkedHashSet());
|
||||
noteAuthInfo.put("readers", new LinkedHashSet());
|
||||
noteAuthInfo.put("runners", new LinkedHashSet(entities));
|
||||
noteAuthInfo.put("writers", new LinkedHashSet());
|
||||
} else {
|
||||
noteAuthInfo.put("runners", new LinkedHashSet(entities));
|
||||
}
|
||||
authInfo.put(noteId, noteAuthInfo);
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
|
||||
public void setWriters(String noteId, Set<String> entities) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
entities = validateUser(entities);
|
||||
|
|
@ -207,6 +227,7 @@ public class NotebookAuthorization {
|
|||
noteAuthInfo = new LinkedHashMap();
|
||||
noteAuthInfo.put("owners", new LinkedHashSet());
|
||||
noteAuthInfo.put("readers", new LinkedHashSet());
|
||||
noteAuthInfo.put("runners", new LinkedHashSet());
|
||||
noteAuthInfo.put("writers", new LinkedHashSet(entities));
|
||||
} else {
|
||||
noteAuthInfo.put("writers", new LinkedHashSet(entities));
|
||||
|
|
@ -243,6 +264,20 @@ public class NotebookAuthorization {
|
|||
return entities;
|
||||
}
|
||||
|
||||
public Set<String> getRunners(String noteId) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
Set<String> entities = null;
|
||||
if (noteAuthInfo == null) {
|
||||
entities = new HashSet<>();
|
||||
} else {
|
||||
entities = noteAuthInfo.get("runners");
|
||||
if (entities == null) {
|
||||
entities = new HashSet<>();
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public Set<String> getWriters(String noteId) {
|
||||
Map<String, Set<String>> noteAuthInfo = authInfo.get(noteId);
|
||||
Set<String> entities = null;
|
||||
|
|
@ -268,7 +303,14 @@ public class NotebookAuthorization {
|
|||
public boolean isReader(String noteId, Set<String> entities) {
|
||||
return isMember(entities, getReaders(noteId)) ||
|
||||
isMember(entities, getOwners(noteId)) ||
|
||||
isMember(entities, getWriters(noteId));
|
||||
isMember(entities, getWriters(noteId)) ||
|
||||
isMember(entities, getRunners(noteId));
|
||||
}
|
||||
|
||||
public boolean isRunner(String noteId, Set<String> entities) {
|
||||
return isMember(entities, getRunners(noteId)) ||
|
||||
isMember(entities, getWriters(noteId)) ||
|
||||
isMember(entities, getOwners(noteId));
|
||||
}
|
||||
|
||||
// return true if b is empty or if (a intersection b) is non-empty
|
||||
|
|
@ -311,6 +353,17 @@ public class NotebookAuthorization {
|
|||
return isReader(noteId, userAndRoles);
|
||||
}
|
||||
|
||||
public boolean hasRunAuthorization(Set<String> userAndRoles, String noteId) {
|
||||
if (conf.isAnonymousAllowed()) {
|
||||
LOG.debug("Zeppelin runs in anonymous mode, everybody is runner");
|
||||
return true;
|
||||
}
|
||||
if (userAndRoles == null) {
|
||||
return false;
|
||||
}
|
||||
return isRunner(noteId, userAndRoles);
|
||||
}
|
||||
|
||||
public void removeNote(String noteId) {
|
||||
authInfo.remove(noteId);
|
||||
saveToFile();
|
||||
|
|
@ -337,13 +390,16 @@ public class NotebookAuthorization {
|
|||
owners.add(subject.getUser());
|
||||
setOwners(noteId, owners);
|
||||
} else {
|
||||
// add current user to owners, readers, writers - private note
|
||||
// add current user to owners, readers, runners, writers - private note
|
||||
Set<String> entities = getOwners(noteId);
|
||||
entities.add(subject.getUser());
|
||||
setOwners(noteId, entities);
|
||||
entities = getReaders(noteId);
|
||||
entities.add(subject.getUser());
|
||||
setReaders(noteId, entities);
|
||||
entities = getRunners(noteId);
|
||||
entities.add(subject.getUser());
|
||||
setRunners(noteId, entities);
|
||||
entities = getWriters(noteId);
|
||||
entities.add(subject.getUser());
|
||||
setWriters(noteId, entities);
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ public class NotebookRepoSync implements NotebookRepo {
|
|||
NotebookAuthorization notebookAuthorization = NotebookAuthorization.getInstance();
|
||||
return notebookAuthorization.getOwners(noteId).isEmpty()
|
||||
&& notebookAuthorization.getReaders(noteId).isEmpty()
|
||||
&& notebookAuthorization.getRunners(noteId).isEmpty()
|
||||
&& notebookAuthorization.getWriters(noteId).isEmpty();
|
||||
}
|
||||
|
||||
|
|
@ -299,6 +300,9 @@ public class NotebookRepoSync implements NotebookRepo {
|
|||
users = notebookAuthorization.getReaders(noteId);
|
||||
users.add(subject.getUser());
|
||||
notebookAuthorization.setReaders(noteId, users);
|
||||
users = notebookAuthorization.getRunners(noteId);
|
||||
users.add(subject.getUser());
|
||||
notebookAuthorization.setRunners(noteId, users);
|
||||
users = notebookAuthorization.getWriters(noteId);
|
||||
users.add(subject.getUser());
|
||||
notebookAuthorization.setWriters(noteId, users);
|
||||
|
|
|
|||
|
|
@ -721,6 +721,8 @@ public class NotebookTest implements JobListenerFactory{
|
|||
new HashSet<>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isReader(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isRunner(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isWriter(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user2"))), true);
|
||||
|
||||
|
|
@ -728,6 +730,8 @@ public class NotebookTest implements JobListenerFactory{
|
|||
new HashSet<>(Arrays.asList("user1")));
|
||||
notebookAuthorization.setReaders(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user1", "user2")));
|
||||
notebookAuthorization.setRunners(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user3")));
|
||||
notebookAuthorization.setWriters(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user1")));
|
||||
|
||||
|
|
@ -737,21 +741,26 @@ public class NotebookTest implements JobListenerFactory{
|
|||
new HashSet<>(Arrays.asList("user1"))), true);
|
||||
|
||||
assertEquals(notebookAuthorization.isReader(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user3"))), false);
|
||||
new HashSet<>(Arrays.asList("user4"))), false);
|
||||
assertEquals(notebookAuthorization.isReader(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user2"))), true);
|
||||
|
||||
assertEquals(notebookAuthorization.isRunner(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user3"))), true);
|
||||
assertEquals(notebookAuthorization.isRunner(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user2"))), false);
|
||||
|
||||
assertEquals(notebookAuthorization.isWriter(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user2"))), false);
|
||||
assertEquals(notebookAuthorization.isWriter(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user1"))), true);
|
||||
|
||||
// Test clearing of permssions
|
||||
// Test clearing of permissions
|
||||
notebookAuthorization.setReaders(note.getId(), Sets.<String>newHashSet());
|
||||
assertEquals(notebookAuthorization.isReader(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user2"))), true);
|
||||
assertEquals(notebookAuthorization.isReader(note.getId(),
|
||||
new HashSet<>(Arrays.asList("user3"))), true);
|
||||
new HashSet<>(Arrays.asList("user4"))), true);
|
||||
|
||||
notebook.removeNote(note.getId(), anonymous);
|
||||
}
|
||||
|
|
@ -767,11 +776,13 @@ public class NotebookTest implements JobListenerFactory{
|
|||
|
||||
Note note = notebook.createNote(new AuthenticationInfo(user1));
|
||||
|
||||
// check that user1 is owner, reader and writer
|
||||
// check that user1 is owner, reader, runner and writer
|
||||
assertEquals(notebookAuthorization.isOwner(note.getId(),
|
||||
Sets.newHashSet(user1)), true);
|
||||
assertEquals(notebookAuthorization.isReader(note.getId(),
|
||||
Sets.newHashSet(user1)), true);
|
||||
assertEquals(notebookAuthorization.isRunner(note.getId(),
|
||||
Sets.newHashSet(user2)), true);
|
||||
assertEquals(notebookAuthorization.isWriter(note.getId(),
|
||||
Sets.newHashSet(user1)), true);
|
||||
|
||||
|
|
@ -780,6 +791,8 @@ public class NotebookTest implements JobListenerFactory{
|
|||
Sets.newHashSet(user2)), false);
|
||||
assertEquals(notebookAuthorization.isReader(note.getId(),
|
||||
Sets.newHashSet(user2)), true);
|
||||
assertEquals(notebookAuthorization.isRunner(note.getId(),
|
||||
Sets.newHashSet(user2)), true);
|
||||
assertEquals(notebookAuthorization.isWriter(note.getId(),
|
||||
Sets.newHashSet(user2)), true);
|
||||
|
||||
|
|
@ -790,7 +803,7 @@ public class NotebookTest implements JobListenerFactory{
|
|||
assertEquals(user1Notes.size(), 1);
|
||||
assertEquals(user1Notes.get(0).getId(), note.getId());
|
||||
|
||||
// check that user2 has note listed in his workbech because of admin role
|
||||
// check that user2 has note listed in his workbench because of admin role
|
||||
Set<String> user2AndRoles = notebookAuthorization.getRoles(user2);
|
||||
user2AndRoles.add(user2);
|
||||
List<Note> user2Notes = notebook.getAllNotes(user2AndRoles);
|
||||
|
|
@ -1094,6 +1107,7 @@ public class NotebookTest implements JobListenerFactory{
|
|||
|
||||
notebook.getNotebookAuthorization().setOwners(note1.getId(), Sets.newHashSet("user1"));
|
||||
notebook.getNotebookAuthorization().setWriters(note1.getId(), Sets.newHashSet("user1"));
|
||||
notebook.getNotebookAuthorization().setRunners(note1.getId(), Sets.newHashSet("user1"));
|
||||
notebook.getNotebookAuthorization().setReaders(note1.getId(), Sets.newHashSet("user1"));
|
||||
assertEquals(1, notebook.getAllNotes(Sets.newHashSet("anonymous")).size());
|
||||
assertEquals(2, notebook.getAllNotes(Sets.newHashSet("user1")).size());
|
||||
|
|
@ -1101,6 +1115,7 @@ public class NotebookTest implements JobListenerFactory{
|
|||
notebook.getNotebookAuthorization().setOwners(note2.getId(), Sets.newHashSet("user2"));
|
||||
notebook.getNotebookAuthorization().setWriters(note2.getId(), Sets.newHashSet("user2"));
|
||||
notebook.getNotebookAuthorization().setReaders(note2.getId(), Sets.newHashSet("user2"));
|
||||
notebook.getNotebookAuthorization().setRunners(note1.getId(), Sets.newHashSet("user2"));
|
||||
assertEquals(0, notebook.getAllNotes(Sets.newHashSet("anonymous")).size());
|
||||
assertEquals(1, notebook.getAllNotes(Sets.newHashSet("user1")).size());
|
||||
assertEquals(1, notebook.getAllNotes(Sets.newHashSet("user2")).size());
|
||||
|
|
@ -1133,6 +1148,12 @@ public class NotebookTest implements JobListenerFactory{
|
|||
notes2 = notebook.getAllNotes(user2);
|
||||
assertEquals(notes1.size(), 1);
|
||||
assertEquals(notes2.size(), 1);
|
||||
|
||||
notebook.getNotebookAuthorization().setRunners(note.getId(), Sets.newHashSet("user1"));
|
||||
notes1 = notebook.getAllNotes(user1);
|
||||
notes2 = notebook.getAllNotes(user2);
|
||||
assertEquals(notes1.size(), 1);
|
||||
assertEquals(notes2.size(), 1);
|
||||
|
||||
notebook.getNotebookAuthorization().setWriters(note.getId(), Sets.newHashSet("user1"));
|
||||
notes1 = notebook.getAllNotes(user1);
|
||||
|
|
@ -1169,6 +1190,7 @@ public class NotebookTest implements JobListenerFactory{
|
|||
// user1 is only owner
|
||||
assertEquals(notebookAuthorization.getOwners(notePublic.getId()).size(), 1);
|
||||
assertEquals(notebookAuthorization.getReaders(notePublic.getId()).size(), 0);
|
||||
assertEquals(notebookAuthorization.getRunners(notePublic.getId()).size(), 0);
|
||||
assertEquals(notebookAuthorization.getWriters(notePublic.getId()).size(), 0);
|
||||
|
||||
// case of private note
|
||||
|
|
@ -1197,6 +1219,7 @@ public class NotebookTest implements JobListenerFactory{
|
|||
// user1 have all rights
|
||||
assertEquals(notebookAuthorization.getOwners(notePrivate.getId()).size(), 1);
|
||||
assertEquals(notebookAuthorization.getReaders(notePrivate.getId()).size(), 1);
|
||||
assertEquals(notebookAuthorization.getRunners(notePrivate.getId()).size(), 1);
|
||||
assertEquals(notebookAuthorization.getWriters(notePrivate.getId()).size(), 1);
|
||||
|
||||
//set back public to true
|
||||
|
|
|
|||
|
|
@ -330,6 +330,7 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
assertEquals(true, authInfo.isOwner(note.getId(), entity));
|
||||
assertEquals(1, authInfo.getOwners(note.getId()).size());
|
||||
assertEquals(0, authInfo.getReaders(note.getId()).size());
|
||||
assertEquals(0, authInfo.getRunners(note.getId()).size());
|
||||
assertEquals(0, authInfo.getWriters(note.getId()).size());
|
||||
|
||||
/* update note and save on secondary storage */
|
||||
|
|
@ -354,6 +355,7 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
assertEquals(true, authInfo.isOwner(note.getId(), entity));
|
||||
assertEquals(1, authInfo.getOwners(note.getId()).size());
|
||||
assertEquals(0, authInfo.getReaders(note.getId()).size());
|
||||
assertEquals(0, authInfo.getRunners(note.getId()).size());
|
||||
assertEquals(0, authInfo.getWriters(note.getId()).size());
|
||||
|
||||
/* scenario 2 - note doesn't exist on main storage */
|
||||
|
|
@ -364,6 +366,7 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
authInfo.removeNote(note.getId());
|
||||
assertEquals(0, authInfo.getOwners(note.getId()).size());
|
||||
assertEquals(0, authInfo.getReaders(note.getId()).size());
|
||||
assertEquals(0, authInfo.getRunners(note.getId()).size());
|
||||
assertEquals(0, authInfo.getWriters(note.getId()).size());
|
||||
|
||||
/* now sync - should bring note from secondary storage with added acl */
|
||||
|
|
@ -372,9 +375,11 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
assertEquals(1, notebookRepoSync.list(1, null).size());
|
||||
assertEquals(1, authInfo.getOwners(note.getId()).size());
|
||||
assertEquals(1, authInfo.getReaders(note.getId()).size());
|
||||
assertEquals(1, authInfo.getRunners(note.getId()).size());
|
||||
assertEquals(1, authInfo.getWriters(note.getId()).size());
|
||||
assertEquals(true, authInfo.isOwner(note.getId(), entity));
|
||||
assertEquals(true, authInfo.isReader(note.getId(), entity));
|
||||
assertEquals(true, authInfo.isRunner(note.getId(), entity));
|
||||
assertEquals(true, authInfo.isWriter(note.getId(), entity));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue