/*
 * 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.usergrid.management.cassandra;


import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.inject.Injector;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.usergrid.corepersistence.service.AggregationService;
import org.apache.usergrid.corepersistence.service.AggregationServiceFactory;
import org.apache.usergrid.corepersistence.service.ApplicationService;
import org.apache.usergrid.corepersistence.util.CpNamingUtils;
import org.apache.usergrid.exception.ConflictException;
import org.apache.usergrid.locking.Lock;
import org.apache.usergrid.locking.LockManager;
import org.apache.usergrid.management.*;
import org.apache.usergrid.management.exceptions.*;
import org.apache.usergrid.persistence.*;
import org.apache.usergrid.persistence.Query.Level;
import org.apache.usergrid.persistence.cache.CacheFactory;
import org.apache.usergrid.persistence.cache.CacheScope;
import org.apache.usergrid.persistence.cache.ScopedCache;
import org.apache.usergrid.persistence.cassandra.CassandraService;
import org.apache.usergrid.persistence.core.scope.ApplicationScope;
import org.apache.usergrid.persistence.entities.Application;
import org.apache.usergrid.persistence.entities.Group;
import org.apache.usergrid.persistence.entities.User;
import org.apache.usergrid.persistence.exceptions.ApplicationAlreadyExistsException;
import org.apache.usergrid.persistence.exceptions.DuplicateUniquePropertyExistsException;
import org.apache.usergrid.persistence.exceptions.EntityNotFoundException;
import org.apache.usergrid.persistence.index.query.Identifier;
import org.apache.usergrid.persistence.model.entity.Id;
import org.apache.usergrid.persistence.model.entity.SimpleId;
import org.apache.usergrid.security.AuthPrincipalInfo;
import org.apache.usergrid.security.AuthPrincipalType;
import org.apache.usergrid.security.crypto.EncryptionService;
import org.apache.usergrid.security.oauth.AccessInfo;
import org.apache.usergrid.security.oauth.ClientCredentialsInfo;
import org.apache.usergrid.security.salt.SaltProvider;
import org.apache.usergrid.security.shiro.PrincipalCredentialsToken;
import org.apache.usergrid.security.shiro.credentials.ApplicationClientCredentials;
import org.apache.usergrid.security.shiro.credentials.OrganizationClientCredentials;
import org.apache.usergrid.security.shiro.principals.ApplicationPrincipal;
import org.apache.usergrid.security.shiro.principals.OrganizationPrincipal;
import org.apache.usergrid.security.shiro.utils.LocalShiroCache;
import org.apache.usergrid.security.shiro.utils.SubjectUtils;
import org.apache.usergrid.security.tokens.TokenCategory;
import org.apache.usergrid.security.tokens.TokenInfo;
import org.apache.usergrid.security.tokens.TokenService;
import org.apache.usergrid.security.tokens.exceptions.TokenException;
import org.apache.usergrid.services.*;
import org.apache.usergrid.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import rx.Observable;

import java.nio.ByteBuffer;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;

import static java.lang.Boolean.parseBoolean;
import static org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString;
import static org.apache.commons.codec.digest.DigestUtils.sha;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.usergrid.locking.LockHelper.getUniqueUpdateLock;
import static org.apache.usergrid.management.AccountCreationProps.*;
import static org.apache.usergrid.management.OrganizationConfigProps.ORGPROPERTIES_ADMIN_SYSADMIN_EMAIL;
import static org.apache.usergrid.management.OrganizationConfigProps.WorkflowUrl;
import static org.apache.usergrid.persistence.CredentialsInfo.getCredentialsSecret;
import static org.apache.usergrid.persistence.Schema.*;
import static org.apache.usergrid.persistence.Schema.PROPERTY_UUID;
import static org.apache.usergrid.persistence.entities.Activity.*;
import static org.apache.usergrid.persistence.entities.Activity.PROPERTY_TITLE;
import static org.apache.usergrid.security.AuthPrincipalType.*;
import static org.apache.usergrid.security.oauth.ClientCredentialsInfo.getTypeFromClientId;
import static org.apache.usergrid.security.oauth.ClientCredentialsInfo.getUUIDFromClientId;
import static org.apache.usergrid.security.tokens.TokenCategory.ACCESS;
import static org.apache.usergrid.security.tokens.TokenCategory.EMAIL;
import static org.apache.usergrid.services.ServiceParameter.parameters;
import static org.apache.usergrid.services.ServicePayload.payload;
import static org.apache.usergrid.services.ServiceResults.genericServiceResults;
import static org.apache.usergrid.utils.ClassUtils.cast;
import static org.apache.usergrid.utils.ConversionUtils.bytes;
import static org.apache.usergrid.utils.ConversionUtils.uuid;
import static org.apache.usergrid.utils.ListUtils.anyNull;
import static org.apache.usergrid.utils.MapUtils.hashMap;
import static org.apache.usergrid.utils.PasswordUtils.mongoPassword;


public class ManagementServiceImpl implements ManagementService {
    private static final Logger logger = LoggerFactory.getLogger( ManagementServiceImpl.class );

    /** Key for the user's pin */
    protected static final String USER_PIN = "pin";

    /** Key for the user's oauth secret */
    protected static final String USER_TOKEN = "secret";

    /** Key for the user's mongo password */
    protected static final String USER_MONGO_PASSWORD = "mongo_pwd";

    /** Key for the user's password */
    protected static final String USER_PASSWORD = "password";

    protected static final String USER_PASSWORD_HISTORY = "password_history";

    private static final String TOKEN_TYPE_ACTIVATION = "activate";

    private static final String TOKEN_TYPE_PASSWORD_RESET = "resetpw";

    private static final String TOKEN_TYPE_CONFIRM = "confirm";

    public static final String ORG_APP_RELATIONSHIP = "applications";

    public static final String OAUTH_SECRET_SALT = "super secret oauth value";

    private static final String ORGANIZATION_PROPERTIES_DICTIONARY = "orgProperties";
    private static final String ORGANIZATION_CONFIG_DICTIONARY = "orgConfig";
    public static final String REGISTRATION_REQUIRES_ADMIN_APPROVAL = "registration_requires_admin_approval";
    public static final String REGISTRATION_REQUIRES_EMAIL_CONFIRMATION = "registration_requires_email_confirmation";
    public static final String NOTIFY_ADMIN_OF_NEW_USERS = "notify_admin_of_new_users";

    public static final String ORG_CONFIG_CACHE_PROP = "usergrid.orgconfig.cache.timeout";

    protected ServiceManagerFactory smf;

    protected EntityManagerFactory emf;

    protected AccountCreationPropsImpl properties;

    protected OrganizationConfigPropsImpl orgConfigProperties;

    protected LockManager lockManager;

    protected TokenService tokens;

    protected SaltProvider saltProvider;

    @Autowired
    protected MailUtils mailUtils;

    protected EncryptionService encryptionService;

    protected CacheFactory cacheFactory;

    protected AggregationServiceFactory aggregationServiceFactory;

    protected ApplicationService service;

    protected LocalShiroCache localShiroCache;


    private LoadingCache<UUID, OrganizationConfig> orgConfigByAppCache = CacheBuilder.newBuilder().maximumSize( 1000 )
        .expireAfterWrite( Long.valueOf( System.getProperty(ORG_CONFIG_CACHE_PROP, "30000") ) , TimeUnit.MILLISECONDS)
        .build( new CacheLoader<UUID, OrganizationConfig>() {
            public OrganizationConfig load( UUID applicationInfoId ) {

                try {

                    if (applicationInfoId != null && applicationInfoId != CpNamingUtils.MANAGEMENT_APPLICATION_ID) {

                        final EntityManager em = emf.getEntityManager(smf.getManagementAppId());

                        Results r = em.getSourceEntities(
                            new SimpleEntityRef(CpNamingUtils.APPLICATION_INFO, applicationInfoId),
                            ORG_APP_RELATIONSHIP, Group.ENTITY_TYPE, Level.ALL_PROPERTIES);

                        Group org = (Group) r.getEntity();
                        if (org != null) {
                            Map<Object, Object> entityProperties = em.getDictionaryAsMap(org, ORGANIZATION_CONFIG_DICTIONARY);
                            return new OrganizationConfig(orgConfigProperties, org.getUuid(), org.getPath(), entityProperties, false);
                        }
                    }

                    return new OrganizationConfig(orgConfigProperties);

                } catch (Exception e) {
                    return new OrganizationConfig(orgConfigProperties);
                }
            }}
        );



    /** Must be constructed with a CassandraClientPool. */
    public ManagementServiceImpl(Injector injector) {

        // Use the injector to get our guice dependencies
        this.lockManager = injector.getInstance(LockManager.class);
        this.cacheFactory = injector.getInstance( CacheFactory.class );
        this.aggregationServiceFactory = injector.getInstance(AggregationServiceFactory.class);
        this.service = injector.getInstance(ApplicationService.class);
        this.localShiroCache = injector.getInstance(LocalShiroCache.class);

    }

    @Autowired
    public void setEntityManagerFactory( EntityManagerFactory emf ) {
        logger.info( "ManagementServiceImpl.setEntityManagerFactory" );
        this.emf = emf;
    }


    @Autowired
    public void setProperties( Properties properties ) {
        this.properties = new AccountCreationPropsImpl( properties );
        this.orgConfigProperties = new OrganizationConfigPropsImpl( properties );
    }

    String orgSysAdminEmail,defaultSysAdminEmail;
    private String getDefaultSysAdminEmail(){
        defaultSysAdminEmail = defaultSysAdminEmail != null
            ? defaultSysAdminEmail
            : properties.getProperty(PROPERTIES_DEFAULT_SYSADMIN_EMAIL);
        return defaultSysAdminEmail;
    }
    private String getOrgSystemEmail(){
        if( orgSysAdminEmail != null ){
            return orgSysAdminEmail;
        }
        orgSysAdminEmail =  properties.getProperty( PROPERTIES_ORG_SYSADMIN_EMAIL );
        if (orgSysAdminEmail == null || orgSysAdminEmail.isEmpty()) {
            orgSysAdminEmail = getDefaultSysAdminEmail();
        }
        return orgSysAdminEmail;
    }

    String defaultAdminSysAdminEmail = null;
    private String getDefaultAdminSystemEmail(){
        if( defaultAdminSysAdminEmail == null ){
            defaultAdminSysAdminEmail = properties.getProperty(ORGPROPERTIES_ADMIN_SYSADMIN_EMAIL);
            if (defaultAdminSysAdminEmail == null || defaultAdminSysAdminEmail.isEmpty()) {
                defaultAdminSysAdminEmail = getDefaultSysAdminEmail();
            }
        }

        return defaultAdminSysAdminEmail;
    }

    private String getAdminSystemEmailForApplication(UUID applicationId) {
        String adminSystemEmail = null;
        try {
            OrganizationConfig orgConfig = getOrganizationConfigForApplication(applicationId);
            if (orgConfig != null) {
                adminSystemEmail = orgConfig.getProperty(ORGPROPERTIES_ADMIN_SYSADMIN_EMAIL);
            }
        }
        catch (Exception e) {
            // swallow
        }

        return (adminSystemEmail != null && !adminSystemEmail.isEmpty()) ?
                adminSystemEmail : getDefaultAdminSystemEmail();
    }

    private String getAdminSystemEmailForOrganization(UUID organizationId) {
        String adminSystemEmail = null;
        try {
            OrganizationConfig orgConfig = getOrganizationConfigByUuid(organizationId);
            if (orgConfig != null) {
                adminSystemEmail = orgConfig.getProperty(ORGPROPERTIES_ADMIN_SYSADMIN_EMAIL);
            }
        }
        catch (Exception e) {
            // swallow
        }

        return adminSystemEmail != null ? adminSystemEmail : getDefaultAdminSystemEmail();
    }


    /** For testing purposes only */
    public Properties getProperties() {
        return properties.properties;
    }

   @Autowired
    public void setTokenService( TokenService tokens ) {
        this.tokens = tokens;
    }


    @Autowired
    public void setServiceManagerFactory( ServiceManagerFactory smf ) {
        this.smf = smf;
    }



    /** @param encryptionService the encryptionService to set */
    @Autowired
    public void setEncryptionService( EncryptionService encryptionService ) {
        this.encryptionService = encryptionService;
    }


    @Override
    public void setup() throws Exception {

        if ( getBooleanProperty( PROPERTIES_SETUP_TEST_ACCOUNT ) ) {
            String test_app_name = properties.getProperty( PROPERTIES_TEST_ACCOUNT_APP );
            String test_organization_name = properties.getProperty( PROPERTIES_TEST_ACCOUNT_ORGANIZATION );
            String test_admin_username = properties.getProperty( PROPERTIES_TEST_ACCOUNT_ADMIN_USER_USERNAME );
            String test_admin_name = properties.getProperty( PROPERTIES_TEST_ACCOUNT_ADMIN_USER_NAME );
            String test_admin_email = properties.getProperty( PROPERTIES_TEST_ACCOUNT_ADMIN_USER_EMAIL );
            String test_admin_password = properties.getProperty( PROPERTIES_TEST_ACCOUNT_ADMIN_USER_PASSWORD );

            if ( anyNull( test_app_name, test_organization_name, test_admin_username, test_admin_name, test_admin_email,
                    test_admin_password ) ) {
                logger.warn( "Missing values for test app, check properties.  Skipping test app setup..." );
                return;
            }

            OrganizationInfo organization = getOrganizationByName( test_organization_name );

            if ( organization == null ) {
                OrganizationOwnerInfo created =
                        createOwnerAndOrganization( test_organization_name, test_admin_username, test_admin_name,
                                test_admin_email, test_admin_password, true, false );
                organization = created.getOrganization();
            }

            if ( !getApplicationsForOrganization( organization.getUuid() ).containsValue( test_app_name ) ) {
                try {
                    createApplication( organization.getUuid(), test_app_name );
                }catch(ApplicationAlreadyExistsException aaee){
                    if(logger.isDebugEnabled()){
                        logger.debug("The database setup already found an existing application");
                    }
                }
            }
        }
        else {
            logger.warn( "Test app creation disabled" );
        }

        if ( superuserEnabled() ) {
            provisionSuperuser();
        }
    }


    public boolean superuserEnabled() {
        boolean superuser_enabled = getBooleanProperty( PROPERTIES_SYSADMIN_LOGIN_ALLOWED );
        String superuser_username = properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_NAME );
        String superuser_email = properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_EMAIL );
        String superuser_password = properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_PASSWORD );

        return superuser_enabled && !anyNull( superuser_username, superuser_email, superuser_password );
    }


    @Override
    public void provisionSuperuser() throws Exception {
        boolean superuser_enabled = getBooleanProperty( PROPERTIES_SYSADMIN_LOGIN_ALLOWED );
        String superuser_username = properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_NAME );
        String superuser_email = properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_EMAIL );
        String superuser_password = properties.getProperty(PROPERTIES_SYSADMIN_LOGIN_PASSWORD);

        if ( !anyNull( superuser_username, superuser_email, superuser_password ) ) {
            UserInfo user = this.getAdminUserByUsername( superuser_username );
            if ( user == null ) {
                createAdminUser( null, superuser_username, "Super User", superuser_email, superuser_password,
                        superuser_enabled, !superuser_enabled );
            }
            else {
                this.setAdminUserPassword( user.getUuid(), superuser_password );
            }
        }
        else {
            System.out.println(
                "Missing values for superuser account, check properties.  Skipping superuser account setup...");
        }
    }


    @Override
    public void resetSuperUser(String username, String password, String email) throws Exception {
        //final AccountCreationProps.SuperUser superUser = properties.getSuperUser();
        //this.getAdminUser
        UserInfo user = this.getAdminUserByUsername( username );
        if ( user == null ) {
            try {
                createAdminUser( null, username, "Super User", email, password, true, false );
            }catch(Exception e){
                logger.info("resetSuperUser: auto creation of superuser failed: {}", e.getMessage());
            }
        }
        else {
            this.setAdminUserPassword( user.getUuid(), password );
        }
    }


    public String generateOAuthSecretKey( AuthPrincipalType type ) {
        long timestamp = System.currentTimeMillis();
        ByteBuffer bytes = ByteBuffer.allocate( 20 );
        bytes.put( sha( timestamp + OAUTH_SECRET_SALT + UUID.randomUUID() ) );
        return type.getBase64Prefix() + encodeBase64URLSafeString( bytes.array() );
    }


    @SuppressWarnings( "serial" )
    @Override
    public void postOrganizationActivity( UUID organizationId, final UserInfo user, String verb, final EntityRef object,
                                          final String objectType, final String objectName, String title,
                                          String content ) throws Exception {
        ServiceManager sm = smf.getServiceManager( smf.getManagementAppId() );

        Map<String, Object> properties = new HashMap<>();
        properties.put( PROPERTY_VERB, verb );
        properties.put( PROPERTY_CATEGORY, "admin" );
        if ( content != null ) {
            properties.put( PROPERTY_CONTENT, content );
        }
        if ( title != null ) {
            properties.put( PROPERTY_TITLE, title );
        }
        properties.put( PROPERTY_ACTOR, new HashMap<String, Object>() {
            {
                put( PROPERTY_DISPLAY_NAME, user.getName() );
                put( PROPERTY_OBJECT_TYPE, "person" );
                put( PROPERTY_ENTITY_TYPE, "user" );
                put( PROPERTY_UUID, user.getUuid() );
            }
        } );
        properties.put( PROPERTY_OBJECT, new HashMap<String, Object>() {
            {
                put( PROPERTY_DISPLAY_NAME, objectName );
                put( PROPERTY_OBJECT_TYPE, objectType );
                put( PROPERTY_ENTITY_TYPE, object.getType() );
                put( PROPERTY_UUID, object.getUuid() );
            }
        } );

        sm.newRequest( ServiceAction.POST, parameters( Schema.COLLECTION_GROUPS, organizationId, "activities" ),
            payload( properties ) ).execute().getEntity();
    }


    @Override
    public ServiceResults getOrganizationActivity( OrganizationInfo organization ) throws Exception {
        ServiceManager sm = smf.getServiceManager( smf.getManagementAppId() );
        return sm.newRequest( ServiceAction.GET, parameters(
            Schema.COLLECTION_GROUPS, organization.getUuid(), "feed" ) ).execute();
    }


    @Override
    public ServiceResults getOrganizationActivityForAdminUser( OrganizationInfo organization, UserInfo user )
            throws Exception {
        ServiceManager sm = smf.getServiceManager( smf.getManagementAppId() );
        return sm.newRequest( ServiceAction.GET, parameters( Schema.COLLECTION_GROUPS, organization.getUuid(),
            "users", user.getUuid(), "feed" ) ).execute();
    }


    @Override
    public ServiceResults getAdminUserActivity( UserInfo user ) throws Exception {
        ServiceManager sm = smf.getServiceManager(smf.getManagementAppId());
        return sm.newRequest( ServiceAction.GET, parameters( "users", user.getUuid(), "feed" ) ).execute();
    }


    @Override
    public OrganizationOwnerInfo createOwnerAndOrganization( String organizationName, String username, String name,
                                                             String email, String password ) throws Exception {

        if(logger.isTraceEnabled()){
            logger.trace("createOwnerAndOrganization(1)");
        }
        boolean activated = !newAdminUsersNeedSysAdminApproval() && !newOrganizationsNeedSysAdminApproval();
        boolean disabled = newAdminUsersRequireConfirmation();
        // if we are active and enabled, skip the send email step

        return createOwnerAndOrganization( organizationName, username, name, email, password, activated, disabled, null,
                null );
    }


    @Override
    public OrganizationOwnerInfo createOwnerAndOrganization( String organizationName, String username, String name,
                                                             String email, String password, boolean activated,
                                                             boolean disabled ) throws Exception {
        if(logger.isTraceEnabled()){
            logger.trace("createOwnerAndOrganization(2)");
        }
        return createOwnerAndOrganization( organizationName, username, name, email, password,
                activated, disabled, null, null );
    }


    @Override
    public OrganizationOwnerInfo createOwnerAndOrganization( String organizationName, String username, String name,
                                                             String email, String password, boolean activated,
                                                             boolean disabled, Map<String, Object> userProperties,
                                                             Map<String, Object> organizationProperties )
            throws Exception {

        logger.info("createOwnerAndOrganization: {} {}", organizationName, email);

        /**
         * Only lock on the target values. We don't want lock contention if another
         * node is trying to set the property do a different value
         */
        Lock groupLock = getUniqueUpdateLock( lockManager, smf.getManagementAppId(), organizationName,
            Schema.COLLECTION_GROUPS, PROPERTY_PATH );

        Lock userLock = getUniqueUpdateLock( lockManager, smf.getManagementAppId(), username, "users", "username" );

        Lock emailLock = getUniqueUpdateLock( lockManager, smf.getManagementAppId(), email, "users", "email" );

        UserInfo user = null;
        OrganizationInfo organization = null;

        try {

            groupLock.lock();
            userLock.lock();
            emailLock.lock();
            EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
            if ( !em.isPropertyValueUniqueForEntity( Group.ENTITY_TYPE, PROPERTY_PATH, organizationName ) ) {
                throw new DuplicateUniquePropertyExistsException( Group.ENTITY_TYPE, PROPERTY_PATH, organizationName );
            }
            if ( !validateAdminInfo( username, name, email, password ) ) {
                return null;
            }
            if ( areActivationChecksDisabled() ) {
                user = createAdminUserInternal( null, username, name, email, password, true, false, userProperties );
            }
            else {
                user = createAdminUserInternal( null, username, name, email, password, activated, disabled, userProperties );
            }

            if(logger.isTraceEnabled()){
                logger.debug("createOwnerAndOrganization: User created");
            }
            organization = createOrganizationInternal( null, organizationName, user, true, organizationProperties );
        }
        finally {
            emailLock.unlock();
            userLock.unlock();
            groupLock.unlock();
        }

        return new OrganizationOwnerInfo( user, organization );
    }


    private OrganizationInfo createOrganizationInternal(
        UUID orgUuid, String organizationName, UserInfo user, boolean activated ) throws Exception {
        if(logger.isTraceEnabled()){
            logger.trace("createOrganizationInternal(1): {}", organizationName);
        }
        return createOrganizationInternal( orgUuid, organizationName, user, activated, null );
    }


    private OrganizationInfo createOrganizationInternal( UUID orgUuid, String organizationName, UserInfo user, boolean activated,
                                                         Map<String, Object> properties ) throws Exception {

        if(logger.isTraceEnabled()){
            logger.trace( "createOrganizationInternal(2): {}", organizationName );
        }

        if (  organizationName == null ) {
            if(logger.isDebugEnabled()){
                logger.debug("organizationName = null");
            }
            return null;
        }
        if ( user == null ) {
            if(logger.isDebugEnabled()){
                logger.debug("user = null (organizationName = {})", organizationName);
            }
            return null;
        }

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

        Group organizationEntity = new Group();
        organizationEntity.setPath( organizationName );

        if ( orgUuid == null ) {
            organizationEntity = em.create( organizationEntity );
        } else {
            em.create( orgUuid, Group.ENTITY_TYPE, organizationEntity.getProperties() );
            organizationEntity = em.get( orgUuid, Group.class );
        }

        em.addToCollection( organizationEntity, "users", new SimpleEntityRef( User.ENTITY_TYPE, user.getUuid() ) );
//        em.addToCollection( new SimpleEntityRef( User.ENTITY_TYPE, user.getUuid() ), Schema.COLLECTION_GROUPS, organizationEntity );

        writeUserToken( smf.getManagementAppId(), organizationEntity, encryptionService
                .plainTextCredentials( generateOAuthSecretKey( AuthPrincipalType.ORGANIZATION ), user.getUuid(),
                        smf.getManagementAppId() ) );

        OrganizationInfo organization =
                new OrganizationInfo( organizationEntity.getUuid(), organizationName, properties );
        updateOrganization( organization );

        if ( orgUuid == null ) { // no import ID specified, so do the activation email flow stuff

            logger.info( "createOrganizationInternal: {}", organizationName );
            postOrganizationActivity( organization.getUuid(), user, "create", organizationEntity, "Organization",
                    organization.getName(),
                    "<a href=\"mailto:" + user.getEmail() + "\">" + user.getName() + " (" + user.getEmail()
                            + ")</a> created a new organization account named " + organizationName, null );

            startOrganizationActivationFlow( organization );
        }



        return organization;
    }


    @Override
    public OrganizationInfo createOrganization(String organizationName, UserInfo user, boolean activated)
            throws Exception {
        return createOrganization( null, organizationName, user, activated );
    }

    @Override
    public OrganizationInfo createOrganization(UUID orgUuid, String organizationName, UserInfo user, boolean activated)
            throws Exception {

        if (  organizationName == null ) {
            if (logger.isTraceEnabled()) {
                logger.trace("organizationName = null");
            }
            return null;
        }
        if ( user == null ) {
            if (logger.isTraceEnabled()) {
                logger.trace("user = null");
            }
            return null;
        }

        Lock groupLock = getUniqueUpdateLock(
            lockManager, smf.getManagementAppId(), organizationName, Schema.COLLECTION_GROUPS, PROPERTY_PATH );

        EntityManager em = emf.getEntityManager(smf.getManagementAppId());
        if ( !em.isPropertyValueUniqueForEntity( Group.ENTITY_TYPE, PROPERTY_PATH, organizationName ) ) {
            throw new DuplicateUniquePropertyExistsException( Group.ENTITY_TYPE, PROPERTY_PATH, organizationName );
        }
        try {
            groupLock.lock();
            return createOrganizationInternal( orgUuid, organizationName, user, activated );
        }
        finally {
            groupLock.unlock();
        }
    }


    /** currently only affects properties */
    public void updateOrganization( OrganizationInfo organizationInfo ) throws Exception {
        Map<String, Object> properties = organizationInfo.getProperties();
        if ( properties != null ) {
            EntityRef organizationEntity = new SimpleEntityRef( Group.ENTITY_TYPE, organizationInfo.getUuid() );
            EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
            for ( Map.Entry<String, Object> entry : properties.entrySet() ) {
                if ( "".equals( entry.getValue() ) ) {
                    properties.remove( entry.getKey() );
                    em.removeFromDictionary( organizationEntity, ORGANIZATION_PROPERTIES_DICTIONARY, entry.getKey() );
                }
                else {
                    em.addToDictionary( organizationEntity, ORGANIZATION_PROPERTIES_DICTIONARY, entry.getKey(),
                            entry.getValue() );
                }
            }
        }
    }


    @Override
    public OrganizationInfo importOrganization( UUID organizationId, OrganizationInfo organizationInfo,
                                                Map<String, Object> properties ) throws Exception {

        String organizationName = null;
        if ( organizationInfo != null ) {
            organizationName = organizationInfo.getName();
        }
        if ( organizationName == null ) {
            organizationName = ( String ) properties.get( PROPERTY_PATH );
        }
        if ( organizationName == null ) {
            organizationName = ( String ) properties.get( PROPERTY_NAME );
        }
        if ( organizationName == null ) {
            return null;
        }

        if (organizationId == null && organizationInfo != null) {
            organizationId = organizationInfo.getUuid();
        }
        if ( organizationId == null ) {
            organizationId = uuid( properties.get( PROPERTY_UUID ) );
        }
        if ( organizationId == null ) {
            return null;
        }

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        if ( !em.isPropertyValueUniqueForEntity( Group.ENTITY_TYPE, PROPERTY_PATH, organizationName ) ) {
            throw new DuplicateUniquePropertyExistsException( Group.ENTITY_TYPE, PROPERTY_PATH, organizationName );
        }
        if ( properties == null ) {
            properties = new HashMap<>();
        }

        properties.put( PROPERTY_PATH, organizationName );
        properties.put( PROPERTY_SECRET, generateOAuthSecretKey( AuthPrincipalType.ORGANIZATION ) );
        Entity organization = em.create( organizationId, Group.ENTITY_TYPE, properties );
        // em.addToCollection(organization, "users", new SimpleEntityRef(
        // User.ENTITY_TYPE, userId));
        return new OrganizationInfo( organization.getUuid(), organizationName );
    }


    @Override
    public UUID importApplication( UUID organizationId, final Application application ) throws Exception {
        throw new UnsupportedOperationException("Import application not supported");
    }


    /**
     * Test if the applicationName contains a '/' character, prepend with orgName if it does not, assume it is complete
     * (and that organization is needed) if so.
     */
    private String buildAppName( String applicationName, OrganizationInfo organization ) {
        return org.apache.commons.lang.StringUtils.lowerCase(
                applicationName.contains( "/" ) ? applicationName : organization.getName() + "/" + applicationName);
    }


    @Override
    public List<OrganizationInfo> getOrganizations( UUID startResult, int count ) throws Exception {
        // still need the bimap to search for existing
        BiMap<UUID, String> organizations = HashBiMap.create();
        EntityManager em = emf.getEntityManager(smf.getManagementAppId());
        Results results = em.getCollection(em.getApplicationRef(),
            Schema.COLLECTION_GROUPS, startResult, count, Level.ALL_PROPERTIES, false);
        List<OrganizationInfo> orgs = new ArrayList<>( results.size() );
        OrganizationInfo orgInfo;
        for ( Entity entity : results.getEntities() ) {
            // TODO T.N. temporary hack to deal with duplicate orgs. Revert this
            // commit after migration
            String path = ( String ) entity.getProperty( PROPERTY_PATH );

            if ( organizations.containsValue( path ) ) {
                path += "DUPLICATE";
            }
            orgInfo = new OrganizationInfo( entity.getUuid(), path );
            orgs.add( orgInfo );
            organizations.put( entity.getUuid(), path );
        }
        return orgs;
    }


    @Override
    public BiMap<UUID, String> getOrganizations() throws Exception {
        List<OrganizationInfo> orgs = getOrganizations(null, 10000);
        return buildOrgBiMap( orgs );
    }


    private BiMap<UUID, String> buildOrgBiMap( List<OrganizationInfo> orgs ) {
        BiMap<UUID, String> organizations = HashBiMap.create();
        for ( OrganizationInfo orgInfo : orgs ) {
            organizations.put( orgInfo.getUuid(), orgInfo.getName() );
        }
        return organizations;
    }


    @Override
    public OrganizationInfo getOrganizationInfoFromAccessToken( String token ) throws Exception {
        Entity entity = getEntityFromAccessToken(token, null, ORGANIZATION);
        if ( entity == null ) {
            return null;
        }
        return new OrganizationInfo( entity.getProperties() );
    }


    @Override
    public OrganizationInfo getOrganizationByName( String organizationName ) throws Exception {

        if ( organizationName == null ) {
            return null;
        }

        EntityManager em = emf.getEntityManager(smf.getManagementAppId());
        EntityRef ref = em.getAlias( Group.ENTITY_TYPE, organizationName );
        if ( ref == null ) {
            return null;
        }
        return getOrganizationByUuid( ref.getUuid() );
    }


    @Override
    public OrganizationInfo getOrganizationByUuid( UUID id ) throws Exception {

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        Entity entity = em.get( new SimpleEntityRef( Group.ENTITY_TYPE, id ) );
        if ( entity == null ) {
            return null;
        }
        Map<Object, Object> properties = em.getDictionaryAsMap( entity, ORGANIZATION_PROPERTIES_DICTIONARY );
        OrganizationInfo orgInfo = new OrganizationInfo( entity.getProperties() );
        orgInfo.setProperties( properties );
        return orgInfo;
    }


    @Override
    public OrganizationInfo getOrganizationByIdentifier( Identifier id ) throws Exception {
        if ( id.isUUID() ) {
            return getOrganizationByUuid( id.getUUID() );
        }
        if ( id.isName() ) {
            return getOrganizationByName( id.getName() );
        }
        return null;
    }


    public void postUserActivity( UserInfo user, String verb, EntityRef object, String objectType, String objectName,
                                  String title, String content ) throws Exception {
        ServiceManager sm = smf.getServiceManager( smf.getManagementAppId() );

        Map<String, Object> properties = new HashMap<>();
        properties.put( PROPERTY_VERB, verb );
        properties.put( PROPERTY_CATEGORY, "admin" );
        if ( content != null ) {
            properties.put( PROPERTY_CONTENT, content );
        }
        if ( title != null ) {
            properties.put( PROPERTY_TITLE, title );
        }
        properties.put( PROPERTY_ACTOR, user.getUuid() );
        properties.put( PROPERTY_ACTOR_NAME, user.getName() );
        properties.put( PROPERTY_OBJECT, object.getUuid() );
        properties.put( PROPERTY_OBJECT_ENTITY_TYPE, object.getType() );
        properties.put( PROPERTY_OBJECT_TYPE, objectType );
        properties.put( PROPERTY_OBJECT_NAME, objectName );

        sm.newRequest( ServiceAction.POST, parameters( "users", user.getUuid(), "activities" ), payload( properties ) )
          .execute().getEntity();
    }


    @Override
    public ServiceResults getAdminUserActivities( UserInfo user ) throws Exception {
        ServiceManager sm = smf.getServiceManager( smf.getManagementAppId() );
        ServiceRequest request = sm.newRequest( ServiceAction.GET, parameters( "users", user.getUuid(), "feed" ) );
        return request.execute();
    }


    private UserInfo doCreateAdmin( UUID organizationId, User user, CredentialsInfo userPassword, CredentialsInfo mongoPassword )
            throws Exception {

        writeUserToken( smf.getManagementAppId(), user, encryptionService
                .plainTextCredentials( generateOAuthSecretKey( AuthPrincipalType.ADMIN_USER ), user.getUuid(),
                        smf.getManagementAppId() ) );

        writeUserPassword( smf.getManagementAppId(), user, userPassword );

        writeUserMongoPassword( smf.getManagementAppId(), user, mongoPassword );

        UserInfo userInfo = new UserInfo(
            smf.getManagementAppId(), user.getUuid(), user.getUsername(), user.getName(),
            user.getEmail(), user.getConfirmed(), user.getActivated(), user.getDisabled(),
            user.getDynamicProperties(), true );

        // special case for sysadmin and test account only
        if (    !user.getEmail().equals( properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_EMAIL ) )
             && !user.getEmail().equals( properties .getProperty( PROPERTIES_TEST_ACCOUNT_ADMIN_USER_EMAIL ) ) ) {
            this.startAdminUserActivationFlow( organizationId, userInfo );
        }

        return userInfo;
    }


    @Override
    public UserInfo createAdminFromPrexistingPassword( UUID organizationId, User user, CredentialsInfo ci ) throws Exception {

        return doCreateAdmin( organizationId, user, ci,
                // we can't actually set the mongo password. We never have the plain text in
                // this path
                encryptionService.plainTextCredentials( mongoPassword( user.getUsername(), "" ), user.getUuid(),
                        smf.getManagementAppId() ) );
    }


    @Override
    public UserInfo createAdminFrom( UUID organizationId, User user, String password ) throws Exception {
        return doCreateAdmin(organizationId, user,
            encryptionService.defaultEncryptedCredentials(password, user.getUuid(), smf.getManagementAppId()),
            encryptionService.plainTextCredentials(mongoPassword(user.getUsername(), password), user.getUuid(),
                smf.getManagementAppId()));
    }


    @Override
    public UserInfo createAdminUser( UUID organizationId, String username, String name, String email, String password, boolean activated,
                                     boolean disabled ) throws Exception {
        return createAdminUser(organizationId, username, name, email, password, activated, disabled, null);
    }


    @Override
    public UserInfo createAdminUser( UUID organizationId, String username, String name, String email, String password, boolean activated,
                                     boolean disabled, Map<String, Object> userProperties ) throws Exception {

        if ( !validateAdminInfo(username, name, email, password) ) {
            return null;
        }
        return createAdminUserInternal( organizationId, username, name, email, password, activated, disabled, userProperties );
    }


    private boolean validateAdminInfo( String username, String name, String email, String password ) throws Exception {
        if ( email == null ) {
            return false;
        }
        if ( username == null ) {
            username = email;
        }

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

        if ( !em.isPropertyValueUniqueForEntity( "user", "username", username ) ) {
            throw new DuplicateUniquePropertyExistsException( "user", "username", username );
        }

        if ( !em.isPropertyValueUniqueForEntity( "user", "email", email ) ) {
            throw new DuplicateUniquePropertyExistsException( "user", "email", email );
        }
        return true;
    }


    private UserInfo createAdminUserInternal( UUID organizationId, String username, String name, String email, String password,
                                              boolean activated, boolean disabled, Map<String, Object> userProperties )
            throws Exception {
        logger.info( "createAdminUserInternal: {}", username );

        if ( isBlank( password ) ) {
            password = encodeBase64URLSafeString( bytes( UUID.randomUUID() ) );
        }
        if ( username == null ) {
            username = email;
        }
        if ( name == null ) {
            name = email;
        }
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        User user = new User();
        user.setUsername( username );
        user.setName( name );
        user.setEmail( email );
        user.setActivated( activated );
        user.setConfirmed( !newAdminUsersRequireConfirmation() ); // only
        user.setDisabled( disabled );
        if ( userProperties != null ) {
            // double check no 'password' property just to be safe
            userProperties.remove( "password" );
            user.setProperties( userProperties );
        }
        user = em.create( user );

        return createAdminFrom( organizationId, user, password );
    }


    public UserInfo getUserInfo( UUID applicationId, Entity entity ) {

        if ( entity == null ) {
            return null;
        }
        return new UserInfo( applicationId, entity.getUuid(), ( String ) entity.getProperty( "username" ),
                entity.getName(), ( String ) entity.getProperty( "email" ),
                ConversionUtils.getBoolean( entity.getProperty( "confirmed" ) ),
                ConversionUtils.getBoolean( entity.getProperty( "activated" ) ),
                ConversionUtils.getBoolean( entity.getProperty( "disabled" ) ),
                entity.getDynamicProperties(),
                ConversionUtils.getBoolean( entity.getProperty( "admin" )));
    }


    public UserInfo getUserInfo( UUID applicationId, Map<String, Object> properties ) {

        if ( properties == null ) {
            return null;
        }
        return new UserInfo( applicationId, properties );
    }


    @Override
    public List<UserInfo> getAdminUsersForOrganization( UUID organizationId ) throws Exception {

        if ( organizationId == null ) {
            return null;
        }

        List<UserInfo> users = new ArrayList<>();

        EntityManager em = emf.getEntityManager(smf.getManagementAppId());
        Results results =
                em.getCollection(new SimpleEntityRef(Group.ENTITY_TYPE, organizationId), "users", null, 10000,
                    Level.ALL_PROPERTIES, false);
        for ( Entity entity : results.getEntities() ) {
            users.add( getUserInfo( smf.getManagementAppId(), entity ) );
        }

        return users;
    }


    @Override
    public UserInfo updateAdminUser( UserInfo user, String username, String name, String email,
                                     Map<String, Object> json ) throws Exception {

        /**
         * Only lock on the target values. We don't want lock contention if another
         * node is trying to set the property do a different value
         */
        Lock usernameLock =
                getUniqueUpdateLock( lockManager, smf.getManagementAppId(), username, "users", "username" );

        Lock emailLock = getUniqueUpdateLock( lockManager, smf.getManagementAppId(), email, "users", "email" );

        try {

            usernameLock.lock();
            emailLock.lock();

            EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

            SimpleEntityRef entityRef = new SimpleEntityRef( User.ENTITY_TYPE, user.getUuid() );
            if ( !isBlank( username ) ) {
                em.setProperty( entityRef, "username", username );
            }
            if ( !isBlank( name ) ) {
                em.setProperty( entityRef, "name", name );
            }
            if ( !isBlank( email ) ) {
                em.setProperty( entityRef, "email", email );
            }
            if ( json != null ) {
                json.remove( "password" );
                json.remove( "oldpassword" );
                json.remove( "newpassword" );
                Map<String, Object> userProperties = user.getProperties();
                userProperties.putAll( json );
                Entity entity = em.get( entityRef, User.class);
                em.updateProperties( entity, userProperties );
            }

            user = getAdminUserByUuid( user.getUuid() );
        }
        finally {
            emailLock.unlock();
            usernameLock.unlock();
        }

        return user;
    }


    public User getAdminUserEntityByEmail( String email ) throws Exception {

        if ( email == null ) {
            return null;
        }

        return getUserEntityByIdentifier(smf.getManagementAppId(), Identifier.fromEmail(email));
    }


    @Override
    public UserInfo getAdminUserByEmail( String email ) throws Exception {
        if ( email == null ) {
            return null;
        }
        return getUserInfo(smf.getManagementAppId(),
            getUserEntityByIdentifier(smf.getManagementAppId(), Identifier.fromEmail(email)));
    }


    public User getUserEntityByIdentifier( UUID applicationId, Identifier identifier ) throws Exception {
        EntityManager em = emf.getEntityManager( applicationId );
        return em.get(em.getUserByIdentifier(identifier), User.class);
    }


    @Override
    public UserInfo getAdminUserByUsername( String username ) throws Exception {
        if ( username == null ) {
            return null;
        }
        return getUserInfo(smf.getManagementAppId(),
            getUserEntityByIdentifier(smf.getManagementAppId(), Identifier.fromName(username)));
    }


    @Override
    public User getAdminUserEntityByUuid( UUID id ) throws Exception {
        if ( id == null ) {
            return null;
        }
        return getUserEntityByIdentifier(smf.getManagementAppId(), Identifier.fromUUID(id));
    }


    @Override
    public UserInfo getAdminUserByUuid( UUID id ) throws Exception {
        return getUserInfo(smf.getManagementAppId(),
            getUserEntityByIdentifier(smf.getManagementAppId(), Identifier.fromUUID(id)));
    }


    @Override
    public User getAdminUserEntityByIdentifier( Identifier id ) throws Exception {
        return getUserEntityByIdentifier( smf.getManagementAppId(), id );
    }


    @Override
    public UserInfo getAdminUserByIdentifier( Identifier id ) throws Exception {
        if ( id.isUUID() ) {
            return getAdminUserByUuid( id.getUUID() );
        }
        if ( id.isName() ) {
            return getAdminUserByUsername( id.getName() );
        }
        if ( id.isEmail() ) {
            return getAdminUserByEmail( id.getEmail() );
        }
        return null;
    }


    public User findUserEntity( UUID applicationId, String identifierString ) {

        User user = null;
        if ( UUIDUtils.isUUID( identifierString ) ) {
            try {
                Entity entity = getUserEntityByIdentifier( applicationId,
                        Identifier.fromUUID( UUID.fromString( identifierString ) ) );
                if ( entity != null ) {
                    user = ( User ) entity.toTypedEntity();
                    if (logger.isTraceEnabled()) {
                        logger.trace("Found user {} as a UUID", identifierString);
                    }
                }
            }
            catch ( Exception e ) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Unable to get user {} as a UUID, trying username...", identifierString);
                }
            }
            return user;
        }
        // now we are either an email or a username. Let Indentifier handle the parsing of such.
        Identifier identifier = Identifier.from( identifierString );

        try {
            Entity entity = getUserEntityByIdentifier( applicationId, identifier );
            if ( entity != null ) {
                user = ( User ) entity.toTypedEntity();
                if (logger.isTraceEnabled()) {
                    logger.trace("Found user {} as an {}", identifierString, identifier.getType());
                }
            }
        }
        catch ( Exception e ) {
            logger.warn( "Unable to get user {} as a {}", identifierString, identifier.getType(), e);
        }
        if ( user != null ) {
            return user;
        }

        return null;
    }


    @Override
    public UserInfo findAdminUser( String identifier ) {
        return getUserInfo( smf.getManagementAppId(), findUserEntity( smf.getManagementAppId(), identifier ) );
    }


    @Override
    public void setAdminUserPassword( UUID userId, String oldPassword, String newPassword ) throws Exception {

        if ( ( userId == null ) || ( oldPassword == null ) || ( newPassword == null ) ) {
            return;
        }
        User user = emf.getEntityManager( smf.getManagementAppId() ).get( userId, User.class );

        if ( !verify( smf.getManagementAppId(), user.getUuid(), oldPassword ) ) {
            throw new IncorrectPasswordException( "Old password does not match" );
        }

        setAdminUserPassword(userId, newPassword);
    }


    private static final String CREDENTIALS_HISTORY = "credentialsHistory";


    @Override
    public void setAdminUserPassword( UUID userId, String newPassword ) throws Exception {

        if ( ( userId == null ) || ( newPassword == null ) ) {
            return;
        }

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        User user = em.get( userId, User.class );

        CredentialsInfo newCredentials =
                encryptionService.defaultEncryptedCredentials( newPassword, user.getUuid(), smf.getManagementAppId() );

        int passwordHistorySize = calculatePasswordHistorySizeForUser( user.getUuid() );
        Map<String, CredentialsInfo> credsMap = cast( em.getDictionaryAsMap( user, CREDENTIALS_HISTORY ) );

        CredentialsInfo currentCredentials = null;
        if ( passwordHistorySize > 0 ) {
            ArrayList<CredentialsInfo> oldCreds = new ArrayList<>( credsMap.values() );
            Collections.sort( oldCreds );

            currentCredentials = readUserPasswordCredentials( smf.getManagementAppId(), user.getUuid(), user.getType() );

            // check credential history
            if ( encryptionService.verify( newPassword, currentCredentials, userId, smf.getManagementAppId() ) ) {
                throw new RecentlyUsedPasswordException();
            }
            for ( int i = 0; i < oldCreds.size() && i < passwordHistorySize; i++ ) {
                CredentialsInfo ci = oldCreds.get( i );
                if ( encryptionService.verify( newPassword, ci, userId, smf.getManagementAppId() ) ) {
                    throw new RecentlyUsedPasswordException();
                }
            }
        }

        // remove excess history
        if ( credsMap.size() > passwordHistorySize ) {
            ArrayList<UUID> oldUUIDs = new ArrayList<>( credsMap.size() );
            credsMap.keySet().forEach((uuid) -> oldUUIDs.add(UUID.fromString(uuid)));
            UUIDUtils.sort( oldUUIDs );
            for ( int i = 0; i < oldUUIDs.size() - passwordHistorySize; i++ ) {
                em.removeFromDictionary( user, CREDENTIALS_HISTORY, oldUUIDs.get( i ).toString() );
            }
        }

        if ( passwordHistorySize > 0 ) {
            UUID uuid = UUIDUtils.newTimeUUID();
            em.addToDictionary( user, CREDENTIALS_HISTORY, uuid.toString(), currentCredentials );
        }

        writeUserPassword( smf.getManagementAppId(), user, newCredentials );
        writeUserMongoPassword( smf.getManagementAppId(), user, encryptionService
                .plainTextCredentials( mongoPassword( ( String ) user.getProperty( "username" ), newPassword ),
                        user.getUuid(), smf.getManagementAppId() ) );

    }


    public int calculatePasswordHistorySizeForUser( UUID userId ) throws Exception {

        if(logger.isTraceEnabled()){
            logger.trace( "calculatePasswordHistorySizeForUser {}", userId.toString() );
        }

        int size = 0;
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

        Results orgResults = em.getCollection( new SimpleEntityRef( User.ENTITY_TYPE, userId ),
                Schema.COLLECTION_GROUPS, null, 10000, Level.REFS, false );

        if(logger.isTraceEnabled()){
            logger.trace("    orgResults.size() = {}", orgResults.size());
        }

        for ( EntityRef orgRef : orgResults.getRefs() ) {
            Map<Object, Object> properties = em.getDictionaryAsMap( orgRef, ORGANIZATION_PROPERTIES_DICTIONARY );

            if ( properties != null ) {
                OrganizationInfo orgInfo = new OrganizationInfo( null, null, properties );

                if(logger.isTraceEnabled()){
                    logger.trace( "    orgInfo.getPasswordHistorySize() = {}", orgInfo.getPasswordHistorySize() );
                }

                size = Math.max( orgInfo.getPasswordHistorySize(), size );
            }
        }

        return size;
    }


    @Override
    public boolean verifyAdminUserPassword( UUID userId, String password ) throws Exception {
        if ( ( userId == null ) || ( password == null ) ) {
            return false;
        }
        User user = emf.getEntityManager( smf.getManagementAppId() ).get( userId, User.class );

        return verify( smf.getManagementAppId(), user.getUuid(), password );
    }


    @Override
    public UserInfo verifyAdminUserPasswordCredentials( String name, String password ) throws Exception {

        if(logger.isTraceEnabled()){
            logger.trace("verifyAdminUserPasswordCredentials for {}", name);
        }

        User user = findUserEntity( smf.getManagementAppId(), name );
        if ( user == null ) {
            return null;
        }

        if ( verify( smf.getManagementAppId(), user.getUuid(), password ) ) {
            UserInfo userInfo = getUserInfo( smf.getManagementAppId(), user );

            boolean userIsSuperAdmin = properties.getSuperUser().isEnabled()
                && properties.getSuperUser().getEmail().equals(userInfo.getEmail());

            boolean testUserEnabled = parseBoolean( properties.getProperty( PROPERTIES_SETUP_TEST_ACCOUNT ) );
            boolean userIsTestUser = testUserEnabled && properties.getProperty(PROPERTIES_SYSADMIN_LOGIN_EMAIL)
                    .equals(userInfo.getEmail());

            if ( !userIsSuperAdmin && !userIsTestUser ) {

                if ( !userInfo.isConfirmed() && newAdminUsersRequireConfirmation() ) {
                    throw new UnconfirmedAdminUserException();
                }
                if ( !userInfo.isActivated() ) {
                    throw new UnactivatedAdminUserException();
                }
                if ( userInfo.isDisabled() ) {
                    throw new DisabledAdminUserException();
                }
            }
            return userInfo;
        }
        logger.info( "password compare fail for {}", name );
        return null;
    }


    @Override
    public UserInfo verifyMongoCredentials( String name, String nonce, String key ) throws Exception {

        Entity user = findUserEntity( smf.getManagementAppId(), name );

        if ( user == null ) {
            return null;
        }

        String mongo_pwd = readUserMongoPassword( smf.getManagementAppId(), user.getUuid(), user.getType() ).getSecret();

        if ( mongo_pwd == null ) {
            throw new IncorrectPasswordException( "Your mongo password has not be set" );
        }

        String expected_key = DigestUtils.md5Hex( nonce + user.getProperty( "username" ) + mongo_pwd );

        if ( !expected_key.equalsIgnoreCase( key ) ) {
            throw new IncorrectPasswordException();
        }

        UserInfo userInfo = new UserInfo( smf.getManagementAppId(), user.getProperties() );

        if ( !userInfo.isActivated() ) {
            throw new UnactivatedAdminUserException();
        }
        if ( userInfo.isDisabled() ) {
            throw new DisabledAdminUserException();
        }

        return userInfo;
    }


    public String getTokenForPrincipal( TokenCategory token_category, String token_type, UUID applicationId,
                                        AuthPrincipalType principal_type, UUID id, long duration ) throws Exception {

        return getTokenForPrincipal(token_category, token_type, applicationId, principal_type, id, duration, null);
    }

    // include workflowOrgId
    public String getTokenForPrincipal( TokenCategory token_category, String token_type, UUID applicationId,
                                        AuthPrincipalType principal_type, UUID id, long duration,
                                        UUID workflowOrgId) throws Exception {

        if ( anyNull(token_category, applicationId, principal_type, id) ) {
            return null;
        }

        return tokens
                .createToken( token_category, token_type, new AuthPrincipalInfo( principal_type, id, applicationId ),
                        null, duration, workflowOrgId );
    }


    public void revokeTokensForPrincipal( AuthPrincipalType principalType, UUID applicationId, UUID id )
            throws Exception {

        if ( anyNull( applicationId, principalType, id ) ) {
            throw new IllegalArgumentException( "applicationId, principal_type and id are required" );
        }

        AuthPrincipalInfo principal = new AuthPrincipalInfo( principalType, id, applicationId );

        tokens.removeTokens( principal );
    }


    public boolean validateTokenAndPrincipalTypes(TokenInfo tokenInfo, String expected_token_type,
                                                  AuthPrincipalType expected_principal_type) throws Exception {
        boolean success = true;
        if (tokenInfo == null || (expected_token_type != null && !expected_token_type.equals(tokenInfo.getType()))) {
            success = false;
        } else {
            AuthPrincipalInfo principal = tokenInfo.getPrincipal();
            if (principal == null ||
                    (expected_principal_type != null && !expected_principal_type.equals(principal.getType()))) {
                success = false;
            }
        }

        return success;
    }



    public TokenInfo getTokenInfoFromAccessToken(String token, String expected_token_type,
                                                 AuthPrincipalType expected_principal_type) throws Exception {

        return getTokenInfoFromAccessToken(token, expected_token_type, expected_principal_type, true);
    }

    public TokenInfo getTokenInfoFromAccessToken(String token, String expected_token_type,
                                                 AuthPrincipalType expected_principal_type,
                                                 boolean updateAccessTime) throws Exception {

        TokenInfo tokenInfo = tokens.getTokenInfo( token, updateAccessTime );

        return validateTokenAndPrincipalTypes(tokenInfo, expected_token_type, expected_principal_type) ?
                tokenInfo : null;
    }


    public AuthPrincipalInfo getPrincipalFromAccessToken(String token, String expected_token_type,
                                                         AuthPrincipalType expected_principal_type) throws Exception {

        // validates expected types
        TokenInfo tokenInfo = getTokenInfoFromAccessToken(token, expected_token_type, expected_principal_type);

        return tokenInfo != null ? tokenInfo.getPrincipal() : null;
    }


    public Entity getEntityFromAccessToken( String token, String expected_token_type,
                                            AuthPrincipalType expected_principal_type ) throws Exception {

        AuthPrincipalInfo principal =
                getPrincipalFromAccessToken(token, expected_token_type, expected_principal_type);
        if ( principal == null ) {
            return null;
        }

        return getEntityFromPrincipal( principal );
    }


    public Entity getEntityFromPrincipal( AuthPrincipalInfo principal ) throws Exception {

        EntityManager em = emf.getEntityManager(
            principal.getApplicationId() != null
                ? principal.getApplicationId() : smf.getManagementAppId() );

        return em.get(new SimpleEntityRef( principal.getType().getEntityType(), principal.getUuid()));
    }


    @Override
    public String getAccessTokenForAdminUser( UUID userId, long duration ) throws Exception {
        return getTokenForPrincipal( ACCESS, null, smf.getManagementAppId(), ADMIN_USER, userId, duration );
    }


  /*
   * (non-Javadoc)
   *
   * @see
   * org.apache.usergrid.management.ManagementService#revokeAccessTokensForAdminUser
   * (java.util.UUID)
   */
    @Override
    public void revokeAccessTokensForAdminUser( UUID userId ) throws Exception {
        revokeTokensForPrincipal(ADMIN_USER, smf.getManagementAppId(), userId);
    }


    @Override
    public void revokeAccessTokenForAdminUser( UUID userId, String token ) throws Exception {
        if ( anyNull( userId, token ) ) {
            throw new IllegalArgumentException( "token is required" );
        }

        Entity user = getAdminUserEntityFromAccessToken( token );
        if ( !user.getUuid().equals( userId ) ) {
            throw new TokenException( "Could not match token : " + token );
        }

        tokens.revokeToken(token);
    }


    @Override
    public Entity getAdminUserEntityFromAccessToken( String token ) throws Exception {

        return getEntityFromAccessToken(token, null, ADMIN_USER);
    }


    @Override
    public UserInfo getAdminUserInfoFromAccessToken( String token ) throws Exception {
        Entity user = getAdminUserEntityFromAccessToken(token);
        return new UserInfo( smf.getManagementAppId(), user.getProperties() );
    }


    @Override
    public BiMap<UUID, String> getOrganizationsForAdminUser( UUID userId ) throws Exception {

        if ( userId == null ) {
            return null;
        }

        BiMap<UUID, String> organizations = HashBiMap.create();
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        Results results = em.getCollection(  new SimpleEntityRef( User.ENTITY_TYPE, userId ),
            Schema.COLLECTION_GROUPS, null, 1000, Level.ALL_PROPERTIES, false );

        do {
            for ( Entity entity : results.getEntities() ) {

                String path = ( String ) entity.getProperty( PROPERTY_PATH );

                if ( path != null ) {
                    path = path.toLowerCase();
                }

                try {
                    organizations.put( entity.getUuid(), path );
                } catch (IllegalArgumentException e) {
                    logger.warn("Error adding {}:{} to BiMap: {}", entity.getUuid(), path, e.getMessage() );
                }
            }

            results = results.hasMoreResults() ? results.getNextPageResults() : null ;

        } while (results != null);

        return organizations;
    }


    @Override
    public Map<String, Object> getAdminUserOrganizationData( UUID userId ) throws Exception {
        UserInfo user = getAdminUserByUuid( userId );
        return getAdminUserOrganizationData( user, true );
    }


    @Override
    public Long getLastAdminPasswordChange( UUID userId ) throws Exception {
        CredentialsInfo ci = readUserPasswordCredentials(smf.getManagementAppId(), userId, User.ENTITY_TYPE);
        return ci.getCreated();
    }


    @Override
    public Map<String, Object> getAdminUserOrganizationData( UserInfo user, boolean deep ) throws Exception {

        Map<String, Object> json = new HashMap<>();

        json.putAll( JsonUtils.toJsonMap( user ) );

        Map<String, Map<String, Object>> jsonOrganizations = new HashMap<>();
        json.put( "organizations", jsonOrganizations );

        Map<UUID, String> organizations;

        AccountCreationProps.SuperUser superUser = properties.getSuperUser();
        if ( superUser.isEnabled() && superUser.getUsername().equals( user.getUsername() ) ) {
            int maxOrganizations = this.getAccountCreationProps().getMaxOrganizationsForSuperUserLogin();
            organizations = buildOrgBiMap( getOrganizations( null, maxOrganizations ) );
        }
        else {
            organizations = getOrganizationsForAdminUser( user.getUuid() );
        }

        for ( Entry<UUID, String> organization : organizations.entrySet() ) {
            Map<String, Object> jsonOrganization = new HashMap<>();

            jsonOrganizations.put( organization.getValue(), jsonOrganization );

            jsonOrganization.put( PROPERTY_NAME, organization.getValue() );
            jsonOrganization.put( PROPERTY_UUID, organization.getKey() );
            jsonOrganization.put( "properties", getOrganizationByUuid( organization.getKey() ).getProperties() );

            if ( deep ) {
                BiMap<UUID, String> applications = getApplicationsForOrganization( organization.getKey() );
                jsonOrganization.put( "applications", applications.inverse() );

                List<UserInfo> users = getAdminUsersForOrganization( organization.getKey() );
                Map<String, Object> jsonUsers = new HashMap<>();
                for ( UserInfo u : users ) {
                    jsonUsers.put( u.getUsername(), u );
                }
                jsonOrganization.put( "users", jsonUsers );
            }
        }

        return json;
    }


    @Override
    public Map<String, Object> getOrganizationData( OrganizationInfo organization ) throws Exception {

        Map<String, Object> jsonOrganization = new HashMap<>();
        jsonOrganization.putAll( JsonUtils.toJsonMap( organization ) );

        BiMap<UUID, String> applications = getApplicationsForOrganization( organization.getUuid() );
        jsonOrganization.put( "applications", applications.inverse() );

        List<UserInfo> users = getAdminUsersForOrganization( organization.getUuid() );
        Map<String, Object> jsonUsers = new HashMap<>();
        for ( UserInfo u : users ) {
            jsonUsers.put( u.getUsername(), u );
        }
        jsonOrganization.put( "users", jsonUsers );

        return jsonOrganization;
    }


    @Override
    public void addAdminUserToOrganization( UserInfo user, OrganizationInfo organization, boolean email )
            throws Exception {

        if ( ( user == null ) || ( organization == null ) ) {
            return;
        }

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );


        if(em.getCollection(organization.getUuid() ,"users",Query.fromQL( "select * where uuid ="+user.getUuid() ),Level.IDS ).size() >0){
            if(logger.isDebugEnabled()) {
                logger.debug( "addAdminUserToOrganization - Found value: {} already in collection", user.getName() );
            }
            return;
        }

        em.addToCollection(new SimpleEntityRef(Group.ENTITY_TYPE, organization.getUuid()), "users",
            new SimpleEntityRef(User.ENTITY_TYPE, user.getUuid()));

        invalidateManagementAppAuthCache();

        if ( email ) {
            sendAdminUserInvitedEmail( user, organization );
        }
    }


    @Override
    public void removeAdminUserFromOrganization( UUID userId, UUID organizationId ) throws Exception {
        removeAdminUserFromOrganization( userId, organizationId, false );
    }


    @Override
    public void removeAdminUserFromOrganization( UUID userId, UUID organizationId, boolean force ) throws Exception {

        if ( ( userId == null ) || ( organizationId == null ) ) {
            return;
        }

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

        try {
            int size = em.getCollection( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ),
                    "users", null, 2, Level.IDS, false ).size();

            if ( !force && size <= 1 ) {
                throw new Exception();
            }
        }
        catch ( Exception e ) {
            throw new UnableToLeaveOrganizationException( "Organizations must have at least one member." );
        }

        em.removeFromCollection(new SimpleEntityRef(Group.ENTITY_TYPE, organizationId), "users",
            new SimpleEntityRef(User.ENTITY_TYPE, userId));

        invalidateManagementAppAuthCache();
    }


    @Override
    public ApplicationInfo createApplication( UUID organizationId, String applicationName ) throws Exception {

        // DO NOT CHANGE THIS AS SOME EXTERNAL CLASSES MAY RELY ON THIS BEHAVIOR WHEN EXTENDING
        return createApplication( organizationId, applicationName, null );
    }


    @Override
    public ApplicationInfo createApplication( UUID organizationId, String applicationName,
                                              Map<String, Object> properties ) throws Exception {
        return createApplication(organizationId, applicationName, null, properties, false);
    }

    @Override
    public ApplicationInfo createApplication(UUID organizationId, String applicationName, UUID applicationId,
                                             Map<String, Object> properties, boolean forMigration) throws Exception {

        if ( ( organizationId == null ) || ( applicationName == null ) ) {
            return null;
        }

        if ( properties == null ) {
            properties = new HashMap<>();
        }

        OrganizationInfo organizationInfo = getOrganizationByUuid( organizationId );
        Entity appInfo = emf.createApplicationV2(
            organizationInfo.getName(), applicationName, applicationId ,properties, forMigration);

        // only generate a client secret on app creation when the app is not being created during appinfo migration
        if( !forMigration ){

            writeUserToken( smf.getManagementAppId(), appInfo,
                encryptionService.plainTextCredentials(
                    generateOAuthSecretKey( AuthPrincipalType.APPLICATION ),
                    null,
                    smf.getManagementAppId() ) );
        }


        applicationId = addApplicationToOrganization( organizationId, appInfo );

        UserInfo user = null;
        try {
            user = SubjectUtils.getUser();
        }
        catch ( UnavailableSecurityManagerException e ) {
            // occurs in the rare case that this is called before the full stack is initialized
            logger.warn("Error getting user, application created activity will not be created", e);
        }
        if ( ( user != null ) && user.isAdminUser() ) {
            postOrganizationActivity( organizationId, user, "create", appInfo, "Application", applicationName,
                "<a href=\"mailto:" + user.getEmail() + "\">" + user.getName() + " (" + user.getEmail()
                    + ")</a> created a new application named " + applicationName, null );
        }

        invalidateManagementAppAuthCache();

        return new ApplicationInfo( applicationId, appInfo.getName() );
    }



    @Override
    public void deleteApplication(UUID applicationId) throws Exception {
        emf.deleteApplication( applicationId );
    }


    @Override
    public ApplicationInfo restoreApplication(UUID applicationId) throws Exception {

        ApplicationInfo app = getDeletedApplicationInfo( applicationId );
        if ( app == null ) {
            throw new EntityNotFoundException("Deleted application ID " + applicationId + " not found");
        }

        if ( emf.lookupApplication( app.getName() ) != null ) {
            throw new ConflictException("Cannot restore application, one with that name already exists.");
        }

        // restore application_info entity

        EntityManager em = emf.getEntityManager( emf.getManagementAppId() );
        Entity appInfo = emf.restoreApplication(applicationId);

        // restore token

        writeUserToken( smf.getManagementAppId(), appInfo,
            encryptionService.plainTextCredentials(
                generateOAuthSecretKey( AuthPrincipalType.APPLICATION ),
                null,
                smf.getManagementAppId() ) );

        String orgName = appInfo.getName().split("/")[0];
        EntityRef alias = em.getAlias( Group.ENTITY_TYPE, orgName );
        Entity orgEntity = em.get( alias );

        addApplicationToOrganization( orgEntity.getUuid(), appInfo );

        // create activity

        UserInfo user = null;
        try {
            user = SubjectUtils.getUser();
        }
        catch ( UnavailableSecurityManagerException e ) {
            // occurs in the rare case that this is called before the full stack is initialized
            logger.warn("Error getting user, application restored created activity will not be created", e);
        }
        if ( ( user != null ) && user.isAdminUser() ) {
            postOrganizationActivity( orgEntity.getUuid(), user, "restore", appInfo, "Application", appInfo.getName(),
                "<a href=\"mailto:" + user.getEmail() + "\">" + user.getName() + " (" + user.getEmail()
                    + ")</a> restored an application named " + appInfo.getName(), null );
        }

        invalidateManagementAppAuthCache();

        return new ApplicationInfo( applicationId, appInfo.getName() );
    }

    @Override
    public long getApplicationSize(final UUID applicationId) {
        AggregationService aggregationService = aggregationServiceFactory.getAggregationService();
        ApplicationScope applicationScope =CpNamingUtils.getApplicationScope(applicationId);
        return aggregationService.getApplicationSize(applicationScope);
    }

    @Override
    public Map<String,Long> getEachCollectionSize(final UUID applicationId) {
        AggregationService aggregationService = aggregationServiceFactory.getAggregationService();
        ApplicationScope applicationScope =CpNamingUtils.getApplicationScope(applicationId);
        return aggregationService.getEachCollectionSize(applicationScope);
    }

    @Override
    public long getCollectionSize(final UUID applicationId, final String collectionName) {
        AggregationService aggregationService = aggregationServiceFactory.getAggregationService();
        ApplicationScope applicationScope =CpNamingUtils.getApplicationScope(applicationId);
        return aggregationService.getSize(applicationScope,
            CpNamingUtils.createCollectionSearchEdge(applicationScope.getApplication(), collectionName));
    }


    protected Entity getOrganizationEntityForApplication( UUID applicationInfoId ) throws Exception {
        if ( applicationInfoId == null ) {
            return null;
        }

        final EntityManager em = emf.getEntityManager(smf.getManagementAppId());

        Results r = em.getSourceEntities(
                new SimpleEntityRef(CpNamingUtils.APPLICATION_INFO, applicationInfoId),
                ORG_APP_RELATIONSHIP, Group.ENTITY_TYPE, Level.ALL_PROPERTIES);

        return r.getEntity();
    }

    @Override
    public UUID getOrganizationIdForApplication( UUID applicationInfoId ) throws Exception {

        Entity entity = getOrganizationEntityForApplication(applicationInfoId);

        return entity != null ? entity.getUuid() : null;
    }

    @Override
    public OrganizationInfo getOrganizationForApplication( UUID applicationInfoId ) throws Exception {

        Entity entity = getOrganizationEntityForApplication(applicationInfoId);

        return entity != null ?
                new OrganizationInfo( entity.getUuid(), ( String ) entity.getProperty( "path" ) ) :
                null;
    }


    @Override
    public BiMap<UUID, String> getApplicationsForOrganization( UUID organizationGroupId ) throws Exception {

        if ( organizationGroupId == null ) {
            return null;
        }
        final BiMap<UUID, String> applications = HashBiMap.create();
        final EntityManager em = emf.getEntityManager(smf.getManagementAppId());

        // query for application_info entities
        final Results results = em.getTargetEntities(
            new SimpleEntityRef(Group.ENTITY_TYPE, organizationGroupId),
            ORG_APP_RELATIONSHIP, CpNamingUtils.APPLICATION_INFO, Level.ALL_PROPERTIES);

        final PagingResultsIterator itr = new PagingResultsIterator( results );

        String entityName;

        while ( itr.hasNext() ) {

            final Entity entity = ( Entity ) itr.next();

            entityName = entity.getName();

            if ( entityName != null ) {
                entityName = entityName.toLowerCase();
            }

            // make sure we return applicationId and not the application_info UUID
            UUID applicationId = entity.getUuid();

            applications.put( applicationId, entityName );
        }


        return applications;
    }


    @Override
    public BiMap<UUID, String> getApplicationsForOrganizations( Set<UUID> organizationIds ) throws Exception {
        if ( organizationIds == null ) {
            return null;
        }
        BiMap<UUID, String> applications = HashBiMap.create();
        for ( UUID organizationId : organizationIds ) {
            BiMap<UUID, String> organizationApplications = getApplicationsForOrganization( organizationId );
            applications.putAll( organizationApplications );
        }
        return applications;
    }


    /**
     * @return UUID of the application itself (NOT the application_info entity).
     */
    @Override
    public UUID addApplicationToOrganization(UUID organizationId, Entity appInfo) throws Exception {

        UUID applicationId = appInfo.getUuid();

        if ( ( organizationId == null ) || ( applicationId == null ) ) {
            return null;
        }

        EntityManager em = emf.getEntityManager(smf.getManagementAppId());
        em.createConnection( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), ORG_APP_RELATIONSHIP, appInfo );

        return applicationId;
    }


    @Override
    public void deleteOrganizationApplication( UUID organizationId, UUID applicationId ) throws Exception {
        // TODO Auto-generated method stub

    }


    @Override
    public void removeOrganizationApplication( UUID organizationId, UUID applicationId ) throws Exception {
        // TODO Auto-generated method stub

    }


    @Override
    public ApplicationInfo getApplicationInfo( String applicationName ) throws Exception {
        if ( applicationName == null ) {
            return null;
        }
        UUID applicationId = emf.lookupApplication(applicationName);
        if ( applicationId == null ) {
            return null;
        }
        return new ApplicationInfo( applicationId, applicationName.toLowerCase() );
    }


    @Override
    public ApplicationInfo getApplicationInfo( UUID applicationId ) throws Exception {
        if ( applicationId == null ) {
            return null;
        }
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        Entity entity = em.get(new SimpleEntityRef(CpNamingUtils.APPLICATION_INFO, applicationId));

        if ( entity != null ) {
            return new ApplicationInfo( applicationId, entity.getName() );
        }
        return null;
    }


    @Override
    public ApplicationInfo getDeletedApplicationInfo(UUID applicationId) throws Exception {
        if ( applicationId == null ) {
            return null;
        }
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

        final Entity entity = em.get( new SimpleEntityRef( CpNamingUtils.DELETED_APPLICATION_INFO, applicationId ) );

        if ( entity != null ) {
            return new ApplicationInfo( applicationId, entity.getName() );
        }
        return null;
    }


    @Override
    public ApplicationInfo getApplicationInfo( Identifier id ) throws Exception {
        if ( id == null ) {
            return null;
        }
        if ( id.isUUID() ) {
            return getApplicationInfo( id.getUUID() );
        }
        if ( id.isName() ) {
            return getApplicationInfo( id.getName() );
        }
        return null;
    }


    @Override
    public ApplicationInfo getApplicationInfoFromAccessToken( String token ) throws Exception {
        Entity entity = getEntityFromAccessToken( token, null, APPLICATION );
        if ( entity == null ) {
            throw new TokenException( "Could not find an entity for that access token: " + token );
        }
        return new ApplicationInfo( entity.getProperties() );
    }


    @Override
    public ServiceResults getApplicationMetadata( UUID applicationId ) throws Exception {

        if ( applicationId == null ) {
            return ServiceResults.genericServiceResults();
        }

        EntityManager em = emf.getEntityManager( applicationId );
        Entity entity = em.get( em.getApplicationRef() );

        Results r = Results.fromEntity( entity );

        Map<String, Object> collections = em.getApplicationCollectionMetadata();
        if ( collections.size() > 0 ) {
            r.setMetadata( em.getApplicationRef().getUuid(), "collections", collections );
        }
        return genericServiceResults( r );
    }


    public String getSecret( UUID applicationId, AuthPrincipalType type, UUID entityId ) throws Exception {

        if ( AuthPrincipalType.ORGANIZATION.equals( type )) {
            UUID ownerId = smf.getManagementAppId();
            return getCredentialsSecret( readUserToken( ownerId, entityId, Group.ENTITY_TYPE ) );

        } else if ( AuthPrincipalType.APPLICATION.equals( type ) ) {
            UUID ownerId = smf.getManagementAppId();
            return getCredentialsSecret( readUserToken( ownerId, entityId, Application.ENTITY_TYPE ) );

        }
        else if ( AuthPrincipalType.ADMIN_USER.equals( type ) || AuthPrincipalType.APPLICATION_USER.equals( type ) ) {
            return getCredentialsSecret( readUserPasswordCredentials( applicationId, entityId, User.ENTITY_TYPE ) );
        }

        throw new IllegalArgumentException( "Must specify an admin user, organization or application principal" );
    }


    @Override
    public String getClientIdForOrganization( UUID organizationId ) {
        return ClientCredentialsInfo.getClientIdForTypeAndUuid( AuthPrincipalType.ORGANIZATION, organizationId );
    }


    @Override
    public String getClientSecretForOrganization( UUID organizationId ) throws Exception {
        return getSecret(smf.getManagementAppId(), AuthPrincipalType.ORGANIZATION, organizationId);
    }


    @Override
    public String getClientIdForApplication( UUID applicationId ) {
        return ClientCredentialsInfo.getClientIdForTypeAndUuid(AuthPrincipalType.APPLICATION, applicationId);
    }


    @Override
    public String getClientSecretForApplication( UUID applicationId ) throws Exception {
        return getSecret(smf.getManagementAppId(), AuthPrincipalType.APPLICATION, applicationId);
    }


    public String newSecretKey( AuthPrincipalType type, UUID id ) throws Exception {
        String secret = generateOAuthSecretKey( type );

        writeUserToken( smf.getManagementAppId(), new SimpleEntityRef( type.getEntityType(), id ),
                encryptionService.plainTextCredentials( secret, id, smf.getManagementAppId() ) );

        return secret;
    }


    @Override
    public String newClientSecretForOrganization( UUID organizationId ) throws Exception {
        return newSecretKey( AuthPrincipalType.ORGANIZATION, organizationId );
    }


    @Override
    public String newClientSecretForApplication( UUID applicationId ) throws Exception {
        return newSecretKey( AuthPrincipalType.APPLICATION, applicationId );
    }


    @Override
    public AccessInfo authorizeClient( String clientId, String clientSecret, long ttl ) throws Exception {
        if ( ( clientId == null ) || ( clientSecret == null ) ) {
            return null;
        }
        UUID uuid = getUUIDFromClientId( clientId );
        if ( uuid == null ) {
            return null;
        }
        AuthPrincipalType type = getTypeFromClientId( clientId );
        if ( type == null ) {
            return null;
        }
        AccessInfo access_info = null;

        if ( clientSecret.equals( getSecret( smf.getManagementAppId(), type, uuid ) ) ) {

            String token = getTokenForPrincipal( ACCESS, null, smf.getManagementAppId(), type, uuid, ttl );

            long duration = tokens.getMaxTokenAgeInSeconds( token );

            access_info = new AccessInfo().withExpiresIn( duration ).withAccessToken( token );

            if ( type.equals( AuthPrincipalType.APPLICATION ) ) {
                ApplicationInfo app = getApplicationInfo( uuid );
                access_info = access_info.withProperty( "application", app.getId() );
            }
            else if ( type.equals( AuthPrincipalType.ORGANIZATION ) ) {
                OrganizationInfo organization = getOrganizationByUuid( uuid );
                access_info = access_info.withProperty( "organization", getOrganizationData( organization ) );
            }
        }
        return access_info;
    }


    @Override
    public PrincipalCredentialsToken getPrincipalCredentialsTokenForClientCredentials( String clientId,
                                                                                       String clientSecret )
            throws Exception {
        if ( ( clientId == null ) || ( clientSecret == null ) ) {
            return null;
        }
        UUID uuid = getUUIDFromClientId( clientId );
        if ( uuid == null ) {
            return null;
        }
        AuthPrincipalType type = getTypeFromClientId( clientId );
        if ( type == null ) {
            return null;
        }

        PrincipalCredentialsToken token = null;
        if ( clientSecret.equals( getSecret( smf.getManagementAppId(), type, uuid))) {
            if ( type.equals( AuthPrincipalType.APPLICATION ) ) {
                ApplicationInfo app = getApplicationInfo( uuid );
                token = new PrincipalCredentialsToken( new ApplicationPrincipal( app ),
                        new ApplicationClientCredentials( clientId, clientSecret ) );
            }
            else if ( type.equals( AuthPrincipalType.ORGANIZATION ) ) {
                OrganizationInfo organization = getOrganizationByUuid( uuid );
                token = new PrincipalCredentialsToken( new OrganizationPrincipal( organization ),
                        new OrganizationClientCredentials( clientId, clientSecret ) );
            }
        }
        return token;
    }


    public AccessInfo authorizeAppUser( String clientType, String clientId, String clientSecret ) throws Exception {

        return null;
    }


    @Override
    public String getPasswordResetTokenForAdminUser( UUID userId, long ttl, UUID organizationId ) throws Exception {
        return getTokenForPrincipal( EMAIL, TOKEN_TYPE_PASSWORD_RESET, smf.getManagementAppId(), ADMIN_USER, userId,
                ttl, organizationId );
    }


    @Override
    public TokenInfo getPasswordResetTokenInfoForAdminUser( String token ) throws Exception {
        TokenInfo tokenInfo = null;
        try {
            tokenInfo = getTokenInfoFromAccessToken(token, TOKEN_TYPE_PASSWORD_RESET, ADMIN_USER);
        }
        catch (Exception e) {
            // intentionally empty
        }
        return tokenInfo;
    }


    @Override
    public boolean checkPasswordResetTokenForAdminUser( UUID userId, String token ) throws Exception {
        return checkPasswordResetTokenForAdminUser(userId, getPasswordResetTokenInfoForAdminUser(token));
    }


    @Override
    public boolean checkPasswordResetTokenForAdminUser( UUID userId, TokenInfo tokenInfo ) throws Exception {
        if (tokenInfo == null) {
            return false;
        }
        AuthPrincipalInfo principal = null;
        try {
            principal = tokenInfo.getPrincipal();
        }
        catch ( Exception e ) {
            logger.error( "Unable to verify token", e );
        }
        return ( principal != null ) && userId.equals( principal.getUuid() );
    }


    @Override
    public String getActivationTokenForAdminUser( UUID userId, long ttl, UUID organizationId ) throws Exception {
        return getTokenForPrincipal( EMAIL, TOKEN_TYPE_ACTIVATION, smf.getManagementAppId(), ADMIN_USER, userId,
                ttl, organizationId );
    }


    @Override
    public String getConfirmationTokenForAdminUser( UUID userId, long ttl, UUID organizationId ) throws Exception {
        return getTokenForPrincipal( EMAIL, TOKEN_TYPE_CONFIRM, smf.getManagementAppId(), ADMIN_USER, userId,
                ttl, organizationId );
    }


    @Override
    public void activateAdminUser( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "activated", true );

        invalidateManagementAppAuthCache();
    }


    @Override
    public User deactivateUser( UUID applicationId, UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( applicationId );

        User user = em.get( userId, User.class );

        if ( user == null ) {
            throw new ManagementException(
                    String.format( "User with id %s does not exist in app %s", userId, applicationId ) );
        }

        user.setActivated( false );
        user.setDeactivated( System.currentTimeMillis() );

        em.update( user );

        // revoke all access tokens for the app
        revokeAccessTokensForAppUser(applicationId, userId);

        return user;
    }


    @Override
    public boolean isAdminUserActivated( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        return Boolean.TRUE.equals( em.getProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "activated" ) );
    }


    @Override
    public void confirmAdminUser( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "confirmed", true );
    }


    @Override
    public void unconfirmAdminUser( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "confirmed", false );
    }


    @Override
    public boolean isAdminUserConfirmed( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        return Boolean.TRUE.equals( em.getProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "confirmed" ) );
    }


    @Override
    public void enableAdminUser( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "disabled", false );
    }


    @Override
    public void disableAdminUser( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "disabled", true );

        revokeAccessTokensForAdminUser(userId);
    }


    @Override
    public boolean isAdminUserEnabled( UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        return !Boolean.TRUE.equals( em.getProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "disabled" ) );
    }


    public String emailMsg( Map<String, String> values, String propertyName ) {
        return new StrSubstitutor( values ).replace( properties.getProperty( propertyName ) );
    }


    private String appendEmailFooter( String msg ) {
        return msg + "\n" + properties.getProperty( PROPERTIES_EMAIL_FOOTER );
    }


    @Override
    public void startAdminUserPasswordResetFlow( UUID organizationId, UserInfo user ) throws Exception {
        String token = getPasswordResetTokenForAdminUser( user.getUuid(), 0, organizationId );

        OrganizationConfig orgConfig = organizationId != null ?
                getOrganizationConfigByUuid(organizationId) : getOrganizationConfigForUserInfo(user);
        String resetPropertyUrl = orgConfig.getFullUrlTemplate(WorkflowUrl.ADMIN_RESETPW_URL);
        String reset_url = String.format(resetPropertyUrl, user.getUuid().toString())
                + "?token=" + token;

        Map<String, String> pageContext = hashMap( "reset_url", reset_url )
                .map( "reset_url_base", resetPropertyUrl )
                .map( "user_uuid", user.getUuid().toString() ).map( "raw_token", token );

        sendHtmlMail( properties, user.getDisplayEmailAddress(), properties.getProperty( PROPERTIES_MAILER_EMAIL ),
                "Password Reset", appendEmailFooter( emailMsg( pageContext, PROPERTIES_EMAIL_ADMIN_PASSWORD_RESET ) ) );
    }


    @Override
    public String getActivationTokenForOrganization( UUID organizationId, long ttl ) throws Exception {
        return getTokenForPrincipal( EMAIL, TOKEN_TYPE_ACTIVATION, smf.getManagementAppId(), ORGANIZATION,
                organizationId, ttl );
    }


    @Override
    public void startOrganizationActivationFlow( OrganizationInfo organization ) throws Exception {
        logger.info( "startOrganizationActivationFlow: {}", organization.getName() );

        try {
            UUID organizationId = organization.getUuid();
            String token = getActivationTokenForOrganization( organizationId, 0 );
            OrganizationConfig orgConfig = getOrganizationConfigByUuid(organizationId);
            String activationPropertyUrl = orgConfig.getFullUrlTemplate(WorkflowUrl.ORGANIZATION_ACTIVATION_URL);
            String activation_url = String.format(activationPropertyUrl, organizationId.toString())
                    + "?token=" + token;

            List<UserInfo> users = getAdminUsersForOrganization( organizationId );
            String organization_owners = null;
            for ( UserInfo user : users ) {
                organization_owners = ( organization_owners == null ) ? user.getHTMLDisplayEmailAddress() :
                                      organization_owners + ", " + user.getHTMLDisplayEmailAddress();
            }
            if ( newOrganizationsNeedSysAdminApproval() ) {
                logger.info( "sending SysAdminApproval confirmation email: {}", organization.getName() );
                //TODO: org shouldn't approve org activation, right?
                sendHtmlMail( properties, getOrgSystemEmail(),
                        properties.getProperty( PROPERTIES_MAILER_EMAIL ),
                        "Request For Organization Account Activation " + organization.getName(), appendEmailFooter(
                        emailMsg( hashMap( "organization_name", organization.getName() )
                                .map( "activation_url", activation_url )
                                .map( "organization_owners", organization_owners ),
                                PROPERTIES_EMAIL_SYSADMIN_ORGANIZATION_ACTIVATION ) ) );
                sendOrganizationEmail( organization, "Organization Account Confirmed",
                        emailMsg( hashMap( "organization_name", organization.getName() ),
                                PROPERTIES_EMAIL_ORGANIZATION_CONFIRMED_AWAITING_ACTIVATION ) );
            }
            else if ( properties.newOrganizationsRequireConfirmation() ) {
                logger.info( "sending account confirmation email: {}", organization.getName() );
                sendOrganizationEmail( organization, "Organization Account Confirmation", emailMsg(
                        hashMap( "organization_name", organization.getName() )
                                .map( "confirmation_url", activation_url ),
                        PROPERTIES_EMAIL_ORGANIZATION_CONFIRMATION ) );
                sendSysAdminNewOrganizationActivatedNotificationEmail( organization );
            }
            else {
                logger.info( "activating organization (no confirmation): {}", organization.getName() );
                activateOrganization( organization, false );
                sendSysAdminNewOrganizationActivatedNotificationEmail( organization );
            }
        }
        catch ( Exception e ) {
            logger.error( "Unable to send activation emails to {}", organization.getName(), e );
        }
    }


    @Override
    public ActivationState handleActivationTokenForOrganization( UUID organizationId, String token ) throws Exception {
        AuthPrincipalInfo principal = getPrincipalFromAccessToken( token, TOKEN_TYPE_ACTIVATION, ORGANIZATION );
        if ( ( principal != null ) && organizationId.equals( principal.getUuid() ) ) {
            OrganizationInfo organization = this.getOrganizationByUuid( organizationId );
            sendOrganizationActivatedEmail( organization );
            sendSysAdminNewOrganizationActivatedNotificationEmail( organization );

            activateOrganization( organization, false );

            return ActivationState.ACTIVATED;
        }
        return ActivationState.UNKNOWN;
    }


    public void sendOrganizationActivatedEmail( OrganizationInfo organization ) throws Exception {
        sendOrganizationEmail( organization, "Organization Account Activated: " + organization.getName(),
                emailMsg( hashMap( "organization_name", organization.getName() ),
                        PROPERTIES_EMAIL_ORGANIZATION_ACTIVATED ) );
    }


    public void sendSysAdminNewOrganizationActivatedNotificationEmail( OrganizationInfo organization )
            throws Exception {
        if ( properties.notifySysAdminOfNewOrganizations() ) {
            List<UserInfo> users = getAdminUsersForOrganization( organization.getUuid() );
            String organization_owners = null;
            for ( UserInfo user : users ) {
                organization_owners = ( organization_owners == null ) ? user.getHTMLDisplayEmailAddress() :
                                      organization_owners + ", " + user.getHTMLDisplayEmailAddress();
            }
            //TODO: email for org admin or sysadmin?
            sendHtmlMail( properties, getOrgSystemEmail(),
                    properties.getProperty( PROPERTIES_MAILER_EMAIL ),
                    "Organization Account Activated " + organization.getName(), appendEmailFooter( emailMsg(
                    hashMap( "organization_name", organization.getName() )
                            .map( "organization_owners", organization_owners ),
                    PROPERTIES_EMAIL_SYSADMIN_ORGANIZATION_ACTIVATED ) ) );
        }
    }


    @Override
    public void sendOrganizationEmail( OrganizationInfo organization, String subject, String html ) throws Exception {
        List<UserInfo> users = getAdminUsersForOrganization( organization.getUuid() );
        for ( UserInfo user : users ) {
            sendHtmlMail( properties, user.getDisplayEmailAddress(), properties.getProperty( PROPERTIES_MAILER_EMAIL ),
                    subject, appendEmailFooter( html ) );
        }
    }


    @Override
    public void startAdminUserActivationFlow( UUID organizationId, UserInfo user ) throws Exception {
        if ( user.isActivated() ) {
            sendAdminUserConfirmationEmail( organizationId, user );
            sendAdminUserActivatedEmail( user );
            sendSysAdminNewAdminActivatedNotificationEmail( organizationId, user );
        }
        else {
            if ( newAdminUsersRequireConfirmation() ) {
                sendAdminUserConfirmationEmail( organizationId, user );
            }
            else if ( newAdminUsersNeedSysAdminApproval() ) {
                sendSysAdminRequestAdminActivationEmail( organizationId, user );
            }
            else {
                // sdg: There seems to be a hole in the logic. The user has been
                // created
                // in an inactive state but nobody is being notified.
                activateAdminUser( user.getUuid() );
            }
        }
    }


    @Override
    public TokenInfo getConfirmationTokenInfoForAdminUser( String token ) throws Exception {
        return getTokenInfoFromAccessToken(token, TOKEN_TYPE_CONFIRM, ADMIN_USER);
    }


    @Override
    public ActivationState handleConfirmationTokenForAdminUser( UUID userId, String token ) throws Exception {
        return handleConfirmationTokenForAdminUser(userId, getConfirmationTokenInfoForAdminUser(token));
    }


    @Override
    // token may contain the workflow organization id
    public ActivationState handleConfirmationTokenForAdminUser( UUID userId, TokenInfo tokenInfo ) throws Exception {
        if (tokenInfo != null) {
            AuthPrincipalInfo principal = tokenInfo.getPrincipal();
            if ((principal != null) && userId.equals(principal.getUuid())) {
                UUID workflowOrgId = tokenInfo.getWorkflowOrgId();
                UserInfo user = getAdminUserByUuid(principal.getUuid());
                confirmAdminUser(user.getUuid());
                if (newAdminUsersNeedSysAdminApproval()) {
                    sendAdminUserConfirmedAwaitingActivationEmail(user);
                    sendSysAdminRequestAdminActivationEmail(workflowOrgId, user);
                    return ActivationState.CONFIRMED_AWAITING_ACTIVATION;
                } else {
                    activateAdminUser(principal.getUuid());
                    sendAdminUserActivatedEmail(user);
                    sendSysAdminNewAdminActivatedNotificationEmail(workflowOrgId, user);
                    return ActivationState.ACTIVATED;
                }
            }
        }
        return ActivationState.UNKNOWN;
    }


    @Override
    public TokenInfo getActivationTokenInfoForAdminUser( String token ) throws Exception {
        return getTokenInfoFromAccessToken(token, TOKEN_TYPE_ACTIVATION, ADMIN_USER);
    }


    @Override
    public ActivationState handleActivationTokenForAdminUser( UUID userId, String token ) throws Exception {
        return handleActivationTokenForAdminUser(userId, getActivationTokenInfoForAdminUser(token));
    }


    @Override
    // token may contain the workflow organization id
    public ActivationState handleActivationTokenForAdminUser( UUID userId, TokenInfo tokenInfo ) throws Exception {
        if (tokenInfo != null) {
            AuthPrincipalInfo principal = tokenInfo.getPrincipal();
            if ((principal != null) && userId.equals(principal.getUuid())) {
                UUID workflowOrgId = tokenInfo.getWorkflowOrgId();
                activateAdminUser(principal.getUuid());
                UserInfo user = getAdminUserByUuid(principal.getUuid());
                sendAdminUserActivatedEmail(user);
                sendSysAdminNewAdminActivatedNotificationEmail(workflowOrgId, user);
                return ActivationState.ACTIVATED;
            }
        }
        return ActivationState.UNKNOWN;
    }


    public void sendAdminUserConfirmationEmail( UUID organizationId, UserInfo user ) throws Exception {
        String token = getConfirmationTokenForAdminUser(user.getUuid(), 0, organizationId);
        OrganizationConfig orgConfig = organizationId != null ?
                getOrganizationConfigByUuid(organizationId) : getOrganizationConfigForUserInfo(user);
        String confirmation_url = orgConfig.getFullUrl(WorkflowUrl.ADMIN_CONFIRMATION_URL, user.getUuid().toString()) +
                "?token=" + token;
        sendAdminUserEmail( user, "User Account Confirmation: " + user.getEmail(),
                emailMsg( hashMap( "confirm_email", user.getEmail() ).map( "confirmation_url", confirmation_url ),
                        PROPERTIES_EMAIL_ADMIN_CONFIRMATION ) );
    }


    public void sendSysAdminRequestAdminActivationEmail( UUID organizationId, UserInfo user ) throws Exception {
        String token = getActivationTokenForAdminUser(user.getUuid(), 0, organizationId);
        //TODO: admin specific email
        OrganizationConfig orgConfig = organizationId != null ?
                getOrganizationConfigByUuid(organizationId) : getOrganizationConfigForUserInfo(user);
        String activation_url = orgConfig.getFullUrl(WorkflowUrl.ADMIN_ACTIVATION_URL, user.getUuid().toString()) +
                "?token=" + token;
        String adminSystemEmail = organizationId != null ? getAdminSystemEmailForOrganization(organizationId) :
                getAdminSystemEmailForApplication(user.getApplicationId());
        sendHtmlMail(properties, adminSystemEmail, properties.getProperty(PROPERTIES_MAILER_EMAIL),
            "Request For Admin User Account Activation " + user.getEmail(), appendEmailFooter(
                emailMsg(hashMap("user_email", user.getEmail()).map("activation_url", activation_url),
                    PROPERTIES_EMAIL_SYSADMIN_ADMIN_ACTIVATION)));
    }


    public void sendSysAdminNewAdminActivatedNotificationEmail( UUID organizationId, UserInfo user ) throws Exception {
        if ( properties.notifySysAdminOfNewAdminUsers() ) {
            String adminSystemEmail = organizationId != null ? getAdminSystemEmailForOrganization(organizationId) :
                    getAdminSystemEmailForApplication(user.getApplicationId());
            sendHtmlMail( properties, adminSystemEmail, properties.getProperty( PROPERTIES_MAILER_EMAIL ),
                    "Admin User Account Activated " + user.getEmail(), appendEmailFooter(
                    emailMsg( hashMap( "user_email", user.getEmail() ), PROPERTIES_EMAIL_SYSADMIN_ADMIN_ACTIVATED ) ) );
        }
    }


    public void sendAdminUserConfirmedAwaitingActivationEmail( UserInfo user ) throws Exception {
        sendAdminUserEmail(user, "User Account Confirmed",
                emailMsg( hashMap("confirmed_email",user.getEmail() ),
                    PROPERTIES_EMAIL_ADMIN_CONFIRMED_AWAITING_ACTIVATION ) );
    }


    public void sendAdminUserActivatedEmail( UserInfo user ) throws Exception {
        if ( properties.notifyAdminOfActivation() ) {
            sendAdminUserEmail( user, "User Account Activated",
                    properties.getProperty( PROPERTIES_EMAIL_ADMIN_ACTIVATED ) );
        }
    }


    public void sendAdminUserInvitedEmail( UserInfo user, OrganizationInfo organization ) throws Exception {
        sendAdminUserEmail( user, "User Invited To Organization",
                emailMsg( hashMap( "organization_name", organization.getName() ), PROPERTIES_EMAIL_ADMIN_INVITED ) );
    }


    @Override
    public void sendAdminUserEmail( UserInfo user, String subject, String html ) throws Exception {
        sendHtmlMail(properties, user.getDisplayEmailAddress(), properties.getProperty(PROPERTIES_MAILER_EMAIL),
            subject, appendEmailFooter(html));
    }


    @Override
    public void activateOrganization( OrganizationInfo organization ) throws Exception {
        activateOrganization(organization, true);
    }


    private void activateOrganization( OrganizationInfo organization, boolean sendEmail ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( Group.ENTITY_TYPE, organization.getUuid() ), "activated", true );
        List<UserInfo> users = getAdminUsersForOrganization( organization.getUuid() );
        for ( UserInfo user : users ) {
            boolean confirmed = user.isConfirmed() || !newAdminUsersRequireConfirmation();
            boolean shouldActivate = confirmed && !newAdminUsersRequireConfirmation();
            if ( shouldActivate ) {
                activateAdminUser( user.getUuid() );
            }
        }
        if ( sendEmail ) {
            startOrganizationActivationFlow( organization );
        }

    }


    @Override
    public void deactivateOrganization( UUID organizationId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), "activated", false );
    }


    @Override
    public boolean isOrganizationActivated( UUID organizationId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        return Boolean.TRUE.equals(
                em.getProperty( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), "activated" ) );
    }


    @Override
    public void enableOrganization( UUID organizationId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), "disabled", false );
    }


    @Override
    public void disableOrganization( UUID organizationId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        em.setProperty( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), "disabled", true );
    }


    @Override
    public boolean isOrganizationEnabled( UUID organizationId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        return !Boolean.TRUE.equals(
                em.getProperty( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), "disabled" ) );
    }


    @Override
    public boolean checkPasswordResetTokenForAppUser( UUID applicationId, UUID userId, String token ) throws Exception {
        AuthPrincipalInfo principal = null;
        try {
            principal = getPrincipalFromAccessToken( token, TOKEN_TYPE_PASSWORD_RESET, APPLICATION_USER );
        }
        catch ( Exception e ) {
            logger.error( "Unable to verify token", e );
        }
        return ( principal != null ) && userId.equals( principal.getUuid() );
    }


    @Override
    public String getAccessTokenForAppUser( UUID applicationId, UUID userId, long duration ) throws Exception {
        return getTokenForPrincipal( ACCESS, null, applicationId, APPLICATION_USER, userId, duration );
    }


    /*
   * (non-Javadoc)
   *
   * @see
   * org.apache.usergrid.management.ManagementService#revokeAccessTokensForAappUser
   * (java.util.UUID, java.util.UUID)
   */
    @Override
    public void revokeAccessTokensForAppUser( UUID applicationId, UUID userId ) throws Exception {
        revokeTokensForPrincipal( APPLICATION_USER, applicationId, userId );
    }


    @Override
    public void revokeAccessTokenForAppUser( String token ) throws Exception {
        if ( anyNull( token ) ) {
            throw new IllegalArgumentException( "token is required" );
        }

        UserInfo userInfo = getAppUserFromAccessToken( token );
        if ( userInfo == null ) {
            throw new TokenException( "Could not match token : " + token );
        }

        tokens.revokeToken(token);
    }


    @Override
    public UserInfo getAppUserFromAccessToken( String token ) throws Exception {
        AuthPrincipalInfo auth_principal = getPrincipalFromAccessToken( token, null, APPLICATION_USER );
        if ( auth_principal == null ) {
            return null;
        }
        UUID appId = auth_principal.getApplicationId();
        if ( appId != null ) {
            Entity user = getAppUserByIdentifier( appId, Identifier.fromUUID( auth_principal.getUuid() ) );
            if ( user != null ) {
                return new UserInfo( appId, user.getProperties() );
            }
        }
        return null;
    }


    @Override
    public User getAppUserByIdentifier( UUID applicationId, Identifier identifier ) throws Exception {
        EntityManager em = emf.getEntityManager(applicationId);
        return em.get( em.getUserByIdentifier( identifier ), User.class );
    }


    @Override
    public void startAppUserPasswordResetFlow( UUID applicationId, User user ) throws Exception {
        String token = getPasswordResetTokenForAppUser(applicationId, user.getUuid());
        OrganizationConfig orgConfig = getOrganizationConfigForApplication(applicationId);
        String resetPropertyUrl = orgConfig.getFullUrlTemplate(WorkflowUrl.USER_RESETPW_URL);
        String reset_url =
                buildUserAppUrl( applicationId, resetPropertyUrl, user, token);
        Map<String, String> pageContext = hashMap( "reset_url", reset_url )
                .map( "reset_url_base", resetPropertyUrl )
                .map( "user_uuid", user.getUuid().toString() ).map( "raw_token", token )
                .map( "application_id", applicationId.toString() );
    /*
     * String reset_url = String.format(
     * properties.getProperty(PROPERTIES_USER_RESETPW_URL), oi.getName(),
     * ai.getName(), user.getUuid().toString()) + "?token=" + token;
     */
        sendHtmlMail( properties, user.getDisplayEmailAddress(), properties.getProperty( PROPERTIES_MAILER_EMAIL ),
                "Password Reset", appendEmailFooter( emailMsg( pageContext, PROPERTIES_EMAIL_USER_PASSWORD_RESET ) ) );
    }


    @Override
    public boolean newAppUsersNeedAdminApproval( UUID applicationId ) throws Exception {
        EntityManager em = emf.getEntityManager(applicationId);
        Boolean registration_requires_admin_approval = ( Boolean ) em
                .getProperty( new SimpleEntityRef( Application.ENTITY_TYPE, applicationId ),
                        REGISTRATION_REQUIRES_ADMIN_APPROVAL );
        return registration_requires_admin_approval != null && registration_requires_admin_approval;
    }


    @Override
    public boolean newAppUsersRequireConfirmation( UUID applicationId ) throws Exception {
        EntityManager em = emf.getEntityManager( applicationId );
        Boolean registration_requires_email_confirmation = ( Boolean ) em
                .getProperty( new SimpleEntityRef( Application.ENTITY_TYPE, applicationId ),
                        REGISTRATION_REQUIRES_EMAIL_CONFIRMATION );
        return registration_requires_email_confirmation != null && registration_requires_email_confirmation;
    }


    public boolean notifyAdminOfNewAppUsers( UUID applicationId ) throws Exception {
        EntityManager em = emf.getEntityManager( applicationId );
        Boolean notify_admin_of_new_users = ( Boolean ) em
                .getProperty( new SimpleEntityRef( Application.ENTITY_TYPE, applicationId ),
                        NOTIFY_ADMIN_OF_NEW_USERS );
        return notify_admin_of_new_users != null && notify_admin_of_new_users;
    }


    @Override
    public void startAppUserActivationFlow( UUID applicationId, User user ) throws Exception {
        if ( newAppUsersRequireConfirmation( applicationId ) ) {
            sendAppUserConfirmationEmail( applicationId, user );
        }
        else if ( newAppUsersNeedAdminApproval( applicationId ) ) {
            sendAdminRequestAppUserActivationEmail( applicationId, user );
        }
        else {
            sendAppUserActivatedEmail( applicationId, user );
            sendAdminNewAppUserActivatedNotificationEmail( applicationId, user );
        }
    }


    @Override
    public ActivationState handleConfirmationTokenForAppUser( UUID applicationId, UUID userId, String token )
            throws Exception {
        AuthPrincipalInfo principal = getPrincipalFromAccessToken( token, TOKEN_TYPE_CONFIRM, APPLICATION_USER );

        if ( ( principal != null ) && userId.equals( principal.getUuid() ) ) {
            EntityManager em = emf.getEntityManager( applicationId );
            User user = em.get( userId, User.class );
            confirmAppUser( applicationId, user.getUuid() );

            if ( newAppUsersNeedAdminApproval( applicationId ) ) {
                sendAppUserConfirmedAwaitingActivationEmail( applicationId, user );
                sendAdminRequestAppUserActivationEmail( applicationId, user );
                return ActivationState.CONFIRMED_AWAITING_ACTIVATION;
            }
            else {
                activateAppUser( applicationId, principal.getUuid() );
                sendAppUserActivatedEmail( applicationId, user );
                sendAdminNewAppUserActivatedNotificationEmail( applicationId, user );
                return ActivationState.ACTIVATED;
            }
        }

        return ActivationState.UNKNOWN;
    }


    @Override
    public ActivationState handleActivationTokenForAppUser( UUID applicationId, UUID userId, String token )
            throws Exception {
        AuthPrincipalInfo principal = getPrincipalFromAccessToken( token, TOKEN_TYPE_ACTIVATION, APPLICATION_USER );
        if ( ( principal != null ) && userId.equals( principal.getUuid() ) ) {
            activateAppUser( applicationId, principal.getUuid() );
            EntityManager em = emf.getEntityManager( applicationId );
            User user = em.get( userId, User.class );
            sendAppUserActivatedEmail( applicationId, user );
            sendAdminNewAppUserActivatedNotificationEmail(applicationId, user);
            return ActivationState.ACTIVATED;
        }
        return ActivationState.UNKNOWN;
    }


    public void sendAppUserConfirmationEmail( UUID applicationId, User user ) throws Exception {
        String token = getConfirmationTokenForAppUser(applicationId, user.getUuid());
        OrganizationConfig orgConfig = getOrganizationConfigForApplication(applicationId);
        String confirmationPropertyUrl = orgConfig.getFullUrlTemplate(WorkflowUrl.USER_CONFIRMATION_URL);
        String confirmation_url =
                buildUserAppUrl( applicationId, confirmationPropertyUrl, user, token);

    /*
     * String confirmation_url = String.format(
     * properties.getProperty(PROPERTIES_USER_CONFIRMATION_URL),
     * applicationId.toString(), user.getUuid().toString()) + "?token=" + token;
     */
        sendAppUserEmail( user, "User Account Confirmation: " + user.getEmail(),
                emailMsg( hashMap( "confirmation_url", confirmation_url ), PROPERTIES_EMAIL_USER_CONFIRMATION ) );
    }


    protected String buildUserAppUrl(UUID applicationId, String url, User user, String token) throws Exception {
        ApplicationInfo ai = getApplicationInfo(applicationId);
        OrganizationInfo oi = getOrganizationForApplication(applicationId);
        return String.format( url, oi.getName(), StringUtils.stringOrSubstringAfterFirst( ai.getName(), '/' ),
                user.getUuid().toString() ) + "?token=" + token;
    }


    public void sendAdminRequestAppUserActivationEmail( UUID applicationId, User user ) throws Exception {
        String token = getActivationTokenForAppUser(applicationId, user.getUuid());
        OrganizationInfo organization = this.getOrganizationForApplication( applicationId );
        OrganizationConfig orgConfig = getOrganizationConfigByUuid(organization.getUuid());
        String activationPropertyUrl = orgConfig.getFullUrlTemplate(WorkflowUrl.USER_ACTIVATION_URL);
        String activation_url =
                buildUserAppUrl(applicationId, activationPropertyUrl, user, token);
    /*
     * String activation_url = String.format(
     * properties.getProperty(PROPERTIES_USER_ACTIVATION_URL),
     * applicationId.toString(), user.getUuid().toString()) + "?token=" + token;
     */
        this.sendOrganizationEmail( organization, "Request For User Account Activation " + user.getEmail(), emailMsg(
                hashMap( "organization_name", organization.getName() ).map( "activation_url", activation_url ),
                PROPERTIES_EMAIL_ADMIN_USER_ACTIVATION ) );
    }


    public void sendAdminNewAppUserActivatedNotificationEmail( UUID applicationId, User user ) throws Exception {
        if ( notifyAdminOfNewAppUsers( applicationId ) ) {
            OrganizationInfo organization = this.getOrganizationForApplication( applicationId );
            this.sendOrganizationEmail( organization, "New User Account Activated " + user.getEmail(),
                    emailMsg( hashMap( "organization_name", organization.getName() ),
                            PROPERTIES_EMAIL_ADMIN_USER_ACTIVATION ) );
        }
    }


    public void sendAppUserConfirmedAwaitingActivationEmail( UUID applicationId, User user ) throws Exception {
        sendAppUserEmail( user, "User Account Confirmed",
                properties.getProperty( PROPERTIES_EMAIL_USER_CONFIRMED_AWAITING_ACTIVATION ) );
    }


    public void sendAppUserActivatedEmail( UUID applicationId, User user ) throws Exception {
        sendAppUserEmail( user, "User Account Activated", properties.getProperty( PROPERTIES_EMAIL_USER_ACTIVATED ) );
    }


    @Override
    public void activateAppUser( UUID applicationId, UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( applicationId );
        em.setProperty(new SimpleEntityRef(User.ENTITY_TYPE, userId), "activated", true);
    }


    public void confirmAppUser( UUID applicationId, UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( applicationId );
        em.setProperty( new SimpleEntityRef( User.ENTITY_TYPE, userId ), "confirmed", true );
    }


    @Override
    public void setAppUserPassword( UUID applicationId, UUID userId, String newPassword ) throws Exception {
        if ( ( userId == null ) || ( newPassword == null ) ) {
            return;
        }

        EntityManager em = emf.getEntityManager( applicationId );
        User user = em.get(userId, User.class);

        writeUserPassword(applicationId, user,
            encryptionService.defaultEncryptedCredentials(newPassword, user.getUuid(), applicationId));
    }


    @Override
    public void setAppUserPassword( UUID applicationId, UUID userId, String oldPassword, String newPassword )
            throws Exception {
        if ( ( userId == null ) ) {
            throw new IllegalArgumentException( "userId is required" );
        }
        if ( ( oldPassword == null ) || ( newPassword == null ) ) {
            throw new IllegalArgumentException( "oldpassword and newpassword are both required" );
        }
        // TODO load the user, send the hashType down to maybeSaltPassword
        User user = emf.getEntityManager( applicationId ).get(userId, User.class);
        if ( !verify( applicationId, user.getUuid(), oldPassword ) ) {
            throw new IncorrectPasswordException( "Old password does not match" );
        }

        setAppUserPassword(applicationId, userId, newPassword);
    }


    @Override
    public void setAppUserCredentialsInfo( final UUID applicationId, final UUID userId,
                                           final CredentialsInfo credentialsInfo ) throws Exception {

        Preconditions.checkNotNull( applicationId, "applicationId is required" );
        Preconditions.checkNotNull( userId, "userId is required" );
        Preconditions.checkNotNull( credentialsInfo, "credentialsInfo is required" );

        final User user = emf.getEntityManager( applicationId ).get(userId, User.class);

        if(user == null){
            throw new EntityNotFoundException( "User with id " + userId + " cannot be found" );
        }

        writeUserPassword(applicationId, user, credentialsInfo);
    }


    @Override
    public CredentialsInfo getAppUserCredentialsInfo( final UUID applicationId, final UUID userId ) throws Exception {

        final User user = emf.getEntityManager( applicationId ).get( userId, User.class );

        if(user == null){
            throw new EntityNotFoundException("Could not find user with id " + userId + " in application" + applicationId  );
        }

        final CredentialsInfo ci = readUserPasswordCredentials( applicationId, userId, User.ENTITY_TYPE );

        if ( ci == null ) {
            throw new EntityNotFoundException("Could not find credentials for user with id " + userId + " in application" + applicationId );
        }

        return ci;
    }


    @Override
    public User verifyAppUserPasswordCredentials( UUID applicationId, String name, String password ) throws Exception {

        User user = findUserEntity( applicationId, name );
        if ( user == null ) {
            return null;
        }

        if ( verify( applicationId, user.getUuid(), password ) ) {
            if ( !user.activated() ) {
                throw new UnactivatedAppUserException();
            }
            if ( user.disabled() ) {
                throw new DisabledAppUserException();
            }
            return user;
        }

        return null;
    }


    public String getPasswordResetTokenForAppUser( UUID applicationId, UUID userId ) throws Exception {
        return getTokenForPrincipal( EMAIL, TOKEN_TYPE_PASSWORD_RESET, applicationId, APPLICATION_USER, userId, 0 );
    }


    public void sendAppUserEmail( User user, String subject, String html ) throws Exception {
        sendHtmlMail( properties, user.getDisplayEmailAddress(), properties.getProperty( PROPERTIES_MAILER_EMAIL ),
                subject, appendEmailFooter( html ) );
    }


    public String getActivationTokenForAppUser( UUID applicationId, UUID userId ) throws Exception {
        return getTokenForPrincipal( EMAIL, TOKEN_TYPE_ACTIVATION, applicationId, APPLICATION_USER, userId, 0 );
    }


    public String getConfirmationTokenForAppUser( UUID applicationId, UUID userId ) throws Exception {
        return getTokenForPrincipal( EMAIL, TOKEN_TYPE_CONFIRM, applicationId, APPLICATION_USER, userId, 0 );
    }


    @Override
    public void setAppUserPin( UUID applicationId, UUID userId, String newPin ) throws Exception {
        if ( ( userId == null ) || ( newPin == null ) ) {
            return;
        }

        writeUserPin( applicationId, new SimpleEntityRef( User.ENTITY_TYPE, userId ),
                encryptionService.plainTextCredentials( newPin, userId, applicationId ) );
    }


    @Override
    public void sendAppUserPin( UUID applicationId, UUID userId ) throws Exception {
        EntityManager em = emf.getEntityManager( applicationId );
        User user = em.get( userId, User.class );
        if ( user == null ) {
            return;
        }
        if ( user.getEmail() == null ) {
            return;
        }
        String pin = getCredentialsSecret( readUserPin( applicationId, userId, user.getType() ) );

        sendHtmlMail(properties, user.getDisplayEmailAddress(), properties.getProperty(PROPERTIES_MAILER_EMAIL),
            "Your app pin",
            appendEmailFooter(emailMsg(hashMap(USER_PIN, pin), PROPERTIES_EMAIL_USER_PIN_REQUEST)));
    }


    @Override
    public User verifyAppUserPinCredentials( UUID applicationId, String name, String pin ) throws Exception {

        User user = findUserEntity(applicationId, name);
        if ( user == null ) {
            return null;
        }
        if ( pin.equals( getCredentialsSecret( readUserPin( applicationId, user.getUuid(), user.getType() ) ) ) ) {
            return user;
        }
        return null;
    }


    @Override
    public void countAdminUserAction( UserInfo user, String action ) throws Exception {
        EntityManager em = emf.getEntityManager(smf.getManagementAppId());
        em.incrementAggregateCounters( user.getUuid(), null, null, "admin_logins", 1 );
    }


    /*
   * (non-Javadoc)
   *
   * @see
   * org.apache.usergrid.management.ManagementService#setOrganizationProps(java.util
   * .UUID, java.util.Map)
   */
    @Override
    public void setOrganizationProps( UUID orgId, Map<String, Object> props ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

        Group org = em.get( orgId, Group.class );

        if ( org == null ) {
            throw new EntityNotFoundException( String.format( "Could not find organization with id %s", orgId.toString() ) );
        }

        org.setProperties( props );

        em.update(org);
    }


    /*
   * (non-Javadoc)
   *
   * @see
   * org.apache.usergrid.management.ManagementService#getOrganizationProps(java.util
   * .UUID)
   */
    @Override
    public Group getOrganizationProps( UUID orgId ) throws Exception {
        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );

        return em.get( orgId, Group.class );
    }


    /** Persist the user's password credentials info */
    protected void writeUserPassword( UUID appId, EntityRef owner, CredentialsInfo creds ) throws Exception {
        writeCreds( appId, owner, creds, USER_PASSWORD );
    }


    /** read the user password credential's info */
    protected CredentialsInfo readUserPasswordCredentials( UUID appId, UUID ownerId, String ownerType ) throws Exception {
        return readCreds( appId, ownerId, ownerType, USER_PASSWORD );
    }


    /** Write the user's token */
    protected void writeUserToken( UUID appId, EntityRef owner, CredentialsInfo token ) throws Exception {
        writeCreds( appId, owner, token, USER_TOKEN );
    }


    /** Read the credentials info for the user's token */
    protected CredentialsInfo readUserToken( UUID appId, UUID ownerId, String ownerType ) throws Exception {
        return readCreds( appId, ownerId, ownerType, USER_TOKEN );
    }


    /** Write the mongo password */
    protected void writeUserMongoPassword( UUID appId, EntityRef owner, CredentialsInfo password ) throws Exception {
        writeCreds( appId, owner, password, USER_MONGO_PASSWORD );
    }


    /** Read the mongo password */
    protected CredentialsInfo readUserMongoPassword( UUID appId, UUID ownerId, String ownerType ) throws Exception {
        return readCreds( appId, ownerId, ownerType, USER_MONGO_PASSWORD );
    }


    /** Write the user's pin */
    protected void writeUserPin( UUID appId, EntityRef owner, CredentialsInfo pin ) throws Exception {
        writeCreds( appId, owner, pin, USER_PIN );
    }


    /** Read the user's pin */
    protected CredentialsInfo readUserPin( UUID appId, UUID ownerId, String ownerType ) throws Exception {
        return readCreds( appId, ownerId, ownerType, USER_PIN );
    }


    private void writeCreds( UUID appId, EntityRef owner, CredentialsInfo creds, String key ) throws Exception {
        EntityManager em = emf.getEntityManager( appId );
        em.addToDictionary( owner, DICTIONARY_CREDENTIALS, key, creds );
    }


    private CredentialsInfo readCreds( UUID appId, UUID ownerId, String ownerType, String key ) throws Exception {
        EntityManager em = emf.getEntityManager( appId );
        Entity owner = em.get( ownerId );
        return ( CredentialsInfo ) em.getDictionaryElementValue( owner, DICTIONARY_CREDENTIALS, key );
    }


    private Set<CredentialsInfo> readUserPasswordHistory( UUID appId, UUID ownerId ) throws Exception {
        EntityManager em = emf.getEntityManager( appId );
        Entity owner = em.get( new SimpleEntityRef("user", ownerId ));

        @SuppressWarnings("unchecked")
        Set<CredentialsInfo> credInfo =
                (Set<CredentialsInfo>)em.getDictionaryElementValue(owner, DICTIONARY_CREDENTIALS, USER_PASSWORD_HISTORY);

        return credInfo;
    }


    @Override
    public boolean newAdminUsersNeedSysAdminApproval() {
        return properties.newAdminUsersNeedSysAdminApproval();
    }


    @Override
    public boolean newAdminUsersRequireConfirmation() {
        return properties.newAdminUsersRequireConfirmation();
    }


    @Override
    public boolean newOrganizationsNeedSysAdminApproval() {
        return properties.newOrganizationsNeedSysAdminApproval();
    }


    private boolean areActivationChecksDisabled() {
        return !( newOrganizationsNeedSysAdminApproval() || properties.newOrganizationsRequireConfirmation()
                || newAdminUsersNeedSysAdminApproval() || newAdminUsersRequireConfirmation() );
    }


    private void sendHtmlMail( AccountCreationProps props, String to, String from, String subject, String html ) {
        mailUtils.sendHtmlMail( props.getMailProperties(), to, from, subject, html );
    }


    public AccountCreationProps getAccountCreationProps() {
        return properties;
    }


    private boolean verify( UUID applicationId, UUID userId, String password ) throws Exception {
        CredentialsInfo ci = readUserPasswordCredentials( applicationId, userId, User.ENTITY_TYPE );

        return (ci != null) && encryptionService.verify( password, ci, userId, applicationId );
    }


    /** @return the saltProvider */
    public SaltProvider getSaltProvider() {
        return saltProvider;
    }


    /** @param saltProvider the saltProvider to set */
    public void setSaltProvider( SaltProvider saltProvider ) {
        this.saltProvider = saltProvider;
    }


    @Override
    public Object registerAppWithAPM( OrganizationInfo orgInfo, ApplicationInfo appInfo ) throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Observable<Id> deleteAllEntities(final UUID applicationId,final int limit){
        if(applicationId.equals(CpNamingUtils.MANAGEMENT_APPLICATION_ID)){
            throw new IllegalArgumentException("Can't delete from management app");
        }

        return service.deleteAllEntities(CpNamingUtils.getApplicationScope(applicationId),limit);
    }

    private String getProperty(String key) {
        String obj = properties.getProperty(key);
        if(StringUtils.isEmpty(obj))
            return null;
        else
            return obj;
    }

    private boolean getBooleanProperty(String key) {
        String obj = getProperty(key);
        return !StringUtils.isEmpty(obj) && Boolean.parseBoolean(obj);
    }

    @Override
    public OrganizationConfig getOrganizationConfigDefaultsOnly() {
        return new OrganizationConfig(orgConfigProperties);
    }


    @Override
    public OrganizationConfig getOrganizationConfigByName( String organizationName ) throws Exception {

        if ( organizationName == null || organizationName.equals(CassandraService.MANAGEMENT_APPLICATION)) {
            return getOrganizationConfigDefaultsOnly();
        }

        EntityManager em = emf.getEntityManager(smf.getManagementAppId());
        EntityRef ref = em.getAlias( Group.ENTITY_TYPE, organizationName );
        return ref != null ? getOrganizationConfigByUuid(ref.getUuid()) : getOrganizationConfigDefaultsOnly();
    }


    @Override
    public OrganizationConfig getOrganizationConfigByUuid( UUID id ) throws Exception {

        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
        Entity entity = em.get( new SimpleEntityRef( Group.ENTITY_TYPE, id ) );
        if ( entity == null ) {
            return getOrganizationConfigDefaultsOnly();
        }
        Map<Object, Object> entityProperties = em.getDictionaryAsMap(entity, ORGANIZATION_CONFIG_DICTIONARY);
        return new OrganizationConfig( orgConfigProperties,
                (UUID)entity.getProperty(PROPERTY_UUID),
                (String)entity.getProperty(PROPERTY_PATH),
                entityProperties, false);
    }


    private OrganizationConfig getOrganizationConfigForUserInfo(UserInfo user) throws Exception {
        UUID userApp = user.getApplicationId();

        if (userApp == CpNamingUtils.MANAGEMENT_APPLICATION_ID) {
            Map<UUID, String> organizations = getOrganizationsForAdminUser(user.getUuid());
            if (organizations != null) {
                Iterator<UUID> iter = organizations.keySet().iterator();
                if (iter.hasNext()) {
                    return getOrganizationConfigByUuid(iter.next());
                }
            }
        } else {
            // if user is not an admin, use associated application
            return getOrganizationConfigForApplication(userApp);
        }

        // return default
        return getOrganizationConfigDefaultsOnly();
    }


    private String getOrganizationConfigPropertyForUserInfo(UserInfo user, String key) throws Exception {
        return getOrganizationConfigForUserInfo(user).getProperty(key);
    }


    private String getOrganizationConfigPropertyForApplication(UUID applicationId, String key) throws Exception {
        return getOrganizationConfigForApplication(applicationId).getProperty(key);
    }


    private String getOrganizationConfigPropertyByUuid(UUID organizationId, String key) throws Exception {
        return getOrganizationConfigByUuid(organizationId).getProperty(key);
    }


    @Override
    public OrganizationConfig getOrganizationConfigForApplication( UUID applicationInfoId ) throws Exception {

        // return from the cache. if the orgconfig cannot be loaded, defaults are loaded and cached
        return orgConfigByAppCache.get( applicationInfoId );
    }


    @Override
    public void updateOrganizationConfig( OrganizationConfig organizationConfig ) throws Exception {
        // get only the overrides
        Map<String, Object> orgConfigProperties = organizationConfig.getOrgConfigOverridesMap();
        if ( orgConfigProperties != null ) {
            EntityRef organizationEntity = new SimpleEntityRef( Group.ENTITY_TYPE, organizationConfig.getUuid() );
            EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
            for ( Map.Entry<String, Object> entry : orgConfigProperties.entrySet() ) {
                if ( "".equals( entry.getValue() ) ) {
                    em.removeFromDictionary( organizationEntity, ORGANIZATION_CONFIG_DICTIONARY, entry.getKey() );
                } else {
                    em.addToDictionary( organizationEntity, ORGANIZATION_CONFIG_DICTIONARY, entry.getKey(),
                            entry.getValue() );
                }
            }

            // evict cache for this key if it exists
            orgConfigByAppCache.invalidate( organizationConfig.getUuid() );

        }
    }


    private void invalidateManagementAppAuthCache() {
        ScopedCache scopedCache = cacheFactory.getScopedCache(
            new CacheScope( new SimpleId( CpNamingUtils.MANAGEMENT_APPLICATION_ID, "application" )));
        scopedCache.invalidate();
        localShiroCache.invalidateAll();
    }
}
