/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.platform.plugin.action.mondrian.mapper;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import mondrian.olap.Util;
import mondrian.olap.Util.PropertyList;
import mondrian.rolap.RolapConnectionProperties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.olap4j.OlapConnection;
import org.olap4j.OlapException;
import org.pentaho.platform.api.engine.IConnectionUserRoleMapper;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.PentahoAccessControlException;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalog;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianSchema;
import org.pentaho.platform.plugin.action.olap.IOlapService;
import org.pentaho.platform.plugin.services.importexport.legacy.MondrianCatalogRepositoryHelper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
/**
* @author mbatchelor
*/
public abstract class MondrianAbstractPlatformUserRoleMapper implements IConnectionUserRoleMapper {
private static final Log log = LogFactory.getLog( MondrianAbstractPlatformUserRoleMapper.class );
public MondrianAbstractPlatformUserRoleMapper() {
}
/**
* Subclasses simply need to implement this one method to do the specific mapping desired.
*
* @param mondrianRoles
* Sorted list of roles defined in the catalog
* @param platformRoles
* Sorted list of the roles defined in the catalog
* @return
*/
protected abstract String[] mapRoles( String[] mondrianRoles, String[] platformRoles )
throws PentahoAccessControlException;
/**
* This method returns the role names as found in the Mondrian schema. The returned names must be ordered (sorted) or
* code down-stream will not work.
*
* @param userSession
* Users' session
* @param catalogName
* The name of the catalog
* @return Array of role names from the schema file
*/
protected String[] getMondrianRolesFromCatalog( IPentahoSession userSession, String context ) {
String[] rtn = null;
// Get the catalog service
IMondrianCatalogService catalogService = PentahoSystem.get( IMondrianCatalogService.class );
if ( catalogService != null ) {
// Get the catalog by name
MondrianCatalog catalog = catalogService.getCatalog( context, userSession );
if ( catalog != null ) {
// The roles are in the schema object
MondrianSchema schema = catalog.getSchema();
if ( schema != null ) {
// Ask the schema for the role names array
String[] roleNames = schema.getRoleNames();
if ( ( roleNames != null ) && ( roleNames.length > 0 ) ) {
// Return the roles from the schema
Arrays.sort( roleNames );
return roleNames;
}
}
}
}
// Check with the IOlapService and try to get a list of roles there.
IOlapService olapService = PentahoSystem.get( IOlapService.class );
if ( olapService != null ) {
MondrianCatalogRepositoryHelper helper =
new MondrianCatalogRepositoryHelper( PentahoSystem.get( IUnifiedRepository.class ) );
String serverName = null;
for ( String name : helper.getOlap4jServers() ) {
PropertyList props = Util.parseConnectString( helper.getOlap4jServerInfo( name ).URL );
if ( props.get( RolapConnectionProperties.Catalog.name(), "" ).equals( context ) ) {
serverName = name;
}
}
if ( serverName != null ) {
OlapConnection conn = null;
try {
// Use a null session for root access.
conn = olapService.getConnection( serverName, null );
List<String> roleList = conn.getAvailableRoleNames();
String[] roleArray = roleList.toArray( new String[roleList.size()] );
Arrays.sort( roleArray );
return roleArray;
} catch ( OlapException e ) {
log.error( "Failed to get a list of roles from olap connection " + context, e );
throw new RuntimeException( e );
} finally {
if ( conn != null ) {
try {
conn.close();
} catch ( SQLException e ) {
// OK to squash this one.
log.error( "Failed to get a list of roles from olap connection " + context, e );
}
}
}
}
}
// Sort the returned list of roles.
return rtn;
}
/**
* This method returns the users' roles as specified in the Spring Security authentication object. The role names
* returned must be sorted for other code downstream to work properly.
*
* @param session
* The users' session
* @return Users' roles as defined in the authentication object
*/
protected String[] getPlatformRolesFromSession( IPentahoSession session ) {
// Get the authorities
Collection<? extends GrantedAuthority> gAuths = (Collection) session.getAttribute( IPentahoSession.SESSION_ROLES );
if ( gAuths == null ) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
gAuths = authentication.getAuthorities();
Assert.state( authentication != null );
}
List<String> rtn = null;
if ( ( gAuths != null ) && ( gAuths.size() > 0 ) ) {
// Copy role names out of the Authentication
rtn = new ArrayList<String>();
for ( GrantedAuthority auth : gAuths ) {
rtn.add( auth.getAuthority() );
}
// Sort the returned list of roles
Collections.sort( rtn );
}
return rtn != null ? rtn.toArray( new String[]{} ) : null;
}
/*
* (non-Javadoc)
*
* @see org.pentaho.platform.api.engine.IConnectionUserRoleMapper#mapConnectionRoles(org.pentaho.platform.api.engine.
* IPentahoSession, java.lang.String)
*/
public String[] mapConnectionRoles( IPentahoSession userSession, String connectionContext )
throws PentahoAccessControlException {
// The connectionContextName for this mapper is the Mondrian Catalog.
String[] mondrianRoleNames = getMondrianRolesFromCatalog( userSession, connectionContext );
String[] platformRoleNames = getPlatformRolesFromSession( userSession );
String[] mappedResult = null;
if ( ( mondrianRoleNames != null ) && ( platformRoleNames != null ) && ( mondrianRoleNames.length > 0 )
&& ( platformRoleNames.length > 0 ) ) {
mappedResult = mapRoles( mondrianRoleNames, platformRoleNames );
}
return mappedResult;
}
/*
* (non-Javadoc)
*
* @see org.pentaho.platform.api.engine.IConnectionUserRoleMapper#mapConnectionUser(org.pentaho.platform.api.engine.
* IPentahoSession, java.lang.String)
*/
public Object mapConnectionUser( IPentahoSession userSession, String context ) throws PentahoAccessControlException {
throw new UnsupportedOperationException();
}
}