Skip to content

Commit c7fdc66

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 9762134 + de5f55a commit c7fdc66

File tree

16 files changed

+689
-74
lines changed

16 files changed

+689
-74
lines changed

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ please check [its own contribution guidelines](https://github.com/apache/incubat
125125
126126
### Code convention
127127
We are following Google Code style:
128-
* [Java style](http://google-styleguide.googlecode.com/svn/trunk/javaguide.html)
129-
* [Shell style](https://google-styleguide.googlecode.com/svn/trunk/shell.xml)
128+
* [Java style](https://google.github.io/styleguide/javaguide.html)
129+
* [Shell style](https://google.github.io/styleguide/shell.xml)
130130
131131
Check style report location are in `${submodule}/target/site/checkstyle.html`
132132
Test coverage report location are in `${submodule}/target/site/cobertura/index.html`

docs/development/writingzeppelininterpreter.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@ Creating a new interpreter is quite simple. Just extend [org.apache.zeppelin.int
3939
You can include `org.apache.zeppelin:zeppelin-interpreter:[VERSION]` artifact in your build system. And you should your jars under your interpreter directory with specific directory name. Zeppelin server reads interpreter directories recursively and initializes interpreters including your own interpreter.
4040

4141
There are three locations where you can store your interpreter group, name and other information. Zeppelin server tries to find the location below. Next, Zeppelin tries to find `interpareter-setting.json` in your interpreter jar.
42+
4243
```
4344
{ZEPPELIN_INTERPRETER_DIR}/{YOUR_OWN_INTERPRETER_DIR}/interpreter-setting.json
4445
```
4546

4647
Here is an example of `interpareter-setting.json` on your own interpreter.
48+
4749
```json
4850
[
4951
{
@@ -72,11 +74,13 @@ Here is an example of `interpareter-setting.json` on your own interpreter.
7274
```
7375

7476
Finally, Zeppelin uses static initialization with the following:
77+
7578
```
7679
static {
7780
Interpreter.register("MyInterpreterName", MyClassName.class.getName());
7881
}
7982
```
83+
8084
**Static initialization is deprecated and will be supported until 0.6.0.**
8185

8286
The name will appear later in the interpreter name option box during the interpreter configuration process.

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@
475475
<exclude>conf/zeppelin-env.sh</exclude>
476476
<exclude>spark-*-bin*/**</exclude>
477477
<exclude>.spark-dist/**</exclude>
478+
<exclude>**/interpreter-setting.json</exclude>
478479

479480
<!-- bundled from bootstrap -->
480481
<exclude>docs/assets/themes/zeppelin/bootstrap/**</exclude>

shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,27 +45,12 @@ public class ShellInterpreter extends Interpreter {
4545
Logger logger = LoggerFactory.getLogger(ShellInterpreter.class);
4646
private static final String EXECUTOR_KEY = "executor";
4747
public static final String SHELL_COMMAND_TIMEOUT = "shell.command.timeout.millisecs";
48-
public static final String DEFAULT_COMMAND_TIMEOUT = "600000";
4948
int commandTimeOut;
5049
private static final boolean isWindows = System
5150
.getProperty("os.name")
5251
.startsWith("Windows");
5352
final String shell = isWindows ? "cmd /c" : "bash -c";
5453

55-
static {
56-
Interpreter.register(
57-
"sh",
58-
"sh",
59-
ShellInterpreter.class.getName(),
60-
new InterpreterPropertyBuilder()
61-
.add(
62-
SHELL_COMMAND_TIMEOUT,
63-
DEFAULT_COMMAND_TIMEOUT,
64-
"Shell command time out in millisecs. Default = 600000")
65-
.build()
66-
);
67-
}
68-
6954
public ShellInterpreter(Properties property) {
7055
super(property);
7156
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[
2+
{
3+
"group": "sh",
4+
"name": "sh",
5+
"className": "org.apache.zeppelin.shell.ShellInterpreter",
6+
"properties": {
7+
"shell.command.timeout.millisecs": {
8+
"envName": "SHELL_COMMAND_TIMEOUT",
9+
"propertyName": "shell.command.timeout.millisecs",
10+
"defaultValue": "60000",
11+
"description": "Shell command time out in millisecs. Default = 60000"
12+
}
13+
}
14+
}
15+
]

testing/downloadSpark.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,17 @@ if [[ ! -d "${SPARK_HOME}" ]]; then
7676
echo "${SPARK_CACHE} does not have ${SPARK_ARCHIVE} downloading ..."
7777

7878
# download archive if not cached
79-
if [[ "${SPARK_VER_RANGE}" == "<=1.2" ]]; then
80-
# spark 1.1.x and spark 1.2.x can be downloaded from archive
79+
if [[ "${SPARK_VERSION}" = "1.1.1" || "${SPARK_VERSION}" = "1.2.2" || "${SPARK_VERSION}" = "1.3.1" || "${SPARK_VERSION}" = "1.4.1" ]]; then
80+
echo "${SPARK_VERSION} being downloaded from archives"
81+
# spark old versions are only available only on the archives (prior to 1.5.2)
8182
STARTTIME=`date +%s`
8283
#timeout -s KILL "${MAX_DOWNLOAD_TIME_SEC}" wget "http://archive.apache.org/dist/spark/spark-${SPARK_VERSION}/${SPARK_ARCHIVE}.tgz"
8384
download_with_retry "http://archive.apache.org/dist/spark/spark-${SPARK_VERSION}/${SPARK_ARCHIVE}.tgz"
8485
ENDTIME=`date +%s`
8586
DOWNLOADTIME="$((ENDTIME-STARTTIME))"
8687
else
87-
# spark 1.3.x and later can be downloaded from mirror
88+
echo "${SPARK_VERSION} being downloaded from mirror"
89+
# spark 1.5.2 and up and later can be downloaded from mirror
8890
# get download address from mirror
8991
MIRROR_INFO=$(curl -s "http://www.apache.org/dyn/closer.cgi/spark/spark-${SPARK_VERSION}/${SPARK_ARCHIVE}.tgz?asjson=1")
9092

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.zeppelin.rest;
19+
20+
import org.apache.commons.lang3.reflect.FieldUtils;
21+
import org.apache.shiro.realm.jdbc.JdbcRealm;
22+
import org.apache.shiro.realm.ldap.JndiLdapContextFactory;
23+
import org.apache.shiro.realm.ldap.JndiLdapRealm;
24+
import org.apache.shiro.realm.text.IniRealm;
25+
import org.apache.shiro.util.JdbcUtils;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
29+
import javax.naming.NamingEnumeration;
30+
import javax.naming.directory.Attributes;
31+
import javax.naming.directory.SearchControls;
32+
import javax.naming.directory.SearchResult;
33+
import javax.naming.ldap.LdapContext;
34+
import javax.sql.DataSource;
35+
import java.sql.Connection;
36+
import java.sql.PreparedStatement;
37+
import java.sql.ResultSet;
38+
import java.util.ArrayList;
39+
import java.util.Iterator;
40+
import java.util.List;
41+
import java.util.Map;
42+
43+
/**
44+
* This is class which help fetching users from different realms.
45+
* getUserList() function is overloaded and according to the realm passed to the function it
46+
* extracts users from its respective realm
47+
*/
48+
public class GetUserList {
49+
50+
private static final Logger LOG = LoggerFactory.getLogger(GetUserList.class);
51+
52+
/**
53+
* function to extract users from shiro.ini
54+
*/
55+
public List<String> getUserList(IniRealm r) {
56+
List<String> userList = new ArrayList<>();
57+
Map getIniUser = r.getIni().get("users");
58+
Iterator it = getIniUser.entrySet().iterator();
59+
while (it.hasNext()) {
60+
Map.Entry pair = (Map.Entry) it.next();
61+
userList.add(pair.getKey().toString());
62+
}
63+
return userList;
64+
}
65+
66+
/**
67+
* function to extract users from LDAP
68+
*/
69+
public List<String> getUserList(JndiLdapRealm r) {
70+
List<String> userList = new ArrayList<>();
71+
String userDnTemplate = r.getUserDnTemplate();
72+
String userDn[] = userDnTemplate.split(",", 2);
73+
String userDnPrefix = userDn[0].split("=")[0];
74+
String userDnSuffix = userDn[1];
75+
JndiLdapContextFactory CF = (JndiLdapContextFactory) r.getContextFactory();
76+
try {
77+
LdapContext ctx = CF.getSystemLdapContext();
78+
SearchControls constraints = new SearchControls();
79+
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
80+
String[] attrIDs = {userDnPrefix};
81+
constraints.setReturningAttributes(attrIDs);
82+
NamingEnumeration result = ctx.search(userDnSuffix, "(objectclass=*)", constraints);
83+
while (result.hasMore()) {
84+
Attributes attrs = ((SearchResult) result.next()).getAttributes();
85+
if (attrs.get(userDnPrefix) != null) {
86+
String currentUser = attrs.get(userDnPrefix).toString();
87+
userList.add(currentUser.split(":")[1]);
88+
}
89+
}
90+
} catch (Exception e) {
91+
LOG.error("Error retrieving User list from Ldap Realm", e);
92+
}
93+
return userList;
94+
}
95+
96+
/**
97+
* function to extract users from JDBCs
98+
*/
99+
public List<String> getUserList(JdbcRealm obj) {
100+
List<String> userlist = new ArrayList<>();
101+
PreparedStatement ps = null;
102+
ResultSet rs = null;
103+
DataSource dataSource = null;
104+
String authQuery = "";
105+
String retval[];
106+
String tablename = "";
107+
String username = "";
108+
String userquery = "";
109+
try {
110+
dataSource = (DataSource) FieldUtils.readField(obj, "dataSource", true);
111+
authQuery = (String) FieldUtils.readField(obj, "DEFAULT_AUTHENTICATION_QUERY", true);
112+
LOG.info(authQuery);
113+
String authQueryLowerCase = authQuery.toLowerCase();
114+
retval = authQueryLowerCase.split("from", 2);
115+
if (retval.length >= 2) {
116+
retval = retval[1].split("with|where", 2);
117+
tablename = retval[0];
118+
retval = retval[1].split("where", 2);
119+
if (retval.length >= 2)
120+
retval = retval[1].split("=", 2);
121+
else
122+
retval = retval[0].split("=", 2);
123+
username = retval[0];
124+
}
125+
126+
if (username.equals("") || tablename.equals("")){
127+
return userlist;
128+
}
129+
130+
userquery = "select " + username + " from " + tablename;
131+
132+
} catch (IllegalAccessException e) {
133+
LOG.error("Error while accessing dataSource for JDBC Realm", e);
134+
return null;
135+
}
136+
137+
try {
138+
Connection con = dataSource.getConnection();
139+
ps = con.prepareStatement(userquery);
140+
rs = ps.executeQuery();
141+
while (rs.next()) {
142+
userlist.add(rs.getString(1));
143+
}
144+
} catch (Exception e) {
145+
LOG.error("Error retrieving User list from JDBC Realm", e);
146+
} finally {
147+
JdbcUtils.closeResultSet(rs);
148+
JdbcUtils.closeStatement(ps);
149+
}
150+
return userlist;
151+
}
152+
153+
}

zeppelin-server/src/main/java/org/apache/zeppelin/rest/SecurityRestApi.java

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717

1818
package org.apache.zeppelin.rest;
1919

20+
21+
import org.apache.shiro.realm.Realm;
22+
import org.apache.shiro.realm.jdbc.JdbcRealm;
23+
import org.apache.shiro.realm.ldap.JndiLdapRealm;
24+
import org.apache.shiro.realm.text.IniRealm;
25+
import org.apache.shiro.util.ThreadContext;
26+
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
2027
import org.apache.zeppelin.annotation.ZeppelinApi;
2128
import org.apache.zeppelin.conf.ZeppelinConfiguration;
2229
import org.apache.zeppelin.server.JsonResponse;
@@ -27,11 +34,10 @@
2734

2835
import javax.ws.rs.GET;
2936
import javax.ws.rs.Path;
37+
import javax.ws.rs.PathParam;
3038
import javax.ws.rs.Produces;
3139
import javax.ws.rs.core.Response;
32-
import java.util.HashMap;
33-
import java.util.HashSet;
34-
import java.util.Map;
40+
import java.util.*;
3541

3642
/**
3743
* Zeppelin security rest api endpoint.
@@ -81,4 +87,54 @@ public Response ticket() {
8187
LOG.warn(response.toString());
8288
return response.build();
8389
}
90+
91+
/**
92+
* Get userlist
93+
* Returns list of all user from available realms
94+
*
95+
* @return 200 response
96+
*/
97+
@GET
98+
@Path("userlist/{searchText}")
99+
public Response getUserList(@PathParam("searchText") String searchText) {
100+
101+
List<String> usersList = new ArrayList<>();
102+
try {
103+
GetUserList getUserListObj = new GetUserList();
104+
DefaultWebSecurityManager defaultWebSecurityManager;
105+
String key = ThreadContext.SECURITY_MANAGER_KEY;
106+
defaultWebSecurityManager = (DefaultWebSecurityManager) ThreadContext.get(key);
107+
Collection<Realm> realms = defaultWebSecurityManager.getRealms();
108+
List realmsList = new ArrayList(realms);
109+
for (int i = 0; i < realmsList.size(); i++) {
110+
String name = ((Realm) realmsList.get(i)).getName();
111+
if (name.equals("iniRealm")) {
112+
usersList.addAll(getUserListObj.getUserList((IniRealm) realmsList.get(i)));
113+
} else if (name.equals("ldapRealm")) {
114+
usersList.addAll(getUserListObj.getUserList((JndiLdapRealm) realmsList.get(i)));
115+
} else if (name.equals("jdbcRealm")) {
116+
usersList.addAll(getUserListObj.getUserList((JdbcRealm) realmsList.get(i)));
117+
}
118+
}
119+
120+
} catch (Exception e) {
121+
LOG.error("Exception in retrieving Users from realms ", e);
122+
}
123+
List<String> autoSuggestList = new ArrayList<>();
124+
Collections.sort(usersList);
125+
int maxLength = 0;
126+
for (int i = 0; i < usersList.size(); i++) {
127+
String userLowerCase = usersList.get(i).toLowerCase();
128+
String searchTextLowerCase = searchText.toLowerCase();
129+
if (userLowerCase.indexOf(searchTextLowerCase) != -1) {
130+
maxLength++;
131+
autoSuggestList.add(usersList.get(i));
132+
}
133+
if (maxLength == 5) {
134+
break;
135+
}
136+
}
137+
return new JsonResponse<>(Response.Status.OK, "", autoSuggestList).build();
138+
}
139+
84140
}

zeppelin-web/src/app/home/home.controller.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,8 @@ angular.module('zeppelinWebApp').controller('HomeCtrl', function($scope, noteboo
2828

2929
$scope.isReloading = false;
3030

31-
var getZeppelinVersion = function() {
32-
$http.get(baseUrlSrv.getRestApiBase() +'/version').
33-
success(function (data, status, headers, config) {
34-
$scope.zeppelinVersion = data.body;
35-
}).
36-
error(function(data, status, headers, config) {
37-
console.log('Error %o %o', status, data.message);
38-
});
39-
};
40-
4131
var initHome = function() {
4232
websocketMsgSrv.getHomeNotebook();
43-
getZeppelinVersion();
4433
};
4534

4635
initHome();

0 commit comments

Comments
 (0)