| /* |
| * 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.Optional; |
| 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.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; |
| import static org.apache.usergrid.management.OrganizationConfigProps.*; |
| |
| |
| 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; |
| |
| |
| |
| /** 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())); |
| |
| 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)); |
| } |
| |
| |
| @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 ); |
| } |
| |
| ScopedCache scopedCache = cacheFactory.getScopedCache( |
| new CacheScope( new SimpleId( CpNamingUtils.MANAGEMENT_APPLICATION_ID, "application" ))); |
| scopedCache.invalidate(); |
| localShiroCache.invalidateAll(); |
| |
| 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 ); |
| } |
| |
| ScopedCache scopedCache = cacheFactory.getScopedCache( |
| new CacheScope( new SimpleId( CpNamingUtils.MANAGEMENT_APPLICATION_ID, "application" ))); |
| scopedCache.invalidate(); |
| localShiroCache.invalidateAll(); |
| |
| 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 ); |
| } |
| |
| |
| @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 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); |
| |
| } |
| }} |
| ); |
| |
| } |