blob: 443864c55dfda6933b7812dca50568ae9565731d [file] [log] [blame]
/*
* 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.directory.fortress.core.impl;
import java.util.List;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.fortress.core.FinderException;
import org.apache.directory.fortress.core.GlobalErrIds;
import org.apache.directory.fortress.core.GlobalIds;
import org.apache.directory.fortress.core.RemoveException;
import org.apache.directory.fortress.core.SecurityException;
import org.apache.directory.fortress.core.model.AdminRole;
import org.apache.directory.fortress.core.util.ConstraintValidator;
import org.apache.directory.fortress.core.model.Graphable;
import org.apache.directory.fortress.core.model.OrgUnit;
import org.apache.directory.fortress.core.model.UserAdminRole;
import org.apache.directory.fortress.core.util.VUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Process module for the AdminRole entity. This class performs data validations and error mapping. It is typically called
* by internal Fortress delegated manager classes ({@link DelAdminMgrImpl}, {@link DelAccessMgrImpl},
* {@link DelReviewMgrImpl}, ...) and not intended for external non-Fortress clients. This class will accept,
* {@link org.apache.directory.fortress.core.model.AdminRole}, validate its contents and forward on to it's corresponding DAO class {@link AdminRoleDAO}.
* <p>
* Class will throw {@link SecurityException} to caller in the event of security policy, data constraint violation or system
* error internal to DAO object. This class will forward DAO exceptions ({@link org.apache.directory.fortress.core.FinderException},
* {@link org.apache.directory.fortress.core.CreateException},{@link org.apache.directory.fortress.core.UpdateException},{@link org.apache.directory.fortress.core.RemoveException}),
* or {@link org.apache.directory.fortress.core.ValidationException} as {@link SecurityException}s with appropriate
* error id from {@link GlobalErrIds}.
* <p>
* This class is thread safe.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
final class AdminRoleP
{
private static final String CLS_NM = AdminRoleP.class.getName();
private static final Logger LOG = LoggerFactory.getLogger( CLS_NM );
private AdminRoleDAO rDao = new AdminRoleDAO();
private OrgUnitP op = new OrgUnitP();
private static final ConstraintValidator constraintValidator = VUtil.getConstraintValidator();
/**
* Return a fully populated Admin Role entity for a given Admin Role name. If matching record not found a
* SecurityException will be thrown.
*
* @param adminRole contains full Admin Role name.
* @return AdminRole entity containing all attributes associated with Administrative Role in directory.
* @throws SecurityException in the event AdminRole not found or DAO search error.
*/
AdminRole read( AdminRole adminRole ) throws SecurityException
{
return rDao.getRole( adminRole );
}
/**
* Takes a search string that contains full or partial Admin Role name in directory.
*
* @param adminRole contains full or partial Admin role name.
* @return List of type Role containing fully populated matching Admin Role entities. If no records found this will be empty.
* @throws SecurityException in the event of DAO search error.
*/
List<AdminRole> search( AdminRole adminRole )
throws SecurityException
{
return rDao.findRoles( adminRole );
}
/**
* Takes a search string that contains full or partial Admin Role name in directory.
*
* @param adminRole contains full or partial Admin role name.
* @param limit specify the max number of records to return in result set.
* @return List of type String containing Admin Role name of all matching User entities. If no records found this will be empty.
* @throws SecurityException in the event of DAO search error.
*/
List<String> search( AdminRole adminRole, int limit )
throws SecurityException
{
return rDao.findRoles( adminRole, limit );
}
/**
* Return all AdminRoles that have a parent assignment. This used for hierarchical processing.
*
* @param contextId maps to sub-tree in DIT, e.g. ou=contextId, dc=example, dc=com.
* @return List of type AdminRole containing {@link AdminRole#name} and {@link AdminRole#parents} populated.
* @throws SecurityException in the event of DAO search error.
*/
List<Graphable> getAllDescendants( String contextId )
throws SecurityException
{
return rDao.getAllDescendants( contextId );
}
/**
* Adds a new Admin Role entity to directory. The Role entity input object will be validated to ensure that:
* role name is present, and reasonability checks on all of the other populated values.
*
* @param entity Admin Role entity contains data targeted for insertion.
* @return AdminRole entity copy of input + additional attributes (internalId) that were added by op.
* @throws SecurityException in the event of data validation or DAO system error.
*/
AdminRole add( AdminRole entity )
throws SecurityException
{
validate( entity );
return rDao.create( entity );
}
/**
* Updates existing AdminRole entity in directory. e.g., the AdminRole description and temporal constraints
* updated.
*
* @param entity Admin Role entity contains data targeted for updating.
* @return AdminRole entity contains fully populated updated entity.
* @throws SecurityException in the event of data validation or DAO system error.
*/
AdminRole update( AdminRole entity ) throws SecurityException
{
validate( entity );
AdminRole updateEntity = rDao.update( entity );
return read( updateEntity );
}
/**
* Removes parent role assignments from Role entity in directory.
* updated.
*
* @param entity Admin Role entity contains data targeted for updating.
* @throws SecurityException in the event of data validation or DAO system error.
*/
void deleteParent( AdminRole entity ) throws SecurityException
{
validate( entity );
rDao.deleteParent( entity );
}
/**
* This command assigns a user to an admin role.
* Successful completion of this op, the following occurs:
* <p>
* <ul>
* <li> User entity (resides in people container) has role assignment added to aux object class attached to actual user record.
* <li> AdminRole entity (resides in admin role container) has userId added as role occupant.
* <li> (optional) Temporal constraints may be associated with <code>ftUserAttrs</code> aux object class based on:
* <ul>
* <li> timeout - number (in minutes) of session inactivity time allowed.
* <li> beginDate - YYYYMMDD - determines date when role may be activated.
* <li> endDate - YYMMDD - indicates latest date role may be activated.
* <li> beginLockDate - YYYYMMDD - determines beginning of enforced inactive status
* <li> endLockDate - YYMMDD - determines end of enforced inactive status.
* <li> beginTime - HHMM - determines begin hour role may be activated in user's session.
* <li> endTime - HHMM - determines end hour role may be activated in user's session.*
* <li> dayMask - 1234567, 1 = Sunday, 2 = Monday, etc - specifies which day of week role may be activated.
* </ul>
* </ul>
*
* @param entity contains userId and admin role name and (optional) role temporal constraints.
* @param userDn contains the DN of user being assigned.
* @return AdminRole contains copy of input entity and additional data processed by request.
* @throws SecurityException in the event data error in user or role objects or system error.
*/
AdminRole assign( AdminRole entity, String userDn ) throws SecurityException
{
return rDao.assign( entity, userDn );
}
/**
* Add the User dn occupant attribute to the OrganizationalRole entity in ldap. This method is called by AdminMgrImpl
* when the User is being added.
*
* @param uRoles contains a collection of UserAdminRole being targeted for assignment.
* @param userDn contains the userId targeted for attribute addition.
* @param contextId maps to sub-tree in DIT, e.g. ou=contextId, dc=example, dc=com.
* @throws SecurityException in the event of DAO search error.
*/
void addOccupant( List<UserAdminRole> uRoles, String userDn, String contextId )
throws SecurityException
{
if ( CollectionUtils.isNotEmpty( uRoles ) )
{
for ( UserAdminRole uRole : uRoles )
{
AdminRole role = new AdminRole( uRole.getName() );
role.setContextId( contextId );
assign( role, userDn );
}
}
}
/**
* Remove the User dn occupant attribute from the OrganizationalRole entity in ldap. This method is called by AdminMgrImpl
* when the User is being deleted.
*
* @param userDn contains the userId targeted for attribute removal.
* @param contextId maps to sub-tree in DIT, e.g. ou=contextId, dc=example, dc=com.
* @throws SecurityException in the event of DAO search error.
*/
void removeOccupant( String userDn, String contextId )
throws SecurityException
{
List<String> list;
try
{
list = rDao.findAssignedRoles( userDn, contextId );
for ( String roleNm : list )
{
AdminRole role = new AdminRole( roleNm );
role.setContextId( contextId );
deassign( role, userDn );
}
}
catch ( FinderException fe )
{
String error = "removeOccupant userDn [" + userDn + "] caught FinderException=" + fe;
throw new SecurityException( GlobalErrIds.ARLE_REMOVE_OCCUPANT_FAILED, error, fe );
}
}
/**
* This method removes assigned admin role from user entity. Both user and admin role entities must exist and have role relationship
* before calling this method.
* Successful completion:
* del Role to User assignment in User data set
* AND
* User to Role assignment in Admin Role data set.
*
* @param entity contains userId and admin role name targeted for removal.
* @param userDn contains the userId targeted for attribute removal.
* @return AdminRole contains copy of input entity and additional data processed by request.
* @throws SecurityException - in the event data error in user or role objects or system error.
*/
AdminRole deassign( AdminRole entity, String userDn ) throws SecurityException
{
return rDao.deassign( entity, userDn );
}
/**
* This method performs a "hard" delete. It completely the Admin Role node from the ldap directory.
* Admin Role entity must exist in directory prior to making this call else exception will be thrown.
*
* @param entity Contains the name of the Admin Role targeted for deletion.
* @throws SecurityException in the event of data validation or DAO system error.
*/
void delete( AdminRole entity ) throws SecurityException
{
try
{
rDao.remove( entity );
}
catch ( RemoveException re )
{
String error = "delete name [" + entity.getName() + "] caught RemoveException=" + re;
LOG.error( error );
throw new SecurityException( GlobalErrIds.ARLE_DELETE_FAILED, error, re );
}
}
/**
* Method will perform simple validations to ensure the integrity of the Admin Role entity targeted for insertion
* or updating in directory. For example the Admin Role temporal constraints will be validated. Data reasonability
* checks will be performed on all non-null attributes. Validations will be performed on ARBAC constraints as well.
*
* @param entity contains data targeted for insertion or update.
* @throws SecurityException in the event of data validation error or DAO error on Org validation.
*/
private void validate( AdminRole entity )
throws SecurityException
{
VUtil.safeText( entity.getName(), GlobalIds.ROLE_LEN );
if ( StringUtils.isNotEmpty( entity.getBeginRange() ) && StringUtils.isNotEmpty( entity.getEndRange() ) )
{
VUtil.safeText( entity.getBeginRange(), GlobalIds.ROLE_LEN );
VUtil.safeText( entity.getEndRange(), GlobalIds.ROLE_LEN );
if ( entity.getBeginRange().equalsIgnoreCase( entity.getEndRange() )
&& ( !entity.isBeginInclusive() || !entity.isEndInclusive() ) )
{
String error = "validate invalid range detected for role name [" + entity.getName()
+ "] non inclusive endpoint for identical range [" + entity.getBeginRange() + "] begin inclusive ["
+ entity.isBeginInclusive() + "] end inclusive [" + entity.isEndInclusive() + "]";
LOG.warn( error );
throw new SecurityException( GlobalErrIds.ARLE_INVLD_RANGE_INCLUSIVE, error );
}
else if ( !RoleUtil.getInstance().isParent( entity.getBeginRange(), entity.getEndRange(), entity.getContextId() )
&& !entity.getBeginRange().equalsIgnoreCase( entity.getEndRange() ) )
{
String error = "validate invalid range detected for role name [" + entity.getName()
+ "] begin range [" + entity.getBeginRange() + "] end range [" + entity.getEndRange() + "]";
LOG.warn( error );
throw new SecurityException( GlobalErrIds.ARLE_INVLD_RANGE, error );
}
}
else if ( StringUtils.isEmpty( entity.getBeginRange() ) && StringUtils.isNotEmpty( entity.getEndRange() ) )
{
String error = "validate role name [" + entity.getName() + "] begin range value null or empty.";
LOG.warn( error );
throw new SecurityException( GlobalErrIds.ARLE_BEGIN_RANGE_NULL, error );
}
else if ( StringUtils.isNotEmpty( entity.getBeginRange() ) && StringUtils.isEmpty( entity.getEndRange() ) )
{
String error = "validate role name [" + entity.getName() + "] end range value null or empty.";
LOG.warn( error );
throw new SecurityException( GlobalErrIds.ARLE_END_RANGE_NULL, error );
}
if ( StringUtils.isNotEmpty( entity.getDescription() ) )
{
VUtil.description( entity.getDescription() );
}
if ( entity.getTimeout() >= 0 )
{
constraintValidator.timeout( entity.getTimeout() );
}
if ( StringUtils.isNotEmpty( entity.getBeginTime() ) )
{
constraintValidator.beginTime( entity.getBeginTime() );
}
if ( StringUtils.isNotEmpty( entity.getEndTime() ) )
{
constraintValidator.endTime( entity.getEndTime() );
}
if ( StringUtils.isNotEmpty( entity.getBeginDate() ) )
{
constraintValidator.beginDate( entity.getBeginDate() );
}
if ( StringUtils.isNotEmpty( entity.getEndDate() ) )
{
constraintValidator.endDate( entity.getEndDate() );
}
if ( StringUtils.isNotEmpty( entity.getDayMask() ) )
{
constraintValidator.dayMask( entity.getDayMask() );
}
if ( StringUtils.isNotEmpty( entity.getBeginLockDate() ) )
{
constraintValidator.beginDate( entity.getBeginDate() );
}
if ( StringUtils.isNotEmpty( entity.getEndLockDate() ) )
{
constraintValidator.endDate( entity.getEndLockDate() );
}
if ( CollectionUtils.isNotEmpty( entity.getOsUSet() ) )
{
validateOrgs( entity.getOsUSet(), OrgUnit.Type.USER, entity.getContextId() );
}
if ( CollectionUtils.isNotEmpty( entity.getOsPSet() ) )
{
validateOrgs( entity.getOsPSet(), OrgUnit.Type.PERM, entity.getContextId() );
}
}
/**
* Called by validate()
*
* @param orgs
* @param contextId
* @throws SecurityException
*/
private void validateOrgs( Set<String> orgs, OrgUnit.Type type, String contextId ) throws SecurityException
{
for ( String ou : orgs )
{
OrgUnit inOe = new OrgUnit( ou );
inOe.setType( type );
inOe.setContextId( contextId );
op.read( inOe );
}
}
}