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 2016/04/07 22:23:34 UTC
[6/9] nifi git commit: Revert "NIFI-1551:"
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorityProviderFactoryBean.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorityProviderFactoryBean.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorityProviderFactoryBean.java
new file mode 100644
index 0000000..e1a02b8
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorityProviderFactoryBean.java
@@ -0,0 +1,491 @@
+/*
+ * 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.authorization;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.authorization.annotation.AuthorityProviderContext;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
+import org.apache.nifi.authorization.exception.ProviderCreationException;
+import org.apache.nifi.authorization.exception.ProviderDestructionException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+import org.apache.nifi.authorization.generated.AuthorityProviderProperty;
+import org.apache.nifi.authorization.generated.AuthorityProviders;
+import org.apache.nifi.authorization.generated.Provider;
+import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.NarCloseable;
+import org.apache.nifi.util.NiFiProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.xml.sax.SAXException;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Factory bean for loading the configured authority provider.
+ */
+public class AuthorityProviderFactoryBean implements FactoryBean, ApplicationContextAware, DisposableBean, AuthorityProviderLookup {
+
+ private static final Logger logger = LoggerFactory.getLogger(AuthorityProviderFactoryBean.class);
+ private static final String AUTHORITY_PROVIDERS_XSD = "/authority-providers.xsd";
+ private static final String JAXB_GENERATED_PATH = "org.apache.nifi.authorization.generated";
+ private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();
+
+ /**
+ * Load the JAXBContext.
+ */
+ private static JAXBContext initializeJaxbContext() {
+ try {
+ return JAXBContext.newInstance(JAXB_GENERATED_PATH, AuthorityProviderFactoryBean.class.getClassLoader());
+ } catch (JAXBException e) {
+ throw new RuntimeException("Unable to create JAXBContext.");
+ }
+ }
+
+ private ApplicationContext applicationContext;
+ private AuthorityProvider authorityProvider;
+ private NiFiProperties properties;
+ private final Map<String, AuthorityProvider> authorityProviders = new HashMap<>();
+
+ @Override
+ public AuthorityProvider getAuthorityProvider(String identifier) {
+ return authorityProviders.get(identifier);
+ }
+
+ @Override
+ public Object getObject() throws Exception {
+ if (authorityProvider == null) {
+ // look up the authority provider to use
+ final String authorityProviderIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORITY_PROVIDER);
+
+ // ensure the authority provider class name was specified
+ if (StringUtils.isBlank(authorityProviderIdentifier)) {
+ // if configured for ssl, the authority provider must be specified
+ if (properties.getSslPort() != null) {
+ throw new Exception("When running securely, the authority provider identifier must be specified in the nifi properties file.");
+ }
+
+ // use a default provider... only allowable when running not securely
+ authorityProvider = createDefaultProvider();
+ } else {
+ final AuthorityProviders authorityProviderConfiguration = loadAuthorityProvidersConfiguration();
+
+ // create each authority provider
+ for (final Provider provider : authorityProviderConfiguration.getProvider()) {
+ authorityProviders.put(provider.getIdentifier(), createAuthorityProvider(provider.getIdentifier(), provider.getClazz()));
+ }
+
+ // configure each authority provider
+ for (final Provider provider : authorityProviderConfiguration.getProvider()) {
+ final AuthorityProvider instance = authorityProviders.get(provider.getIdentifier());
+ instance.onConfigured(loadAuthorityProviderConfiguration(provider));
+ }
+
+ // get the authority provider instance
+ authorityProvider = getAuthorityProvider(authorityProviderIdentifier);
+
+ // ensure it was found
+ if (authorityProvider == null) {
+ throw new Exception(String.format("The specified authority provider '%s' could not be found.", authorityProviderIdentifier));
+ }
+ }
+ }
+
+ return authorityProvider;
+ }
+
+ private AuthorityProviders loadAuthorityProvidersConfiguration() throws Exception {
+ final File authorityProvidersConfigurationFile = properties.getAuthorityProviderConfiguraitonFile();
+
+ // load the users from the specified file
+ if (authorityProvidersConfigurationFile.exists()) {
+ try {
+ // find the schema
+ final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ final Schema schema = schemaFactory.newSchema(AuthorityProviders.class.getResource(AUTHORITY_PROVIDERS_XSD));
+
+ // attempt to unmarshal
+ final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
+ unmarshaller.setSchema(schema);
+ final JAXBElement<AuthorityProviders> element = unmarshaller.unmarshal(new StreamSource(authorityProvidersConfigurationFile), AuthorityProviders.class);
+ return element.getValue();
+ } catch (SAXException | JAXBException e) {
+ throw new Exception("Unable to load the authority provider configuration file at: " + authorityProvidersConfigurationFile.getAbsolutePath());
+ }
+ } else {
+ throw new Exception("Unable to find the authority provider configuration file at " + authorityProvidersConfigurationFile.getAbsolutePath());
+ }
+ }
+
+ private AuthorityProvider createAuthorityProvider(final String identifier, final String authorityProviderClassName) throws Exception {
+ // get the classloader for the specified authority provider
+ final ClassLoader authorityProviderClassLoader = ExtensionManager.getClassLoader(authorityProviderClassName);
+ if (authorityProviderClassLoader == null) {
+ throw new Exception(String.format("The specified authority provider class '%s' is not known to this nifi.", authorityProviderClassName));
+ }
+
+ // get the current context classloader
+ final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
+
+ final AuthorityProvider instance;
+ try {
+ // set the appropriate class loader
+ Thread.currentThread().setContextClassLoader(authorityProviderClassLoader);
+
+ // attempt to load the class
+ Class<?> rawAuthorityProviderClass = Class.forName(authorityProviderClassName, true, authorityProviderClassLoader);
+ Class<? extends AuthorityProvider> authorityProviderClass = rawAuthorityProviderClass.asSubclass(AuthorityProvider.class);
+
+ // otherwise create a new instance
+ Constructor constructor = authorityProviderClass.getConstructor();
+ instance = (AuthorityProvider) constructor.newInstance();
+
+ // method injection
+ performMethodInjection(instance, authorityProviderClass);
+
+ // field injection
+ performFieldInjection(instance, authorityProviderClass);
+
+ // call post construction lifecycle event
+ instance.initialize(new StandardAuthorityProviderInitializationContext(identifier, this));
+ } finally {
+ if (currentClassLoader != null) {
+ Thread.currentThread().setContextClassLoader(currentClassLoader);
+ }
+ }
+
+ return withNarLoader(instance);
+ }
+
+ private AuthorityProviderConfigurationContext loadAuthorityProviderConfiguration(final Provider provider) {
+ final Map<String, String> providerProperties = new HashMap<>();
+
+ for (final AuthorityProviderProperty property : provider.getProperty()) {
+ providerProperties.put(property.getName(), property.getValue());
+ }
+
+ return new StandardAuthorityProviderConfigurationContext(provider.getIdentifier(), providerProperties);
+ }
+
+ private void performMethodInjection(final AuthorityProvider instance, final Class authorityProviderClass) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ for (final Method method : authorityProviderClass.getMethods()) {
+ if (method.isAnnotationPresent(AuthorityProviderContext.class)) {
+ // make the method accessible
+ final boolean isAccessible = method.isAccessible();
+ method.setAccessible(true);
+
+ try {
+ final Class<?>[] argumentTypes = method.getParameterTypes();
+
+ // look for setters (single argument)
+ if (argumentTypes.length == 1) {
+ final Class<?> argumentType = argumentTypes[0];
+
+ // look for well known types
+ if (NiFiProperties.class.isAssignableFrom(argumentType)) {
+ // nifi properties injection
+ method.invoke(instance, properties);
+ } else if (ApplicationContext.class.isAssignableFrom(argumentType)) {
+ // spring application context injection
+ method.invoke(instance, applicationContext);
+ }
+ }
+ } finally {
+ method.setAccessible(isAccessible);
+ }
+ }
+ }
+
+ final Class parentClass = authorityProviderClass.getSuperclass();
+ if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) {
+ performMethodInjection(instance, parentClass);
+ }
+ }
+
+ private void performFieldInjection(final AuthorityProvider instance, final Class authorityProviderClass) throws IllegalArgumentException, IllegalAccessException {
+ for (final Field field : authorityProviderClass.getDeclaredFields()) {
+ if (field.isAnnotationPresent(AuthorityProviderContext.class)) {
+ // make the method accessible
+ final boolean isAccessible = field.isAccessible();
+ field.setAccessible(true);
+
+ try {
+ // get the type
+ final Class<?> fieldType = field.getType();
+
+ // only consider this field if it isn't set yet
+ if (field.get(instance) == null) {
+ // look for well known types
+ if (NiFiProperties.class.isAssignableFrom(fieldType)) {
+ // nifi properties injection
+ field.set(instance, properties);
+ } else if (ApplicationContext.class.isAssignableFrom(fieldType)) {
+ // spring application context injection
+ field.set(instance, applicationContext);
+ }
+ }
+
+ } finally {
+ field.setAccessible(isAccessible);
+ }
+ }
+ }
+
+ final Class parentClass = authorityProviderClass.getSuperclass();
+ if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) {
+ performFieldInjection(instance, parentClass);
+ }
+ }
+
+ /**
+ * @return a default provider to use when running unsecurely with no
+ * provider configured
+ */
+ private AuthorityProvider createDefaultProvider() {
+ return new AuthorityProvider() {
+ @Override
+ public boolean doesDnExist(String dn) throws AuthorityAccessException {
+ return false;
+ }
+
+ @Override
+ public Set<Authority> getAuthorities(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ return EnumSet.noneOf(Authority.class);
+ }
+
+ @Override
+ public void setAuthorities(String dn, Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException {
+ }
+
+ @Override
+ public Set<String> getUsers(Authority authority) throws AuthorityAccessException {
+ return new HashSet<>();
+ }
+
+ @Override
+ public void revokeUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ }
+
+ @Override
+ public void addUser(String dn, String group) throws IdentityAlreadyExistsException, AuthorityAccessException {
+ }
+
+ @Override
+ public String getGroupForUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ return null;
+ }
+
+ @Override
+ public void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException {
+ }
+
+ @Override
+ public void setUsersGroup(Set<String> dn, String group) throws UnknownIdentityException, AuthorityAccessException {
+ }
+
+ @Override
+ public void ungroupUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ }
+
+ @Override
+ public void ungroup(String group) throws AuthorityAccessException {
+ }
+
+ @Override
+ public DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException {
+ return DownloadAuthorization.approved();
+ }
+
+ @Override
+ public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
+ }
+
+ @Override
+ public void onConfigured(AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException {
+ }
+
+ @Override
+ public void preDestruction() throws ProviderDestructionException {
+ }
+ };
+ }
+
+ /**
+ * Decorates the base provider to ensure the nar context classloader is used
+ * when invoking the underlying methods.
+ *
+ * @param baseProvider base provider
+ * @return provider
+ */
+ public AuthorityProvider withNarLoader(final AuthorityProvider baseProvider) {
+ return new AuthorityProvider() {
+ @Override
+ public boolean doesDnExist(String dn) throws AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ return baseProvider.doesDnExist(dn);
+ }
+ }
+
+ @Override
+ public Set<Authority> getAuthorities(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ return baseProvider.getAuthorities(dn);
+ }
+ }
+
+ @Override
+ public void setAuthorities(String dn, Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.setAuthorities(dn, authorities);
+ }
+ }
+
+ @Override
+ public Set<String> getUsers(Authority authority) throws AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ return baseProvider.getUsers(authority);
+ }
+ }
+
+ @Override
+ public void revokeUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.revokeUser(dn);
+ }
+ }
+
+ @Override
+ public void addUser(String dn, String group) throws IdentityAlreadyExistsException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.addUser(dn, group);
+ }
+ }
+
+ @Override
+ public String getGroupForUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ return baseProvider.getGroupForUser(dn);
+ }
+ }
+
+ @Override
+ public void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.revokeGroup(group);
+ }
+ }
+
+ @Override
+ public void setUsersGroup(Set<String> dns, String group) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.setUsersGroup(dns, group);
+ }
+ }
+
+ @Override
+ public void ungroupUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.ungroupUser(dn);
+ }
+ }
+
+ @Override
+ public void ungroup(String group) throws AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.ungroup(group);
+ }
+ }
+
+ @Override
+ public DownloadAuthorization authorizeDownload(List<String> dnChain, Map<String, String> attributes) throws UnknownIdentityException, AuthorityAccessException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ return baseProvider.authorizeDownload(dnChain, attributes);
+ }
+ }
+
+ @Override
+ public void initialize(AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.initialize(initializationContext);
+ }
+ }
+
+ @Override
+ public void onConfigured(AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.onConfigured(configurationContext);
+ }
+ }
+
+ @Override
+ public void preDestruction() throws ProviderDestructionException {
+ try (final NarCloseable narCloseable = NarCloseable.withNarLoader()) {
+ baseProvider.preDestruction();
+ }
+ }
+ };
+ }
+
+ @Override
+ public Class getObjectType() {
+ return AuthorityProvider.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ if (authorityProvider != null) {
+ authorityProvider.preDestruction();
+ }
+ }
+
+ public void setProperties(NiFiProperties properties) {
+ this.properties = properties;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
index cf35c15..58caea9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
@@ -21,6 +21,7 @@ import org.apache.nifi.authorization.annotation.AuthorizerContext;
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
import org.apache.nifi.authorization.exception.AuthorizerCreationException;
import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
+import org.apache.nifi.authorization.generated.AuthorityProviders;
import org.apache.nifi.authorization.generated.Authorizers;
import org.apache.nifi.authorization.generated.Property;
import org.apache.nifi.nar.ExtensionManager;
@@ -82,7 +83,7 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
public Object getObject() throws Exception {
if (authorizer == null) {
// look up the authorizer to use
- final String authorizerIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORIZER);
+ final String authorizerIdentifier = properties.getProperty(NiFiProperties.SECURITY_USER_AUTHORITY_PROVIDER);
// ensure the authorizer class name was specified
if (StringUtils.isBlank(authorizerIdentifier)) {
@@ -121,14 +122,14 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
}
private Authorizers loadAuthorizersConfiguration() throws Exception {
- final File authorizersConfigurationFile = properties.getAuthorizerConfiguraitonFile();
+ final File authorizersConfigurationFile = properties.getAuthorityProviderConfiguraitonFile();
// load the authorizers from the specified file
if (authorizersConfigurationFile.exists()) {
try {
// find the schema
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
- final Schema schema = schemaFactory.newSchema(Authorizers.class.getResource(AUTHORIZERS_XSD));
+ final Schema schema = schemaFactory.newSchema(AuthorityProviders.class.getResource(AUTHORIZERS_XSD));
// attempt to unmarshal
final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
@@ -220,7 +221,7 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
}
final Class parentClass = authorizerClass.getSuperclass();
- if (parentClass != null && Authorizer.class.isAssignableFrom(parentClass)) {
+ if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) {
performMethodInjection(instance, parentClass);
}
}
@@ -252,7 +253,7 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
}
final Class parentClass = authorizerClass.getSuperclass();
- if (parentClass != null && Authorizer.class.isAssignableFrom(parentClass)) {
+ if (parentClass != null && AuthorityProvider.class.isAssignableFrom(parentClass)) {
performFieldInjection(instance, parentClass);
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderConfigurationContext.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderConfigurationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderConfigurationContext.java
new file mode 100644
index 0000000..45b84c8
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderConfigurationContext.java
@@ -0,0 +1,51 @@
+/*
+ * 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.authorization;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ */
+public class StandardAuthorityProviderConfigurationContext implements AuthorityProviderConfigurationContext {
+
+ private final String identifier;
+ private final Map<String, String> properties;
+
+ public StandardAuthorityProviderConfigurationContext(String identifier, Map<String, String> properties) {
+ this.identifier = identifier;
+ this.properties = Collections.unmodifiableMap(new HashMap<String, String>(properties));
+ }
+
+ @Override
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public String getProperty(String property) {
+ return properties.get(property);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderInitializationContext.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderInitializationContext.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderInitializationContext.java
new file mode 100644
index 0000000..e4b16c4
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/authorization/StandardAuthorityProviderInitializationContext.java
@@ -0,0 +1,42 @@
+/*
+ * 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.authorization;
+
+/**
+ *
+ */
+public class StandardAuthorityProviderInitializationContext implements AuthorityProviderInitializationContext {
+
+ private final String identifier;
+ private final AuthorityProviderLookup authorityProviderLookup;
+
+ public StandardAuthorityProviderInitializationContext(String identifier, AuthorityProviderLookup authorityProviderLookup) {
+ this.identifier = identifier;
+ this.authorityProviderLookup = authorityProviderLookup;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public AuthorityProviderLookup getAuthorityProviderLookup() {
+ return authorityProviderLookup;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/AccountStatus.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/AccountStatus.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/AccountStatus.java
new file mode 100644
index 0000000..d7becf1
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/AccountStatus.java
@@ -0,0 +1,47 @@
+/*
+ * 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.user;
+
+/**
+ * Represents the status of a user's account.
+ */
+public enum AccountStatus {
+
+ ACTIVE,
+ PENDING,
+ DISABLED;
+
+ /**
+ * Returns the matching status or null if the specified status does not
+ * match any statuses.
+ *
+ * @param rawStatus string form of status
+ * @return account status object
+ */
+ public static AccountStatus valueOfStatus(String rawStatus) {
+ AccountStatus desiredStatus = null;
+
+ for (AccountStatus status : values()) {
+ if (status.toString().equals(rawStatus)) {
+ desiredStatus = status;
+ break;
+ }
+ }
+
+ return desiredStatus;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java
index 3da7b3d..231b133 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/java/org/apache/nifi/user/NiFiUser.java
@@ -17,52 +17,123 @@
package org.apache.nifi.user;
import java.io.Serializable;
+import java.util.Date;
+import java.util.EnumSet;
import java.util.Objects;
+import java.util.Set;
+import org.apache.nifi.authorization.Authority;
+import org.apache.commons.lang3.StringUtils;
/**
* An NiFiUser.
*/
public class NiFiUser implements Serializable {
- public static final NiFiUser ANONYMOUS = new NiFiUser("anonymous");
+ public static final String ANONYMOUS_USER_IDENTITY = "anonymous";
+ private String id;
private String identity;
private String userName;
+ private String userGroup;
+ private String justification;
+
+ private Date creation;
+ private Date lastVerified;
+ private Date lastAccessed;
+
+ private AccountStatus status;
+ private EnumSet<Authority> authorities;
private NiFiUser chain;
- public NiFiUser(String identity) {
- this(identity, null, null);
+ /* getters / setters */
+ public Date getCreation() {
+ return creation;
}
- public NiFiUser(String identity, String userName) {
- this(identity, userName, null);
+ public void setCreation(Date creation) {
+ this.creation = creation;
}
- public NiFiUser(String identity, NiFiUser chain) {
- this(identity, null, chain);
+ public String getIdentity() {
+ return identity;
}
- public NiFiUser(String identity, String userName, NiFiUser chain) {
+ public void setIdentity(String identity) {
this.identity = identity;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
this.userName = userName;
- this.chain = chain;
}
- /* getters / setters */
+ public String getUserGroup() {
+ return userGroup;
+ }
- public String getIdentity() {
- return identity;
+ public void setUserGroup(String userGroup) {
+ this.userGroup = userGroup;
}
- public String getUserName() {
- return userName;
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getJustification() {
+ return justification;
+ }
+
+ public void setJustification(String justification) {
+ this.justification = justification;
+ }
+
+ public AccountStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(AccountStatus status) {
+ this.status = status;
+ }
+
+ public Date getLastVerified() {
+ return lastVerified;
+ }
+
+ public void setLastVerified(Date lastVerified) {
+ this.lastVerified = lastVerified;
+ }
+
+ public Date getLastAccessed() {
+ return lastAccessed;
+ }
+
+ public void setLastAccessed(Date lastAccessed) {
+ this.lastAccessed = lastAccessed;
}
public NiFiUser getChain() {
return chain;
}
+ public void setChain(NiFiUser chain) {
+ this.chain = chain;
+ }
+
+ public Set<Authority> getAuthorities() {
+ if (authorities == null) {
+ authorities = EnumSet.noneOf(Authority.class);
+ }
+ return authorities;
+ }
+
@Override
public boolean equals(Object obj) {
if (obj == null) {
@@ -87,7 +158,7 @@ public class NiFiUser implements Serializable {
@Override
public String toString() {
- return String.format("identity[%s], userName[%s]", getIdentity(), getUserName(), ", ");
+ return String.format("identity[%s], userName[%s], justification[%s], authorities[%s]", getIdentity(), getUserName(), getJustification(), StringUtils.join(getAuthorities(), ", "));
}
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml
index bc3662c..3a46314 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/resources/nifi-administration-context.xml
@@ -18,34 +18,41 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
- <!-- user/entity authorizer -->
- <bean id="authorizer" class="org.apache.nifi.authorization.AuthorizerFactoryBean">
+ <!-- user authority provider -->
+ <bean id="authorityProvider" class="org.apache.nifi.authorization.AuthorityProviderFactoryBean" depends-on="clusterManager">
<property name="properties" ref="nifiProperties"/>
</bean>
- <!-- initialize the user key data source -->
- <bean id="keyDataSource" class="org.apache.nifi.admin.KeyDataSourceFactoryBean" destroy-method="shutdown">
+ <!-- user/entity authorizer -->
+ <bean id="authorizer" class="org.apache.nifi.authorization.AuthorizerFactoryBean" depends-on="clusterManager">
<property name="properties" ref="nifiProperties"/>
</bean>
- <!-- initialize the audit data source -->
- <bean id="auditDataSource" class="org.apache.nifi.admin.AuditDataSourceFactoryBean" destroy-method="shutdown">
+ <!-- initialize the user data source -->
+ <bean id="userDataSource" class="org.apache.nifi.admin.UserDataSourceFactoryBean" destroy-method="shutdown">
<property name="properties" ref="nifiProperties"/>
</bean>
- <!-- initialize the user key transaction builder -->
- <bean id="keyTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder">
- <property name="dataSource" ref="keyDataSource"/>
+ <!-- initialize the data source -->
+ <bean id="auditDataSource" class="org.apache.nifi.admin.AuditDataSourceFactoryBean" destroy-method="shutdown" depends-on="userDataSource">
+ <property name="properties" ref="nifiProperties"/>
</bean>
-
+
+ <!-- initialize the user transaction builder -->
+ <bean id="userTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder">
+ <property name="authorityProvider" ref="authorityProvider"/>
+ <property name="dataSource" ref="userDataSource"/>
+ </bean>
+
<!-- initialize the audit transaction builder -->
<bean id="auditTransactionBuilder" class="org.apache.nifi.admin.service.transaction.impl.StandardTransactionBuilder">
+ <property name="authorityProvider" ref="authorityProvider"/>
<property name="dataSource" ref="auditDataSource"/>
</bean>
-
+
<!-- administration service -->
- <bean id="userService" class="org.apache.nifi.admin.service.impl.StandardUserService">
- <property name="transactionBuilder" ref="keyTransactionBuilder"/>
+ <bean id="userService" class="org.apache.nifi.admin.service.impl.StandardUserService" init-method="seedUserAccounts">
+ <property name="transactionBuilder" ref="userTransactionBuilder"/>
<property name="properties" ref="nifiProperties"/>
</bean>
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/xsd/authority-providers.xsd
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/xsd/authority-providers.xsd b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/xsd/authority-providers.xsd
new file mode 100644
index 0000000..1a5fe50
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/main/xsd/authority-providers.xsd
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <!-- role -->
+ <xs:complexType name="Provider">
+ <xs:sequence>
+ <xs:element name="identifier" type="AuthorityProviderNonEmptyStringType"/>
+ <xs:element name="class" type="AuthorityProviderNonEmptyStringType"/>
+ <xs:element name="property" type="AuthorityProviderProperty" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
+ <!-- Name/Value properties-->
+ <xs:complexType name="AuthorityProviderProperty">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="AuthorityProviderNonEmptyStringType"></xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="AuthorityProviderNonEmptyStringType">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- users -->
+ <xs:element name="authorityProviders">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="provider" type="Provider" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/AuthorizeUserActionTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/AuthorizeUserActionTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/AuthorizeUserActionTest.java
new file mode 100644
index 0000000..8d3c15a
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/AuthorizeUserActionTest.java
@@ -0,0 +1,433 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.Set;
+import org.apache.nifi.admin.dao.AuthorityDAO;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountDisabledException;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.admin.service.AccountPendingException;
+import org.apache.nifi.admin.service.AdministrationException;
+import org.apache.nifi.authorization.Authority;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+import org.apache.nifi.user.AccountStatus;
+import org.apache.nifi.user.NiFiUser;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ *
+ */
+public class AuthorizeUserActionTest {
+
+ private static final String USER_ID_6 = "6";
+ private static final String USER_ID_7 = "7";
+ private static final String USER_ID_8 = "8";
+ private static final String USER_ID_9 = "9";
+ private static final String USER_ID_10 = "10";
+ private static final String USER_ID_11 = "11";
+
+ private static final String USER_IDENTITY_1 = "authority access exception while searching for user";
+ private static final String USER_IDENTITY_2 = "unknown user";
+ private static final String USER_IDENTITY_3 = "user removed after checking existence";
+ private static final String USER_IDENTITY_4 = "access exception getting authorities";
+ private static final String USER_IDENTITY_5 = "error creating user account";
+ private static final String USER_IDENTITY_6 = "create user general sequence";
+ private static final String USER_IDENTITY_7 = "existing user requires verification";
+ private static final String USER_IDENTITY_8 = "existing user does not require verification";
+ private static final String USER_IDENTITY_9 = "existing pending user";
+ private static final String USER_IDENTITY_10 = "existing disabled user";
+ private static final String USER_IDENTITY_11 = "existing user is now unknown in the authority provider";
+
+ private DAOFactory daoFactory;
+ private UserDAO userDao;
+ private AuthorityDAO authorityDao;
+ private AuthorityProvider authorityProvider;
+
+ @Before
+ public void setup() throws Exception {
+ // mock the user dao
+ userDao = Mockito.mock(UserDAO.class);
+ Mockito.doAnswer(new Answer<NiFiUser>() {
+ @Override
+ public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String id = (String) args[0];
+
+ NiFiUser user = null;
+ if (USER_ID_7.equals(id)) {
+ user = new NiFiUser();
+ user.setId(USER_ID_7);
+ user.setIdentity(USER_IDENTITY_7);
+ user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
+ } else if (USER_ID_8.equals(id)) {
+ user = new NiFiUser();
+ user.setId(USER_ID_8);
+ user.setIdentity(USER_IDENTITY_8);
+ user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
+ user.setLastVerified(new Date());
+ } else if (USER_ID_11.equals(id)) {
+ user = new NiFiUser();
+ user.setId(USER_ID_11);
+ user.setIdentity(USER_IDENTITY_11);
+ user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
+ user.setStatus(AccountStatus.ACTIVE);
+ }
+
+ return user;
+ }
+ }).when(userDao).findUserById(Mockito.anyString());
+ Mockito.doAnswer(new Answer<NiFiUser>() {
+ @Override
+ public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String dn = (String) args[0];
+
+ NiFiUser user = null;
+ switch (dn) {
+ case USER_IDENTITY_7:
+ user = new NiFiUser();
+ user.setId(USER_ID_7);
+ user.setIdentity(USER_IDENTITY_7);
+ user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
+ break;
+ case USER_IDENTITY_8:
+ user = new NiFiUser();
+ user.setId(USER_ID_8);
+ user.setIdentity(USER_IDENTITY_8);
+ user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
+ user.setLastVerified(new Date());
+ break;
+ case USER_IDENTITY_9:
+ user = new NiFiUser();
+ user.setId(USER_ID_9);
+ user.setIdentity(USER_IDENTITY_9);
+ user.setStatus(AccountStatus.PENDING);
+ break;
+ case USER_IDENTITY_10:
+ user = new NiFiUser();
+ user.setId(USER_ID_10);
+ user.setIdentity(USER_IDENTITY_10);
+ user.setStatus(AccountStatus.DISABLED);
+ break;
+ case USER_IDENTITY_11:
+ user = new NiFiUser();
+ user.setId(USER_ID_11);
+ user.setIdentity(USER_IDENTITY_11);
+ user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_MONITOR));
+ user.setStatus(AccountStatus.ACTIVE);
+ break;
+ }
+
+ return user;
+ }
+ }).when(userDao).findUserByDn(Mockito.anyString());
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ NiFiUser user = (NiFiUser) args[0];
+ switch (user.getIdentity()) {
+ case USER_IDENTITY_5:
+ throw new DataAccessException();
+ case USER_IDENTITY_6:
+ user.setId(USER_ID_6);
+ break;
+ }
+
+ // do nothing
+ return null;
+ }
+ }).when(userDao).createUser(Mockito.any(NiFiUser.class));
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ NiFiUser user = (NiFiUser) args[0];
+
+ // do nothing
+ return null;
+ }
+ }).when(userDao).updateUser(Mockito.any(NiFiUser.class));
+
+ // mock the authority dao
+ authorityDao = Mockito.mock(AuthorityDAO.class);
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ Set<Authority> authorities = (Set<Authority>) args[0];
+ String id = (String) args[1];
+
+ // do nothing
+ return null;
+ }
+ }).when(authorityDao).createAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ Set<Authority> authorities = (Set<Authority>) args[0];
+ String id = (String) args[1];
+
+ // do nothing
+ return null;
+ }
+ }).when(authorityDao).deleteAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
+
+ // mock the dao factory
+ daoFactory = Mockito.mock(DAOFactory.class);
+ Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
+ Mockito.when(daoFactory.getAuthorityDAO()).thenReturn(authorityDao);
+
+ // mock the authority provider
+ authorityProvider = Mockito.mock(AuthorityProvider.class);
+ Mockito.doAnswer(new Answer<Boolean>() {
+ @Override
+ public Boolean answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String dn = (String) args[0];
+ switch (dn) {
+ case USER_IDENTITY_1:
+ throw new AuthorityAccessException(StringUtils.EMPTY);
+ case USER_IDENTITY_2:
+ return false;
+ }
+
+ return true;
+ }
+ }).when(authorityProvider).doesDnExist(Mockito.anyString());
+ Mockito.doAnswer(new Answer<Set<Authority>>() {
+ @Override
+ public Set<Authority> answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String dn = (String) args[0];
+ Set<Authority> authorities = EnumSet.noneOf(Authority.class);
+ switch (dn) {
+ case USER_IDENTITY_3:
+ throw new UnknownIdentityException(StringUtils.EMPTY);
+ case USER_IDENTITY_4:
+ throw new AuthorityAccessException(StringUtils.EMPTY);
+ case USER_IDENTITY_6:
+ authorities.add(Authority.ROLE_MONITOR);
+ break;
+ case USER_IDENTITY_7:
+ authorities.add(Authority.ROLE_DFM);
+ break;
+ case USER_IDENTITY_9:
+ throw new UnknownIdentityException(StringUtils.EMPTY);
+ case USER_IDENTITY_10:
+ throw new UnknownIdentityException(StringUtils.EMPTY);
+ case USER_IDENTITY_11:
+ throw new UnknownIdentityException(StringUtils.EMPTY);
+ }
+
+ return authorities;
+ }
+ }).when(authorityProvider).getAuthorities(Mockito.anyString());
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String dn = (String) args[0];
+ Set<Authority> authorites = (Set<Authority>) args[1];
+
+ // do nothing
+ return null;
+ }
+ }).when(authorityProvider).setAuthorities(Mockito.anyString(), Mockito.anySet());
+ }
+
+ /**
+ * Tests AuthorityAccessException in doesDnExist.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AdministrationException.class)
+ public void testAuthorityAccessExceptionInDoesDnExist() throws Exception {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_1, 0);
+ authorizeUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Test unknown user in the authority provider.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AccountNotFoundException.class)
+ public void testUnknownUser() throws Exception {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_2, 0);
+ authorizeUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Test a user thats been removed after checking their existence.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AccountNotFoundException.class)
+ public void testUserRemovedAfterCheckingExistence() throws Exception {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_3, 0);
+ authorizeUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Testing AuthorityAccessException when getting authorities.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AdministrationException.class)
+ public void testAuthorityAccessException() throws Exception {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_4, 0);
+ authorizeUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Testing DataAccessException while creating user accounts.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = DataAccessException.class)
+ public void testErrorCreatingUserAccount() throws Exception {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_5, 0);
+ authorizeUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Tests the general case when a user account is created.
+ *
+ * @throws Exception ex
+ */
+ @Test
+ public void testAccountCreation() throws Exception {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_6, 0);
+ NiFiUser user = authorizeUser.execute(daoFactory, authorityProvider);
+
+ // verify the user
+ Assert.assertEquals(USER_IDENTITY_6, user.getIdentity());
+ Assert.assertEquals(1, user.getAuthorities().size());
+ Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_MONITOR));
+
+ // verify interaction with dao and provider
+ Mockito.verify(userDao, Mockito.times(1)).createUser(user);
+ }
+
+ /**
+ * Tests the general case when there is an existing user account that
+ * requires verification.
+ *
+ * @throws Exception ex
+ */
+ @Test
+ public void testExistingUserRequiresVerification() throws Exception {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_7, 0);
+ NiFiUser user = authorizeUser.execute(daoFactory, authorityProvider);
+
+ // verify the user
+ Assert.assertEquals(USER_IDENTITY_7, user.getIdentity());
+ Assert.assertEquals(1, user.getAuthorities().size());
+ Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_DFM));
+
+ // verify interaction with dao and provider
+ Mockito.verify(userDao, Mockito.times(1)).updateUser(user);
+ Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(EnumSet.of(Authority.ROLE_DFM), USER_ID_7);
+ }
+
+ /**
+ * Tests the general case when there is an existing user account that does
+ * not require verification.
+ *
+ * @throws Exception ex
+ */
+ @Test
+ public void testExistingUserNoVerification() throws Exception {
+ // disabling verification by passing in a large cache duration
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_8, Integer.MAX_VALUE);
+ NiFiUser user = authorizeUser.execute(daoFactory, authorityProvider);
+
+ // verify the user
+ Assert.assertEquals(USER_IDENTITY_8, user.getIdentity());
+ Assert.assertEquals(1, user.getAuthorities().size());
+ Assert.assertTrue(user.getAuthorities().contains(Authority.ROLE_MONITOR));
+
+ // verify interaction with dao and provider
+ Mockito.verify(userDao, Mockito.times(1)).updateUser(user);
+ Mockito.verify(authorityDao, Mockito.never()).createAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_8));
+ Mockito.verify(authorityDao, Mockito.never()).deleteAuthorities(Mockito.anySet(), Mockito.eq(USER_ID_8));
+ }
+
+ /**
+ * Tests existing users whose accounts are in a pending status.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AccountPendingException.class)
+ public void testExistingPendingUser() throws Exception {
+ // disabling verification by passing in a large cache duration
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_9, Integer.MAX_VALUE);
+ authorizeUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Tests existing users whose accounts are in a disabled status.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AccountDisabledException.class)
+ public void testExistingDisabledUser() throws Exception {
+ // disabling verification by passing in a large cache duration
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_10, Integer.MAX_VALUE);
+ authorizeUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Tests the general case where there is an active user that has been
+ * removed from the authority provider.
+ *
+ * @throws Exception ex
+ */
+ @Test
+ public void testExistingActiveUserNotFoundInProvider() throws Exception {
+ try {
+ AuthorizeUserAction authorizeUser = new AuthorizeUserAction(USER_IDENTITY_11, 0);
+ authorizeUser.execute(daoFactory, authorityProvider);
+
+ Assert.fail();
+ } catch (AccountDisabledException ade) {
+ ArgumentCaptor<NiFiUser> user = ArgumentCaptor.forClass(NiFiUser.class);
+
+ // verify interaction with dao
+ Mockito.verify(userDao, Mockito.times(1)).updateUser(user.capture());
+
+ // verify user
+ Assert.assertEquals(AccountStatus.DISABLED, user.getValue().getStatus());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/CreateUserActionTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/CreateUserActionTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/CreateUserActionTest.java
new file mode 100644
index 0000000..e372781
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/CreateUserActionTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.EnumSet;
+import java.util.Set;
+import org.apache.nifi.admin.dao.AuthorityDAO;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.authorization.Authority;
+import org.apache.nifi.user.NiFiUser;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Test cases for creating a user.
+ */
+public class CreateUserActionTest {
+
+ private final String USER_ID_2 = "2";
+ private final String USER_ID_3 = "3";
+
+ private final String USER_IDENTITY_1 = "data access exception when creating user";
+ private final String USER_IDENTITY_3 = "general create user case";
+
+ private DAOFactory daoFactory;
+ private UserDAO userDao;
+ private AuthorityDAO authorityDao;
+
+ @Before
+ public void setup() throws Exception {
+ // mock the user dao
+ userDao = Mockito.mock(UserDAO.class);
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ NiFiUser user = (NiFiUser) args[0];
+
+ if (USER_IDENTITY_1.equals(user.getIdentity())) {
+ throw new DataAccessException();
+ } else if (USER_IDENTITY_3.equals(user.getIdentity())) {
+ user.setId(USER_ID_3);
+ }
+
+ // do nothing
+ return null;
+ }
+ }).when(userDao).createUser(Mockito.any(NiFiUser.class));
+
+ // mock the authority dao
+ authorityDao = Mockito.mock(AuthorityDAO.class);
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ Set<Authority> authorities = (Set<Authority>) args[0];
+ String id = (String) args[1];
+
+ if (USER_ID_2.equals(id)) {
+ throw new DataAccessException(StringUtils.EMPTY);
+ }
+
+ // do nothing
+ return null;
+ }
+ }).when(authorityDao).createAuthorities(Mockito.anySetOf(Authority.class), Mockito.anyString());
+
+ // mock the dao factory
+ daoFactory = Mockito.mock(DAOFactory.class);
+ Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
+ Mockito.when(daoFactory.getAuthorityDAO()).thenReturn(authorityDao);
+ }
+
+ /**
+ * Tests DataAccessExceptions that occur while creating user accounts.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = DataAccessException.class)
+ public void testExceptionCreatingUser() throws Exception {
+ NiFiUser user = new NiFiUser();
+ user.setIdentity(USER_IDENTITY_1);
+
+ CreateUserAction createUser = new CreateUserAction(user);
+ createUser.execute(daoFactory, null);
+ }
+
+ /**
+ * Tests DataAccessExceptions that occur while create user authorities.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = DataAccessException.class)
+ public void testExceptionCreatingAuthoroties() throws Exception {
+ NiFiUser user = new NiFiUser();
+ user.setId(USER_ID_2);
+
+ CreateUserAction createUser = new CreateUserAction(user);
+ createUser.execute(daoFactory, null);
+ }
+
+ /**
+ * General case for creating a user.
+ *
+ * @throws Exception ex
+ */
+ @Test
+ public void testCreateUserAccount() throws Exception {
+ NiFiUser user = new NiFiUser();
+ user.setIdentity(USER_IDENTITY_3);
+ user.getAuthorities().addAll(EnumSet.of(Authority.ROLE_DFM, Authority.ROLE_ADMIN));
+
+ CreateUserAction createUser = new CreateUserAction(user);
+ createUser.execute(daoFactory, null);
+
+ // verify the user
+ Assert.assertEquals(USER_ID_3, user.getId());
+
+ // verify interaction with dao
+ Mockito.verify(userDao, Mockito.times(1)).createUser(user);
+ Mockito.verify(authorityDao, Mockito.times(1)).createAuthorities(user.getAuthorities(), USER_ID_3);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/DisableUserActionTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/DisableUserActionTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/DisableUserActionTest.java
new file mode 100644
index 0000000..b5f0a7f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/DisableUserActionTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.admin.service.action;
+
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.admin.service.AdministrationException;
+import org.apache.nifi.authorization.AuthorityProvider;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.user.AccountStatus;
+import org.apache.nifi.user.NiFiUser;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.admin.dao.KeyDAO;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class DisableUserActionTest {
+
+ private static final String USER_ID_1 = "1";
+ private static final String USER_ID_2 = "2";
+ private static final String USER_ID_3 = "3";
+ private static final String USER_ID_4 = "4";
+
+ private static final String USER_IDENTITY_3 = "authority access exception";
+ private static final String USER_IDENTITY_4 = "general disable user case";
+
+ private DAOFactory daoFactory;
+ private UserDAO userDao;
+ private KeyDAO keyDao;
+ private AuthorityProvider authorityProvider;
+
+ @Before
+ public void setup() throws Exception {
+ // mock the user dao
+ userDao = Mockito.mock(UserDAO.class);
+ Mockito.doAnswer(new Answer<NiFiUser>() {
+ @Override
+ public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String id = (String) args[0];
+
+ NiFiUser user = null;
+ if (USER_ID_1.equals(id)) {
+ // leave user uninitialized
+ } else if (USER_ID_2.equals(id)) {
+ user = new NiFiUser();
+ user.setId(id);
+ } else if (USER_ID_3.equals(id)) {
+ user = new NiFiUser();
+ user.setId(id);
+ user.setIdentity(USER_IDENTITY_3);
+ } else if (USER_ID_4.equals(id)) {
+ user = new NiFiUser();
+ user.setId(id);
+ user.setIdentity(USER_IDENTITY_4);
+ user.setStatus(AccountStatus.ACTIVE);
+ }
+ return user;
+ }
+ }).when(userDao).findUserById(Mockito.anyString());
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ NiFiUser user = (NiFiUser) args[0];
+
+ if (USER_ID_2.equals(user.getId())) {
+ throw new DataAccessException(StringUtils.EMPTY);
+ }
+
+ // do nothing
+ return null;
+ }
+ }).when(userDao).updateUser(Mockito.any(NiFiUser.class));
+
+ // mock the dao factory
+ keyDao = Mockito.mock(KeyDAO.class);
+ Mockito.doNothing().when(keyDao).deleteKeys(Matchers.anyString());
+
+ // mock the dao factory
+ daoFactory = Mockito.mock(DAOFactory.class);
+ Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
+ Mockito.when(daoFactory.getKeyDAO()).thenReturn(keyDao);
+
+ // mock the authority provider
+ authorityProvider = Mockito.mock(AuthorityProvider.class);
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String dn = (String) args[0];
+
+ if (USER_IDENTITY_3.equals(dn)) {
+ throw new AuthorityAccessException(StringUtils.EMPTY);
+ }
+
+ // do nothing
+ return null;
+ }
+ }).when(authorityProvider).revokeUser(Mockito.anyString());
+ }
+
+ /**
+ * Tests the case when the user account is unknown.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AccountNotFoundException.class)
+ public void testUnknownUserAccount() throws Exception {
+ DisableUserAction disableUser = new DisableUserAction(USER_ID_1);
+ disableUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Tests the case when a DataAccessException is thrown by the userDao.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = DataAccessException.class)
+ public void testDataAccessExceptionInUserDao() throws Exception {
+ DisableUserAction disableUser = new DisableUserAction(USER_ID_2);
+ disableUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Tests the case when a AuthorityAccessException is thrown by the provider.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = AdministrationException.class)
+ public void testAuthorityAccessExceptionInProvider() throws Exception {
+ DisableUserAction disableUser = new DisableUserAction(USER_ID_3);
+ disableUser.execute(daoFactory, authorityProvider);
+ }
+
+ /**
+ * Tests the general case when the user is disabled.
+ *
+ * @throws Exception ex
+ */
+ @Test
+ public void testDisableUser() throws Exception {
+ DisableUserAction disableUser = new DisableUserAction(USER_ID_4);
+ NiFiUser user = disableUser.execute(daoFactory, authorityProvider);
+
+ // verify the user
+ Assert.assertEquals(USER_ID_4, user.getId());
+ Assert.assertEquals(USER_IDENTITY_4, user.getIdentity());
+ Assert.assertEquals(AccountStatus.DISABLED, user.getStatus());
+
+ // verify the interaction with the dao and provider
+ Mockito.verify(userDao, Mockito.times(1)).updateUser(user);
+ Mockito.verify(authorityProvider, Mockito.times(1)).revokeUser(USER_IDENTITY_4);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/3f4ac315/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/InvalidateUserAccountActionTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/InvalidateUserAccountActionTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/InvalidateUserAccountActionTest.java
new file mode 100644
index 0000000..cffd280
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-administration/src/test/java/org/apache/nifi/admin/service/action/InvalidateUserAccountActionTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.admin.service.action;
+
+import java.util.Date;
+import org.junit.Assert;
+import org.apache.nifi.admin.dao.DAOFactory;
+import org.apache.nifi.admin.dao.DataAccessException;
+import org.apache.nifi.admin.dao.UserDAO;
+import org.apache.nifi.admin.service.AccountNotFoundException;
+import org.apache.nifi.user.NiFiUser;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Test case for InvalidateUserAccountAction.
+ */
+public class InvalidateUserAccountActionTest {
+
+ private static final String USER_ID_1 = "1";
+ private static final String USER_ID_2 = "2";
+ private static final String USER_ID_3 = "3";
+
+ private DAOFactory daoFactory;
+ private UserDAO userDao;
+
+ @Before
+ public void setup() throws Exception {
+ // mock the user dao
+ userDao = Mockito.mock(UserDAO.class);
+ Mockito.doAnswer(new Answer<NiFiUser>() {
+ @Override
+ public NiFiUser answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ String id = (String) args[0];
+
+ NiFiUser user = null;
+ if (USER_ID_1.equals(id)) {
+ // leave uninitialized
+ } else if (USER_ID_2.equals(id)) {
+ user = new NiFiUser();
+ user.setId(USER_ID_2);
+ } else if (USER_ID_3.equals(id)) {
+ user = new NiFiUser();
+ user.setId(USER_ID_3);
+ user.setLastVerified(new Date());
+ }
+ return user;
+ }
+ }).when(userDao).findUserById(Mockito.anyString());
+ Mockito.doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ NiFiUser user = (NiFiUser) args[0];
+
+ if (USER_ID_2.equals(user.getId())) {
+ throw new DataAccessException(StringUtils.EMPTY);
+ }
+
+ // do nothing
+ return null;
+ }
+ }).when(userDao).updateUser(Mockito.any(NiFiUser.class));
+
+ // mock the dao factory
+ daoFactory = Mockito.mock(DAOFactory.class);
+ Mockito.when(daoFactory.getUserDAO()).thenReturn(userDao);
+ }
+
+ @Test(expected = AccountNotFoundException.class)
+ public void testAccountNotFoundException() throws Exception {
+ InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(USER_ID_1);
+ invalidateUserAccount.execute(daoFactory, null);
+ }
+
+ /**
+ * Tests when a data access exception occurs when updating the user record.
+ *
+ * @throws Exception ex
+ */
+ @Test(expected = DataAccessException.class)
+ public void testDataAccessException() throws Exception {
+ InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(USER_ID_2);
+ invalidateUserAccount.execute(daoFactory, null);
+ }
+
+ /**
+ * Tests the general case of invalidating a user.
+ *
+ * @throws Exception ex
+ */
+ @Test
+ public void testInvalidateUser() throws Exception {
+ InvalidateUserAccountAction invalidateUserAccount = new InvalidateUserAccountAction(USER_ID_3);
+ invalidateUserAccount.execute(daoFactory, null);
+
+ // verify the interaction with the dao
+ ArgumentCaptor<NiFiUser> userCaptor = ArgumentCaptor.forClass(NiFiUser.class);
+ Mockito.verify(userDao, Mockito.times(1)).updateUser(userCaptor.capture());
+
+ // verify the user
+ NiFiUser user = userCaptor.getValue();
+ Assert.assertEquals(USER_ID_3, user.getId());
+ Assert.assertNull(user.getLastVerified());
+ }
+}