You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2015/11/03 17:10:56 UTC
nifi git commit: NIFI-655: - Adding a new endpoint to obtain the
status of a user registration. - Updated the login page loading to ensure all
possible states work.
Repository: nifi
Updated Branches:
refs/heads/NIFI-655 7f9807f46 -> 71d84117e
NIFI-655:
- Adding a new endpoint to obtain the status of a user registration.
- Updated the login page loading to ensure all possible states work.
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/71d84117
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/71d84117
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/71d84117
Branch: refs/heads/NIFI-655
Commit: 71d84117e4a3b67a90d9c83f2ff3f27bcdea6b95
Parents: 7f9807f
Author: Matt Gilman <ma...@gmail.com>
Authored: Tue Nov 3 11:10:32 2015 -0500
Committer: Matt Gilman <ma...@gmail.com>
Committed: Tue Nov 3 11:10:32 2015 -0500
----------------------------------------------------------------------
.../web/NiFiWebApiSecurityConfiguration.java | 15 +-
.../apache/nifi/web/api/ControllerResource.java | 9 +-
.../web/security/RegistrationStatusFilter.java | 217 +++++++++++++++++++
.../src/main/webapp/WEB-INF/pages/login.jsp | 1 +
.../WEB-INF/partials/canvas/canvas-header.jsp | 3 +
.../WEB-INF/partials/login/login-message.jsp | 20 ++
.../WEB-INF/partials/login/login-submission.jsp | 2 +-
.../nifi-web-ui/src/main/webapp/css/header.css | 4 +
.../webapp/js/nf/canvas/nf-canvas-header.js | 5 +
.../src/main/webapp/js/nf/canvas/nf-canvas.js | 3 +-
.../src/main/webapp/js/nf/login/nf-login.js | 128 ++++++++---
.../src/main/webapp/js/nf/nf-common.js | 10 +
12 files changed, 382 insertions(+), 35 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
index e30f812..d6feef0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiWebApiSecurityConfiguration.java
@@ -23,6 +23,7 @@ import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.security.NiFiAuthenticationProvider;
import org.apache.nifi.web.security.anonymous.NiFiAnonymousUserFilter;
import org.apache.nifi.web.security.NiFiAuthenticationEntryPoint;
+import org.apache.nifi.web.security.RegistrationStatusFilter;
import org.apache.nifi.web.security.form.LoginAuthenticationFilter;
import org.apache.nifi.web.security.jwt.JwtAuthenticationFilter;
import org.apache.nifi.web.security.jwt.JwtService;
@@ -90,11 +91,14 @@ public class NiFiWebApiSecurityConfiguration extends WebSecurityConfigurerAdapte
// login authentication for /token - exchanges for JWT for subsequent API usage
http.addFilterBefore(buildLoginFilter("/token"), UsernamePasswordAuthenticationFilter.class);
- // verify the configured login authenticator supports registration
+ // verify the configured login authenticator supports user login registration
if (loginIdentityProvider.supportsRegistration()) {
http.addFilterBefore(buildRegistrationFilter("/registration"), UsernamePasswordAuthenticationFilter.class);
}
}
+
+ // registration status - will check the status of a user's account registration (regardless if its based on login or not)
+ http.addFilterBefore(buildRegistrationStatusFilter("/registration/status"), UsernamePasswordAuthenticationFilter.class);
// cluster authorized user
http.addFilterBefore(buildNodeAuthorizedUserFilter(), AnonymousAuthenticationFilter.class);
@@ -134,6 +138,15 @@ public class NiFiWebApiSecurityConfiguration extends WebSecurityConfigurerAdapte
private Filter buildRegistrationFilter(final String url) {
return null;
}
+
+ private Filter buildRegistrationStatusFilter(final String url) {
+ final RegistrationStatusFilter registrationFilter = new RegistrationStatusFilter(url);
+ registrationFilter.setCertificateExtractor(certificateExtractor);
+ registrationFilter.setPrincipalExtractor(principalExtractor);
+ registrationFilter.setProperties(properties);
+ registrationFilter.setUserDetailsService(userDetailsService);
+ return registrationFilter;
+ }
private NodeAuthorizedUserFilter buildNodeAuthorizedUserFilter() {
return new NodeAuthorizedUserFilter(properties);
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
index 1a23626..78e7d94 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java
@@ -929,7 +929,7 @@ public class ControllerResource extends ApplicationResource {
IdentityEntity entity = new IdentityEntity();
entity.setRevision(revision);
entity.setUserId(user.getId());
- entity.setIdentity(user.getDn());
+ entity.setIdentity(user.getUserName());
// generate the response
return clusterContext(generateOkResponse(entity)).build();
@@ -945,14 +945,17 @@ public class ControllerResource extends ApplicationResource {
@Consumes(MediaType.WILDCARD)
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/authorities")
- @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
+ @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN', 'ROLE_PROXY', 'ROLE_NIFI', 'ROLE_PROVENANCE')")
@ApiOperation(
value = "Retrieves the user details, including the authorities, about the user making the request",
response = AuthorityEntity.class,
authorizations = {
@Authorization(value = "Read Only", type = "ROLE_MONITOR"),
@Authorization(value = "Data Flow Manager", type = "ROLE_DFM"),
- @Authorization(value = "Administrator", type = "ROLE_ADMIN")
+ @Authorization(value = "Administrator", type = "ROLE_ADMIN"),
+ @Authorization(value = "Proxy", type = "ROLE_PROXY"),
+ @Authorization(value = "NiFi", type = "ROLE_NIFI"),
+ @Authorization(value = "Provenance", type = "ROLE_PROVENANCE")
}
)
@ApiResponses(
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/RegistrationStatusFilter.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/RegistrationStatusFilter.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/RegistrationStatusFilter.java
new file mode 100644
index 0000000..073de67
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/RegistrationStatusFilter.java
@@ -0,0 +1,217 @@
+/*
+ * 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.nifi.web.security;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.nifi.authentication.LoginCredentials;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.util.StringUtils;
+import org.apache.nifi.web.security.token.NiFiAuthenticationRequestToken;
+import org.apache.nifi.web.security.x509.X509CertificateExtractor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.authentication.AccountStatusException;
+import org.springframework.security.authentication.AuthenticationServiceException;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
+import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor;
+
+/**
+ * Exchanges a successful login with the configured provider for a ID token for accessing the API.
+ */
+public class RegistrationStatusFilter extends AbstractAuthenticationProcessingFilter {
+
+ private static final Logger logger = LoggerFactory.getLogger(RegistrationStatusFilter.class);
+
+ private NiFiProperties properties;
+ private AuthenticationUserDetailsService<NiFiAuthenticationRequestToken> userDetailsService;
+ private X509CertificateExtractor certificateExtractor;
+ private X509PrincipalExtractor principalExtractor;
+
+ public RegistrationStatusFilter(final String defaultFilterProcessesUrl) {
+ super(defaultFilterProcessesUrl);
+
+ // do not continue filter chain... simply exchaning authentication for token
+ setContinueChainBeforeSuccessfulAuthentication(false);
+ }
+
+ @Override
+ public Authentication attemptAuthentication(final HttpServletRequest request, final HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
+ // only suppport login when running securely
+ if (!request.isSecure()) {
+ return null;
+ }
+
+ // look for a certificate
+ final X509Certificate certificate = certificateExtractor.extractClientCertificate(request);
+
+ // if no certificate, just check the credentials
+ if (certificate == null) {
+ final LoginCredentials credentials = getLoginCredentials(request);
+
+ if (credentials == null) {
+ throw new BadCredentialsException("Unable to check registration status as no credentials were included with the request.");
+ }
+
+ checkAuthorization(ProxiedEntitiesUtils.buildProxyChain(request, credentials.getUsername()));
+ return new RegistrationStatusAuthenticationToken(credentials);
+ } else {
+ // we have a certificate so let's use that
+ final String principal = extractPrincipal(certificate);
+ checkAuthorization(ProxiedEntitiesUtils.buildProxyChain(request, principal));
+
+ final LoginCredentials preAuthenticatedCredentials = new LoginCredentials(principal, null);
+ return new RegistrationStatusAuthenticationToken(preAuthenticatedCredentials);
+ }
+ }
+
+ /**
+ * Checks the status of the proxy.
+ *
+ * @param proxyChain the proxy chain
+ * @throws AuthenticationException if the proxy chain is not authorized
+ */
+ private void checkAuthorization(final List<String> proxyChain) throws AuthenticationException {
+ userDetailsService.loadUserDetails(new NiFiAuthenticationRequestToken(proxyChain));
+ }
+
+ private String extractPrincipal(final X509Certificate certificate) {
+ // extract the principal
+ final Object certificatePrincipal = principalExtractor.extractPrincipal(certificate);
+ return ProxiedEntitiesUtils.formatProxyDn(certificatePrincipal.toString());
+ }
+
+ private LoginCredentials getLoginCredentials(HttpServletRequest request) {
+ final String username = request.getParameter("username");
+ final String password = request.getParameter("password");
+
+ if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
+ return null;
+ } else {
+ return new LoginCredentials(username, password);
+ }
+ }
+
+ @Override
+ protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain, final Authentication authentication)
+ throws IOException, ServletException {
+
+ // mark as successful
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("text/plain");
+ response.setContentLength(0);
+ }
+
+ @Override
+ protected void unsuccessfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException ae) throws IOException, ServletException {
+ // set the response status
+ response.setContentType("text/plain");
+
+ // write the response message
+ PrintWriter out = response.getWriter();
+
+ // use the type of authentication exception to determine the response code
+ if (ae instanceof UsernameNotFoundException) {
+ if (properties.getSupportNewAccountRequests()) {
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ out.println("Not authorized.");
+ } else {
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ out.println("Access is denied.");
+ }
+ } else if (ae instanceof AccountStatusException) {
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ out.println(ae.getMessage());
+ } else if (ae instanceof UntrustedProxyException) {
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ out.println(ae.getMessage());
+ } else if (ae instanceof AuthenticationServiceException) {
+ logger.error(String.format("Unable to authorize: %s", ae.getMessage()), ae);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ out.println(String.format("Unable to authorize: %s", ae.getMessage()));
+ } else {
+ logger.error(String.format("Unable to authorize: %s", ae.getMessage()), ae);
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ out.println("Access is denied.");
+ }
+
+ // log the failure
+ logger.info(String.format("Rejecting access to web api: %s", ae.getMessage()));
+
+ // optionally log the stack trace
+ if (logger.isDebugEnabled()) {
+ logger.debug(StringUtils.EMPTY, ae);
+ }
+ }
+
+ /**
+ * This is an Authentication Token for logging in. Once a user is authenticated, they can be issues an ID token.
+ */
+ public static class RegistrationStatusAuthenticationToken extends AbstractAuthenticationToken {
+
+ final LoginCredentials credentials;
+
+ public RegistrationStatusAuthenticationToken(final LoginCredentials credentials) {
+ super(null);
+ setAuthenticated(true);
+ this.credentials = credentials;
+ }
+
+ public LoginCredentials getLoginCredentials() {
+ return credentials;
+ }
+
+ @Override
+ public Object getCredentials() {
+ return credentials.getPassword();
+ }
+
+ @Override
+ public Object getPrincipal() {
+ return credentials.getUsername();
+ }
+ }
+
+ public void setCertificateExtractor(X509CertificateExtractor certificateExtractor) {
+ this.certificateExtractor = certificateExtractor;
+ }
+
+ public void setPrincipalExtractor(X509PrincipalExtractor principalExtractor) {
+ this.principalExtractor = principalExtractor;
+ }
+
+ public void setUserDetailsService(AuthenticationUserDetailsService<NiFiAuthenticationRequestToken> userDetailsService) {
+ this.userDetailsService = userDetailsService;
+ }
+
+ public void setProperties(NiFiProperties properties) {
+ this.properties = properties;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/login.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/login.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/login.jsp
index 5cdce5b..58bdaad 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/login.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/login.jsp
@@ -35,6 +35,7 @@
${nf.login.script.tags}
</head>
<body>
+ <jsp:include page="/WEB-INF/partials/login/login-message.jsp"/>
<jsp:include page="/WEB-INF/partials/login/login-form.jsp"/>
<jsp:include page="/WEB-INF/partials/login/user-registration-form.jsp"/>
<jsp:include page="/WEB-INF/partials/login/nifi-registration-form.jsp"/>
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
index 54f6811..43e306e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/canvas-header.jsp
@@ -48,6 +48,9 @@
<span id="current-user" class="hidden"></span>
<span id="login-link" class="link">login</span>
</li>
+ <li id="logout-link-container" style="display: none;">
+ <span id="logout-link" class="link">logout</span>
+ </li>
<li>
<span id="help-link" class="link">help</span>
</li>
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-message.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-message.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-message.jsp
new file mode 100644
index 0000000..5284c23
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-message.jsp
@@ -0,0 +1,20 @@
+<%--
+ 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.
+--%>
+<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
+<div id="login-message-container" class="hidden">
+ <div id="login-message"></div>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-submission.jsp
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-submission.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-submission.jsp
index 787bb56..5749ab9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-submission.jsp
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/login/login-submission.jsp
@@ -15,6 +15,6 @@
limitations under the License.
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
-<div id="login-submission-container">
+<div id="login-submission-container" class="hidden">
<button id="login-submission-button" type="submit" class="btn">Log in</button>
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
index 0f08b47..7161a8c 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/header.css
@@ -506,6 +506,10 @@ div.search-glass-pane {
/* styles for the status link */
+#current-user {
+ margin-right: 8px;
+}
+
#utilities-container {
float: right;
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
index 653d895..551f33e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-header.js
@@ -147,6 +147,11 @@ nf.CanvasHeader = (function () {
} else {
$('#login-link-container').css('display', 'none');
}
+
+ // logout link
+ $('#logout-link').click(function () {
+ nf.Storage.removeItem("jwt");
+ });
// initialize the new template dialog
$('#new-template-dialog').modal({
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
index d2d9e82..28359d7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js
@@ -1054,6 +1054,7 @@ nf.Canvas = (function () {
nf.Common.setAuthorities(authoritiesResponse.authorities);
// at this point the user may be themselves or anonymous
+ $('#current-user').text(identityResponse.identity).show();
// if the user is logged, we want to determine if they were logged in using a certificate
if (identityResponse.identity !== 'anonymous') {
@@ -1064,7 +1065,7 @@ nf.Canvas = (function () {
}).fail(function () {
// if this request succeeds, it means the user is logged in using their certificate.
// if this request fails, it means the user is logged in with login credentials so we want to render a logout button.
- // TODO - render logout button
+ $('#logout-link-container').show();
}).always(function () {
deferred.resolve();
});
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
index 695a11c..45ef691 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/login/nf-login.js
@@ -25,6 +25,8 @@ nf.Login = (function () {
var config = {
urls: {
+ registrationStatus: '../nifi-api/registration/status',
+ registration: '../nifi-api/registration',
identity: '../nifi-api/controller/identity',
users: '../nifi-api/controller/users',
token: '../nifi-api/token',
@@ -32,6 +34,10 @@ nf.Login = (function () {
}
};
+ var initializeMessage = function () {
+ $('#login-message-container').show();
+ };
+
var initializeLogin = function () {
return $.ajax({
type: 'GET',
@@ -45,8 +51,29 @@ nf.Login = (function () {
// handle login click
$('#login-button').on('click', function () {
- login().done(function (response) {
+ login().done(function (response, status, xhr) {
+ var authorization = xhr.getResponseHeader('Authorization');
+ var badToken = false;
+
+ // ensure there was a token in the response
+ if (authorization) {
+ var tokens = authorization.split(/ /);
+
+ // ensure the token is the appropriate length
+ if (tokens.length === 2) {
+ // store the jwt and reload the page
+ nf.Storage.setItem('jwt', tokens[1]);
+ window.location = '/nifi';
+ } else {
+ badToken = true;
+ }
+ } else {
+ badToken = true;
+ }
+ if (badToken === true) {
+ // TODO - show unable to parse response token
+ }
});
});
@@ -112,17 +139,19 @@ nf.Login = (function () {
'justification': justification
}
}).done(function (response) {
- // TODO
- // // hide the registration pane
- // $('#registration-pane').hide();
- //
- // // show the message pane
- // $('#message-pane').show();
- // $('#message-title').text('Thanks');
- // $('#message-content').text('Your request will be processed shortly.');
- }).fail(nf.Common.handleAjaxError);
+ $('#login-message').text('Thanks! Your request will be processed shortly.');
+ }).fail(function (xhr, status, error) {
+ $('#login-message').text(xhr.responseText);
+ }).always(function () {
+ // update form visibility
+ $('#nifi-registration-container').hide();
+ $('#login-submission-container').hide();
+ $('#login-message-container').show();
+ });
}
});
+
+ $('#login-submission-container').show();
};
return {
@@ -132,6 +161,7 @@ nf.Login = (function () {
init: function () {
nf.Storage.init();
+ var showMessage = false;
var needsLogin = false;
var needsNiFiRegistration = false;
@@ -140,47 +170,87 @@ nf.Login = (function () {
url: config.urls.token
});
+ var identity = $.ajax({
+ type: 'GET',
+ url: config.urls.identity,
+ dataType: 'json'
+ });
+
var pageStateInit = $.Deferred(function(deferred) {
// get the current user's identity
- $.ajax({
- type: 'GET',
- url: config.urls.identity,
- dataType: 'json'
- }).done(function (response) {
- var identity = response.identity;
-
- // if the user is anonymous they need to login
- if (identity === 'anonymous') {
+ identity.done(function (response) {
+ // if the user is anonymous see if they need to login or if they are working with a certificate
+ if (response.identity === 'anonymous') {
+ // request a token without including credentials, if successful then the user is using a certificate
token.done(function () {
- // anonymous user and 200 from token means they have a certificate but have not yet requested an account
- needsNiFiRegistration = true;
- }).fail(function (xhr, status, error) {
- // no token granted, user needs to login with their credentials
+ // the user is using a certificate, see if their account is active/pending/revoked/etc
+ $.ajax({
+ type: 'GET',
+ url: config.urls.registrationStatus
+ }).done(function () {
+ showMessage = true;
+
+ // account is active and good
+ $('#login-message').text('Your account is active and you are already logged in.');
+ deferred.resolve();
+ }).fail(function (xhr, status, error) {
+ if (xhr.status === 401) {
+ // anonymous user and 401 means they need nifi registration
+ needsNiFiRegistration = true;
+ } else {
+ showMessage = true;
+
+ // anonymous user and non-401 means they already have an account and it's pending/revoked
+ if ($.trim(xhr.responseText) === '') {
+ $('#login-message').text('Unable to check registration status.');
+ } else {
+ $('#login-message').text(xhr.responseText);
+ }
+ }
+ deferred.resolve();
+ });
+ }).fail(function () {
+ // no token granted, user has no certificate and needs to login with their credentials
needsLogin = true;
+ deferred.resolve();
});
+ } else {
+ showMessage = true;
+
+ // the user is not anonymous and has an active account (though maybe role-less)
+ $('#login-message').text('Your account is active and you are already logged in.');
+ deferred.resolve();
}
}).fail(function (xhr, status, error) {
+ // unable to get identity (and no anonymous user) see if we can offer login
if (xhr.status === 401) {
// attempt to get a token for the current user without passing login credentials
token.done(function () {
// 401 from identity request and 200 from token means they have a certificate but have not yet requested an account
needsNiFiRegistration = true;
- }).fail(function (xhr, status, error) {
+ }).fail(function () {
// no token granted, user needs to login with their credentials
needsLogin = true;
});
- } else if (xhr.status === 403) {
- // the user is logged in with certificate or credentials but their account is still pending. error message should indicate
- // TODO - show error
+ } else {
+ showMessage = true;
+
+ // the user is logged in with certificate or credentials but their account is pending/revoked. error message should indicate
+ if ($.trim(xhr.responseText) === '') {
+ $('#login-message').text('Unable to authorize you to use this NiFi and anonymous access is disabled.');
+ } else {
+ $('#login-message').text(xhr.responseText);
+ }
}
- }).always(function () {
deferred.resolve();
});
}).promise();
// render the page accordingly
$.when(pageStateInit).done(function () {
- if (needsLogin === true) {
+ if (showMessage === true) {
+ initializeMessage();
+ } else if (needsLogin === true) {
initializeLogin();
} else if (needsNiFiRegistration === true) {
initializeNiFiRegistration();
http://git-wip-us.apache.org/repos/asf/nifi/blob/71d84117/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index 642bc31..c798a61 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -50,6 +50,16 @@ $(document).ready(function () {
// hide the loading indicator
$('div.loading-container').removeClass('ajax-loading');
});
+
+ // include jwt when possible
+ $.ajaxSetup({
+ 'beforeSend': function(xhr) {
+ var token = nf.Storage.getItem('jwt');
+ if (token) {
+ xhr.setRequestHeader('Authorization', 'Bearer ' + token);
+ }
+ }
+ });
// initialize the tooltips
$('img.setting-icon').qtip(nf.Common.config.tooltipConfig);