/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.vertical.engine.handlers; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.enonic.esl.util.ArrayUtil; import com.enonic.esl.xml.XMLTool; import com.enonic.vertical.engine.VerticalEngineLogger; import com.enonic.vertical.engine.XDG; import com.enonic.vertical.event.VerticalEventListener; 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.user.User; import com.enonic.cms.core.security.user.UserEntity; import com.enonic.cms.core.security.user.UserType; import com.enonic.cms.core.security.userstore.UserStoreKey; import com.enonic.cms.store.dao.GroupDao; @Component public final class GroupHandler extends BaseHandler implements VerticalEventListener { final static private String USER_TABLE = "tUser"; final static private String GROUP_TABLE = "tGroup"; final static private String GRPGRPMEM_TABLE = "tGrpGrpMembership"; final static private String GROUP_ALL_FIELDS = "grp_hkey, grp_sname, grp_dom_lkey, grp_ltype, grp_sdescription, grp_bisdeleted, grp_brestricted, grp_ssyncvalue"; final static private String GROUP_GET = "SELECT " + GROUP_ALL_FIELDS + " FROM " + GROUP_TABLE; final static private String GROUP_GET_BY_KEY = GROUP_GET + " WHERE grp_hKey = ? AND grp_bIsDeleted != 1 "; final static private String GRPGRPMEM_GET_MEMBERSHIPS = "SELECT * FROM " + GRPGRPMEM_TABLE + " LEFT JOIN " + GROUP_TABLE + " ON " + GROUP_TABLE + ".grp_hKey = " + GRPGRPMEM_TABLE + ".ggm_mbr_grp_hKey LEFT JOIN " + USER_TABLE + " ON " + GROUP_TABLE + ".grp_hKey = " + USER_TABLE + ".usr_grp_hKey " + " WHERE ggm_grp_hKey=?"; final static private String GRPGRPMEM_GET_MULTIPLE_MEMBERSHIPS = "SELECT * FROM " + GRPGRPMEM_TABLE + " LEFT JOIN " + GROUP_TABLE + " ON " + GROUP_TABLE + ".grp_hKey = " + GRPGRPMEM_TABLE + ".ggm_mbr_grp_hKey WHERE ggm_mbr_grp_hKey IN "; @Autowired private GroupDao groupDao; private String getAuthenticatedUsersGroupKey( final UserStoreKey userStoreKey ) { if ( userStoreKey == null ) { return null; } final GroupEntity entity = this.groupDao.findBuiltInAuthenticatedUsers( userStoreKey ); if ( entity == null ) { return null; } return entity.getGroupKey().toString(); } public Document getGroup( String groupKey ) { Document doc = XMLTool.createDocument( "groups" ); PreparedStatement preparedStmt = null; ResultSet resultSet = null; try { Connection con = getConnection(); preparedStmt = con.prepareStatement( GROUP_GET_BY_KEY ); preparedStmt.setString( 1, groupKey ); resultSet = preparedStmt.executeQuery(); groupResultSetToDom( con, doc.getDocumentElement(), resultSet ); } catch ( SQLException e ) { VerticalEngineLogger.error( "A database error occurred: %t", e ); } finally { close( resultSet ); close( preparedStmt ); } return doc; } private void groupResultSetToDom( Connection con, Element rootElement, ResultSet grpResultSet ) throws SQLException { Document doc = rootElement.getOwnerDocument(); PreparedStatement preparedStmt = con.prepareStatement( GRPGRPMEM_GET_MEMBERSHIPS ); try { int num = 0; while (grpResultSet.next()) { num++; Element groupElement = XMLTool.createElement( doc, rootElement, "group" ); // attribute: group key String gKey = grpResultSet.getString( "grp_hKey" ); groupElement.setAttribute( "key", String.valueOf( gKey ) ); // attribute: group type GroupType groupType = GroupType.get( grpResultSet.getInt( "grp_lType" ) ); if ( grpResultSet.wasNull() ) { if ( gKey.equals( getEnterpriseAdministratorGroupKey() ) ) { groupElement.setAttribute( "type", "0" ); } else if ( gKey.equals( getAnonymousGroupKey() ) ) { groupElement.setAttribute( "type", "7" ); } } else { groupElement.setAttribute( "type", groupType.toInteger().toString() ); } // attribute: restricted groupElement.setAttribute( "restricted", String.valueOf( grpResultSet.getBoolean( "grp_bRestricted" ) ) ); if ( groupType == GroupType.ENTERPRISE_ADMINS ) { groupElement.setAttribute( "scope", "0" ); } else if ( groupType == GroupType.USERSTORE_GROUP || groupType == GroupType.USERSTORE_ADMINS || groupType == GroupType.AUTHENTICATED_USERS || groupType == GroupType.ANONYMOUS ) { groupElement.setAttribute( "scope", "1" ); } else if ( groupType == GroupType.GLOBAL_GROUP || groupType == GroupType.ADMINS || groupType == GroupType.CONTRIBUTORS ) { groupElement.setAttribute( "scope", "2" ); } else { groupElement.setAttribute( "scope", "-1" ); } // element: group name XMLTool.createElement( doc, groupElement, "name", grpResultSet.getString( "grp_sName" ) ); // element: group description XMLTool.createElement( doc, groupElement, "description", grpResultSet.getString( "grp_sDescription" ) ); buildGroupMembersDOM( preparedStmt, groupElement, gKey ); } rootElement.setAttribute( "totalcount", String.valueOf( num ) ); } finally { // the outer try/finally-block makes sure we close the // PreparedStatement even if we encounter errors. close( preparedStmt ); } } private void buildGroupMembersDOM( PreparedStatement preparedStmt, Element groupElement, String gKey ) throws SQLException { Document doc = groupElement.getOwnerDocument(); ResultSet resultSet = null; try { preparedStmt.setString( 1, gKey ); resultSet = preparedStmt.executeQuery(); Element membersElement = XMLTool.createElement( doc, groupElement, "members" ); Element groupMembersElement = XMLTool.createElement( doc, membersElement, "groups" ); int membercount = 0; while ( resultSet.next() ) { Element memberGroupElement = XMLTool.createElement( doc, groupMembersElement, "group" ); memberGroupElement.setAttribute( "key", resultSet.getString( "grp_hKey" ) ); GroupType groupType = GroupType.get( resultSet.getInt( "grp_lType" ) ); memberGroupElement.setAttribute( "type", groupType.toInteger().toString() ); memberGroupElement.setAttribute( "restricted", String.valueOf( resultSet.getBoolean( "grp_dom_lKey" ) ) ); // sort is used as a prefix to the title int sort = 1; memberGroupElement.setAttribute( "name", "hey" ); memberGroupElement.setAttribute( "sort", String.valueOf( sort ) ); membercount++; } membersElement.setAttribute( "membercount", String.valueOf( membercount ) ); } finally { close( resultSet ); } } public String[] getAllGroupMembershipsForUser( User user ) { return getAllGroupMembershipsForUser( user.getKey().toString(), user.getType(), user.getUserGroupKey(), user.getUserStoreKey() ); } private String[] getAllGroupMembershipsForUser( String userKey, UserType userType, GroupKey userGroupKey, UserStoreKey userStoreKey ) { String[] groups; if ( userKey != null ) { if ( userType != UserType.ANONYMOUS && userType != UserType.ADMINISTRATOR ) { groups = new String[]{userGroupKey.toString(), getAuthenticatedUsersGroupKey( userStoreKey ), getAnonymousGroupKey()}; } else { groups = new String[]{getAnonymousGroupKey()}; } } else { groups = new String[]{getAnonymousGroupKey()}; } Set<String> excludeGroups = new HashSet<String>(); excludeGroups.addAll( Arrays.asList( groups ) ); try { Connection con = getConnection(); String[] addGroups = null; while ( addGroups == null || addGroups.length > 0 ) { addGroups = getGroupMemberships( con, groups, excludeGroups ); // extend group array String[] newGroups = new String[groups.length + addGroups.length]; System.arraycopy( groups, 0, newGroups, 0, groups.length ); // copy old groups System.arraycopy( addGroups, 0, newGroups, groups.length, addGroups.length ); // add new groups // add groups to the excluded set excludeGroups.addAll( Arrays.asList( addGroups ) ); groups = newGroups; } } catch ( SQLException e ) { VerticalEngineLogger.error( "A database error occurred: %t", e ); } return groups; } public String[] getGroupMembers( String[] groups, String[] excludeGroups ) { if ( groups == null || groups.length == 0 ) { return new String[0]; } StringBuffer sql = XDG.generateSelectSQL( db.tGrpGrpMembership, db.tGroup.grp_hKey, true, null ); XDG.appendJoinSQL( sql, db.tGrpGrpMembership.ggm_mbr_grp_hKey ); XDG.appendWhereInSQL( sql, db.tGrpGrpMembership.ggm_grp_hKey, groups ); String[] groupMembers = getCommonHandler().getStringArray( sql.toString(), null ); String[] filteredGroups = ArrayUtil.filter( groupMembers, excludeGroups ); if ( excludeGroups == null ) { excludeGroups = new String[0]; } String[] recursiveGroups = getGroupMembers( filteredGroups, ArrayUtil.concat( filteredGroups, excludeGroups, false ) ); return ArrayUtil.concat( filteredGroups, recursiveGroups, false ); } private String[] getGroupMemberships( Connection _con, String[] groups, Set<String> excludeGroups ) { PreparedStatement preparedStmt = null; ResultSet resultSet = null; ArrayList<String> newGroups = new ArrayList<String>(); Connection con = _con; try { if ( con == null ) { con = getConnection(); } StringBuffer sql = new StringBuffer( "(" ); int groupCount = 0; for ( int i = 0; i < groups.length; ++i ) { if ( i > 0 ) { sql.append( "," ); } sql.append( "'" ); sql.append( groups[i] ); sql.append( "'" ); ++groupCount; } sql.append( ")" ); // there is no point in going any further if there are no groups if ( groupCount > 0 ) { preparedStmt = con.prepareStatement( GRPGRPMEM_GET_MULTIPLE_MEMBERSHIPS + sql.toString() ); resultSet = preparedStmt.executeQuery(); while ( resultSet.next() ) { String groupKey = resultSet.getString( "ggm_grp_hKey" ); if ( ( excludeGroups == null || !excludeGroups.contains( groupKey ) ) && !newGroups.contains( groupKey ) ) { newGroups.add( groupKey ); } } } } catch ( SQLException e ) { VerticalEngineLogger.error( "A database error occurred: %t", e ); } finally { close( resultSet ); close( preparedStmt ); if ( _con == null ) { } } return newGroups.toArray( new String[newGroups.size()] ); } public String getAdminGroupKey() { final GroupEntity entity = this.groupDao.findBuiltInAdministrator(); return entity != null ? entity.getGroupKey().toString() : null; } private String getAnonymousGroupKey() { final GroupEntity entity = this.groupDao.findBuiltInAnonymous(); return entity != null ? entity.getGroupKey().toString() : null; } public String getEnterpriseAdministratorGroupKey() { final GroupEntity entity = this.groupDao.findBuiltInEnterpriseAdministrator(); return entity != null ? entity.getGroupKey().toString() : null; } public Set<UserEntity> getUserNames( String[] groupKeys ) { HashSet<UserEntity> foundUsers = new HashSet<UserEntity>(); HashSet<GroupEntity> groupsToCheck = new HashSet<GroupEntity>(); for ( String gKey : groupKeys ) { GroupEntity group = groupDao.find( gKey ); if ( group.isOfType( GroupType.USER, false ) ) { foundUsers.add( group.getUser() ); } else { groupsToCheck.addAll( group.getAllMembersRecursively() ); } } for ( GroupEntity group : groupsToCheck ) { if ( group.isOfType( GroupType.USER, false ) ) { foundUsers.add( group.getUser() ); } } return foundUsers; } }