/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.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 General Public License for more details.
*
*
* Copyright 2006 - 2013 Pentaho Corporation. All rights reserved.
*/
package org.pentaho.platform.security.policy.rolebased;
import org.pentaho.platform.api.engine.IAuthorizationAction;
import org.pentaho.platform.api.engine.security.userroledao.NotFoundException;
import org.pentaho.platform.api.mt.ITenant;
import org.pentaho.platform.api.mt.ITenantedPrincipleNameResolver;
import org.pentaho.platform.engine.core.system.TenantUtils;
import org.pentaho.platform.repository2.unified.jcr.JcrTenantUtils;
import org.springframework.extensions.jcr.JcrCallback;
import org.springframework.extensions.jcr.JcrTemplate;
import org.springframework.util.Assert;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.io.IOException;
import java.util.*;
/**
* An {@link IRoleAuthorizationPolicyRoleBindingDao} implementation that uses JCR. Storage is done using nodes and
* properties, not XML. Storage looks like this:
*
* <pre>
* {@code
* - acme
* - .authz
* - roleBased
* - runtimeRoles
* - runtimeRole1
* - logicalRole1,logicalRole2 (multi-valued property)
* - runtimeRole2
* - logicalRole2 (multi-valued property)
* }
* </pre>
*
* <p>
* Note: All multi-valued properties are ordered.
* </p>
*
* <p>
* Note: This code runs as the repository superuser. Ideally this would run as the tenant admin but such a named
* user doesn't exist for us to run as. Now that the repo uses IAuthorizationPolicy for access control, this code
* MUST continue to run as the repository superuser. This is one reason not to implement this on top of PUR.
* </p>
*
* @author mlowery
*/
public class JcrRoleAuthorizationPolicyRoleBindingDao extends AbstractJcrBackedRoleBindingDao {
// ~ Static fields/initializers
// ======================================================================================
// ~ Instance fields
// =================================================================================================
private JcrTemplate jcrTemplate;
// ~ Constructors
// ====================================================================================================
public JcrRoleAuthorizationPolicyRoleBindingDao( final JcrTemplate jcrTemplate, final Map<String, List<IAuthorizationAction>> immutableRoleBindings,
final Map<String, List<String>> bootstrapRoleBindings, final String superAdminRoleName,
final ITenantedPrincipleNameResolver tenantedRoleNameUtils, final List<IAuthorizationAction> authorizationActions ) {
super(immutableRoleBindings, bootstrapRoleBindings, superAdminRoleName, tenantedRoleNameUtils,
authorizationActions );
Assert.notNull( jcrTemplate );
this.jcrTemplate = jcrTemplate;
}
// ~ Methods
// =========================================================================================================
/**
* {@inheritDoc}
*/
@Override
public RoleBindingStruct getRoleBindingStruct( final String locale ) {
return (RoleBindingStruct) jcrTemplate.execute( new JcrCallback() {
@Override
public Object doInJcr( final Session session ) throws RepositoryException, IOException {
return getRoleBindingStruct( session, null, locale );
}
} );
}
@Override
public RoleBindingStruct getRoleBindingStruct( final ITenant tenant, final String locale ) {
if ( ( tenant != null ) && !TenantUtils.isAccessibleTenant( tenant ) ) {
return new RoleBindingStruct( new HashMap<String, String>(), new HashMap<String, List<String>>(), new HashSet<String>() );
}
return (RoleBindingStruct) jcrTemplate.execute( new JcrCallback() {
@Override
public Object doInJcr( final Session session ) throws RepositoryException, IOException {
return getRoleBindingStruct( session, tenant, locale );
}
} );
}
/**
* {@inheritDoc}
*/
@Override
public void setRoleBindings( final String runtimeRoleName, final List<String> logicalRoleNames ) {
setRoleBindings( (ITenant) null, runtimeRoleName, logicalRoleNames );
}
@Override
public void setRoleBindings( final ITenant tenant, final String runtimeRoleName,
final List<String> logicalRoleNames ) {
ITenant tempTenant = tenant;
if ( tenant == null ) {
tempTenant = JcrTenantUtils.getTenant( runtimeRoleName, false );
}
if ( !TenantUtils.isAccessibleTenant( tempTenant ) ) {
throw new NotFoundException( "Tenant " + tenant.getId() + " not found" );
}
Assert.notNull( logicalRoleNames );
jcrTemplate.execute( new JcrCallback() {
@Override
public Object doInJcr( final Session session ) throws RepositoryException, IOException {
setRoleBindings( session, tenant, runtimeRoleName, logicalRoleNames );
return null;
}
} );
}
/**
* {@inheritDoc}
*/
@Override
@SuppressWarnings( "unchecked" )
public List<String> getBoundLogicalRoleNames( final List<String> runtimeRoleNames ) {
// what runtimeRoleNames are in the cache; we don't need to fetch them
return (List<String>) jcrTemplate.execute( new JcrCallback() {
@Override
public Object doInJcr( final Session session ) throws RepositoryException, IOException {
return getBoundLogicalRoleNames( session, runtimeRoleNames );
}
} );
}
@Override
public List<String> getBoundLogicalRoleNames( final ITenant tenant, final List<String> runtimeRoleNames ) {
if ( ( tenant != null ) && !TenantUtils.isAccessibleTenant( tenant ) ) {
return new ArrayList<String>();
}
// what runtimeRoleNames are in the cache; we don't need to fetch them
return (List<String>) jcrTemplate.execute( new JcrCallback() {
@Override
public Object doInJcr( final Session session ) throws RepositoryException, IOException {
return getBoundLogicalRoleNames( session, tenant, runtimeRoleNames );
}
} );
}
}