/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.security.user; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang.builder.HashCodeBuilder; import org.joda.time.DateTime; import com.google.common.collect.Maps; import com.enonic.cms.core.security.group.GroupEntity; import com.enonic.cms.core.security.group.GroupKey; import com.enonic.cms.core.security.group.GroupType; import com.enonic.cms.core.security.userstore.UserStoreEntity; import com.enonic.cms.core.security.userstore.UserStoreKey; import com.enonic.cms.api.plugin.ext.userstore.UserField; import com.enonic.cms.api.plugin.ext.userstore.UserFieldType; import com.enonic.cms.api.plugin.ext.userstore.UserFields; import com.enonic.cms.core.user.field.UserFieldTransformer; public class UserEntity implements User, Serializable { private UserKey key; private String name; private String displayName; private Integer deleted; private UserType type; private DateTime timestamp; private String syncValue; private String email; private UserStoreEntity userStore; private GroupEntity userGroup; private byte[] photo; private String password; private Map<String, String> fieldMap = new HashMap<String, String>(); private transient UserFields userFields = null; private transient QualifiedUsername qualifiedName; private transient List<GroupKey> allMembershipsGroupKeys; public UserEntity() { // Default constructor used by Hibernate. } public UserEntity( UserEntity source ) { this(); this.key = source.getKey(); this.name = source.getName(); this.displayName = source.getDisplayName(); this.email = source.getEmail(); this.deleted = source.getDeleted(); this.type = source.getType(); this.timestamp = source.getTimestamp(); this.syncValue = source.getSync(); this.email = source.getEmail(); this.userStore = source.getUserStore() != null ? new UserStoreEntity( source.getUserStore() ) : null; this.userGroup = source.getUserGroup(); this.photo = source.getPhoto(); this.password = source.getPassword(); this.fieldMap = source.getFieldMap() != null ? Maps.newHashMap( source.getFieldMap() ) : null; } public UserKey getKey() { return key; } public String getName() { return name; } public String getDisplayName() { return displayName; } public String getEmail() { return this.email; } public Integer getDeleted() { return deleted; } public boolean isDeleted() { return deleted != 0; } public UserType getType() { return type; } public boolean isAnonymous() { return getType().isAnonymous(); } /** * @return true if user is the hard coded admin super user. */ public boolean isRoot() { return getName().equals( ROOT_UID ); } public boolean isEnterpriseAdmin() { if ( isRoot() ) { return true; } if ( isAnonymous() ) { return false; } if ( getUserGroup() == null ) { return false; } return getUserGroup().isOfType( GroupType.ENTERPRISE_ADMINS, true ); } public static boolean isBuiltInUser( String uid ) { return uid.equalsIgnoreCase( ROOT_UID ) || uid.equalsIgnoreCase( ANONYMOUS_UID ); } public boolean isBuiltIn() { if ( getType().isBuiltIn() ) { return true; } return getUserGroup() != null && getUserGroup().isBuiltIn(); } public DateTime getTimestamp() { return timestamp; } public String getSync() { return syncValue; } public UserStoreEntity getUserStore() { return userStore; } public UserStoreKey getUserStoreKey() { return getUserStore() != null ? getUserStore().getKey() : null; } public void setKey( UserKey key ) { this.key = key; } public void setName( String value ) { this.name = value; // invalidate qualifiedName = null; } public void setDisplayName( final String value ) { displayName = value; } public void setDeleted( int deleted ) { this.deleted = deleted; } public void setDeleted( boolean value ) { this.deleted = value ? 1 : 0; } public void setType( UserType value ) { type = value; } public void setTimestamp( DateTime value ) { this.timestamp = value; } public void setSyncValue( String value ) { this.syncValue = value; } public void setEmail( String value ) { this.email = value; } public void setUserStore( UserStoreEntity value ) { this.userStore = value; // invalidate qualifiedName = null; } public void setUserGroup( GroupEntity value ) { this.userGroup = value; } public GroupKey getUserGroupKey() { return getUserGroup() != null ? getUserGroup().getGroupKey() : null; } public GroupEntity getUserGroup() { return userGroup; } public QualifiedUsername getQualifiedName() { if ( qualifiedName == null ) { String uid = getName(); if ( "anonymous".equals( uid ) || "admin".equals( uid ) ) { qualifiedName = new QualifiedUsername( uid ); } else if ( userStore != null ) { qualifiedName = new QualifiedUsername( userStore.getName(), uid ); } } return qualifiedName; } /** * @return The distinct set of all group keys (recursively) of this users memberships, including the user group key. */ public List<GroupKey> getAllMembershipsGroupKeys() { if ( allMembershipsGroupKeys == null ) { allMembershipsGroupKeys = new ArrayList<GroupKey>(); GroupEntity userGroup = getUserGroup(); allMembershipsGroupKeys.add( userGroup.getGroupKey() ); allMembershipsGroupKeys.addAll( userGroup.getAllMembershipsGroupKeys() ); } return allMembershipsGroupKeys; } /** * @return The distinct set of all groups, including recursively fetched subgroups of this users memberships. */ public Set<GroupEntity> getAllMembershipsGroups() { if ( getUserGroup() != null ) { return getUserGroup().getAllMemberships(); } else { return new HashSet<GroupEntity>(); } } public boolean isMemberOf( GroupEntity group, boolean recursively ) { final GroupEntity userGroup = getUserGroup(); if ( userGroup == null ) { return false; } return group.equals( userGroup ) || userGroup.isMemberOf( group, recursively ); } public boolean equals( Object o ) { if ( this == o ) { return true; } if ( !( o instanceof UserEntity ) ) { return false; } UserEntity that = (UserEntity) o; return getKey().equals( that.getKey() ); } public int hashCode() { final int initialNonZeroOddNumber = 273; final int multiplierNonZeroOddNumber = 637; return new HashCodeBuilder( initialNonZeroOddNumber, multiplierNonZeroOddNumber ).append( getKey() ).toHashCode(); } public String getPassword() { return this.password; } public void encodePassword( String password ) { if ( password != null ) { this.password = DigestUtils.shaHex( password ); } else { this.password = null; } } public boolean verifyPassword( String password ) { if ( password == null ) { return this.password == null; } return DigestUtils.shaHex( password ).equals( this.password ); } public String getSelectedLanguageCode() { return null; } public void setSelectedLanguageCode( String languageCode ) { } public boolean hasUserGroup() { return getUserGroup() != null; } public Set<GroupEntity> getAllMemberships() { return getAllMembershipsGroups(); } public Set<GroupEntity> getDirectMemberships() { if ( !hasUserGroup() ) { return new HashSet<GroupEntity>(); } return getUserGroup().getMemberships( false ); } void setFieldMap( Map<String, String> fieldMap ) { this.fieldMap = fieldMap; } public Map<String, String> getFieldMap() { return fieldMap; } public UserFields getUserFields() { return doGetUserFields(); } private UserFields doGetUserFields() { if ( this.userFields == null ) { final UserFieldTransformer fieldTransformer = new UserFieldTransformer(); userFields = fieldTransformer.fromStoreableMap( this.fieldMap ); fieldTransformer.updatePhoto( userFields, this.photo ); } return this.userFields; } /** * @return true if changes where made. */ public boolean overwriteUserFields( final UserFields userFields ) { final Map<String, String> newFieldMap = new UserFieldTransformer().toStoreableMap( userFields ); removeFieldsWithNullValueWhenFieldDoesNotExist( newFieldMap ); final Map<String, String> oldFieldMap = Maps.newHashMap( this.fieldMap ); this.fieldMap.putAll( newFieldMap ); final UserField photoField = userFields.getField( UserFieldType.PHOTO ); this.photo = photoField != null ? (byte[]) photoField.getValue() : null; // invalidate this.userFields = null; return !oldFieldMap.equals( fieldMap ); } /** * Replaces user fiels with given and returns true if it changed from previous user fields. */ public boolean setUserFields( final UserFields userFields ) { final Map<String, String> newFieldMap = new UserFieldTransformer().toStoreableMap( userFields ); removeFieldsWithNullValueWhenFieldDoesNotExist( newFieldMap ); final Map<String, String> oldFieldMap = Maps.newHashMap( this.fieldMap ); this.fieldMap.clear(); fieldMap.putAll( newFieldMap ); final UserField photoField = userFields.getField( UserFieldType.PHOTO ); this.photo = photoField != null ? (byte[]) photoField.getValue() : null; // invalidate this.userFields = null; return !oldFieldMap.equals( fieldMap ); } public boolean isInRemoteUserStore() { return !isBuiltIn() && getUserStore() != null && getUserStore().isRemote(); } public byte[] getPhoto() { return photo; } public boolean hasPhoto() { return photo != null; } public void setPhoto( byte[] photo ) { this.photo = photo; } private void removeFieldsWithNullValueWhenFieldDoesNotExist( final Map<String, String> mapToRemoveFrom ) { final List<String> fieldsToRemove = new ArrayList<String>(); for ( Map.Entry<String, String> entryToPossibleRemoveIfValueIsNull : mapToRemoveFrom.entrySet() ) { if ( entryToPossibleRemoveIfValueIsNull.getValue() == null && !this.fieldMap.containsKey( entryToPossibleRemoveIfValueIsNull.getKey() ) ) { fieldsToRemove.add( entryToPossibleRemoveIfValueIsNull.getKey() ); } } for ( String fieldToRemove : fieldsToRemove ) { mapToRemoveFrom.remove( fieldToRemove ); } } }