You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by sm...@apache.org on 2014/10/22 17:44:34 UTC
[15/51] [partial] Rename packages from org.openldap.fortress to
org.apache.directory.fortress.core. Change default suffix to org.apache.
Switch default ldap api from unbound to apache ldap.
http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java
new file mode 100755
index 0000000..6aa4900
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/RoleDAO.java
@@ -0,0 +1,657 @@
+/*
+ * 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.rbac.dao.apache;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.LdapConnection;
+
+import org.apache.directory.fortress.core.CreateException;
+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.ObjectFactory;
+import org.apache.directory.fortress.core.RemoveException;
+import org.apache.directory.fortress.core.UpdateException;
+import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider;
+import org.apache.directory.fortress.core.rbac.Graphable;
+import org.apache.directory.fortress.core.rbac.Role;
+import org.apache.directory.fortress.core.rbac.RoleUtil;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+import org.apache.directory.fortress.core.util.time.CUtil;
+
+
+/**
+ * This class perform data access for Fortress Role entity.
+ * <p/>
+ * The Fortress Role entity is a composite of the following other Fortress structural and aux object classes:
+ * <h4>1. ftRls Structural objectclass is used to store the Role information like name and temporal constraint attributes</h4>
+ * <ul>
+ * <li> ------------------------------------------
+ * <li> <code>objectclass ( 1.3.6.1.4.1.38088.2.1</code>
+ * <li> <code>NAME 'ftRls'</code>
+ * <li> <code>DESC 'Fortress Role Object Class'</code>
+ * <li> <code>SUP organizationalrole</code>
+ * <li> <code>STRUCTURAL</code>
+ * <li> <code>MUST ( ftId $ ftRoleName )</code>
+ * <li> <code>MAY ( description $ ftCstr ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <h4>2. ftProperties AUXILIARY Object Class is used to store client specific name/value pairs on target entity</h4>
+ * <code># This aux object class can be used to store custom attributes.</code><br />
+ * <code># The properties collections consist of name/value pairs and are not constrainted by Fortress.</code><br />
+ * <ul>
+ * <li> ------------------------------------------
+ * <li> <code>objectclass ( 1.3.6.1.4.1.38088.3.2</code>
+ * <li> <code>NAME 'ftProperties'</code>
+ * <li> <code>DESC 'Fortress Properties AUX Object Class'</code>
+ * <li> <code>AUXILIARY</code>
+ * <li> <code>MAY ( ftProps ) ) </code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <h4>3. ftMods AUXILIARY Object Class is used to store Fortress audit variables on target entity</h4>
+ * <ul>
+ * <li> <code>objectclass ( 1.3.6.1.4.1.38088.3.4</code>
+ * <li> <code>NAME 'ftMods'</code>
+ * <li> <code>DESC 'Fortress Modifiers AUX Object Class'</code>
+ * <li> <code>AUXILIARY</code>
+ * <li> <code>MAY (</code>
+ * <li> <code>ftModifier $</code>
+ * <li> <code>ftModCode $</code>
+ * <li> <code>ftModId ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <p/>
+ * This class is thread safe.
+ *
+ * @author Kevin McKinney
+ */
+public final class RoleDAO extends ApacheDsDataProvider implements org.apache.directory.fortress.core.rbac.dao.RoleDAO
+{
+ /*
+ * *************************************************************************
+ * ** OpenAccessMgr ROLE STATICS
+ * ************************************************************************
+ */
+ private static final String ROLE_OCCUPANT = "roleOccupant";
+ private static final String ROLE_NM = "ftRoleName";
+
+ private static final String[] ROLE_NM_ATR =
+ {
+ ROLE_NM
+ };
+
+ private static final String[] ROLE_ATRS =
+ {
+ GlobalIds.FT_IID, ROLE_NM, GlobalIds.DESC, GlobalIds.CONSTRAINT, ROLE_OCCUPANT, GlobalIds.PARENT_NODES
+ };
+
+
+ /**
+ * @param entity
+ * @return
+ * @throws CreateException
+ */
+ public final Role create( Role entity ) throws CreateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+
+ try
+ {
+ Entry entry = new DefaultEntry( dn );
+ entry.add( GlobalIds.OBJECT_CLASS, GlobalIds.ROLE_OBJ_CLASS );
+ entity.setId();
+ entry.add( GlobalIds.FT_IID, entity.getId() );
+ entry.add( ROLE_NM, entity.getName() );
+
+ // description field is optional on this object class:
+ if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+ {
+ entry.add( GlobalIds.DESC, entity.getDescription() );
+ }
+
+ // CN attribute is required for this object class:
+ entry.add( GlobalIds.CN, entity.getName() );
+ entry.add( GlobalIds.CONSTRAINT, CUtil.setConstraint( entity ) );
+
+ // These multi-valued attributes are optional. The utility function will return quietly if items are not loaded into collection:
+ loadAttrs( entity.getParents(), entry, GlobalIds.PARENT_NODES );
+
+ ld = getAdminConnection();
+ add( ld, entry, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "create role [" + entity.getName() + "] caught LdapException=" + e.getMessage();
+ throw new CreateException( GlobalErrIds.ROLE_ADD_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return entity;
+ }
+
+
+ /**
+ * @param entity
+ * @return
+ * @throws org.apache.directory.fortress.core.UpdateException
+ *
+ */
+ public final Role update( Role entity ) throws UpdateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+
+ try
+ {
+ List<Modification> mods = new ArrayList<Modification>();
+
+ if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+ {
+ mods.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+ GlobalIds.DESC, entity.getDescription() ) );
+ }
+
+ if ( VUtil.isNotNullOrEmpty( entity.getOccupants() ) )
+ {
+ for ( String name : entity.getOccupants() )
+ {
+ mods.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+ ROLE_OCCUPANT, entity.getOccupants().toArray( new String[]
+ {} ) ) );
+ }
+ }
+
+ if ( entity.isTemporalSet() )
+ {
+ String szRawData = CUtil.setConstraint( entity );
+
+ if ( VUtil.isNotNullOrEmpty( szRawData ) )
+ {
+ mods.add( new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE,
+ GlobalIds.CONSTRAINT, szRawData ) );
+ }
+ }
+
+ loadAttrs( entity.getParents(), mods, GlobalIds.PARENT_NODES );
+
+ if ( mods.size() > 0 )
+ {
+ ld = getAdminConnection();
+ modify( ld, dn, mods, entity );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "update name [" + entity.getName() + "] caught LdapException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.ROLE_UPDATE_FAILED, error, e );
+ }
+ catch ( Exception e )
+ {
+ String error = "update name [" + entity.getName() + "] caught LdapException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.ROLE_UPDATE_FAILED, error, e );
+ }
+ finally
+ {
+ try
+ {
+ closeAdminConnection( ld );
+ }
+ catch ( Exception e )
+ {
+ String error = "update name [" + entity.getName() + "] caught LdapException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.ROLE_UPDATE_FAILED, error, e );
+ }
+ }
+
+ return entity;
+ }
+
+
+ /**
+ *
+ * @param entity
+ * @throws UpdateException
+ */
+ public final void deleteParent( Role entity ) throws UpdateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+ try
+ {
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE,
+ GlobalIds.PARENT_NODES ) );
+ ld = getAdminConnection();
+ modify( ld, dn, mods, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "deleteParent name [" + entity.getName() + "] caught LdapException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.ROLE_REMOVE_PARENT_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ }
+
+
+ /**
+ * @param entity
+ * @param userDn
+ * @return
+ * @throws org.apache.directory.fortress.core.UpdateException
+ *
+ */
+ public final Role assign( Role entity, String userDn ) throws UpdateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+
+ try
+ {
+ //ld = getAdminConnection();
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add( new DefaultModification( ModificationOperation.ADD_ATTRIBUTE, ROLE_OCCUPANT, userDn ) );
+ ld = getAdminConnection();
+ modify( ld, dn, mods, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "assign role name [" + entity.getName() + "] user dn [" + userDn + "] caught LdapException="
+ + e.getMessage();
+ throw new UpdateException( GlobalErrIds.ROLE_USER_ASSIGN_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return entity;
+ }
+
+
+ /**
+ * @param entity
+ * @param userDn
+ * @return
+ * @throws org.apache.directory.fortress.core.UpdateException
+ *
+ */
+ public final Role deassign( Role entity, String userDn ) throws UpdateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+ try
+ {
+ List<Modification> mods = new ArrayList<Modification>();
+ mods.add( new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, ROLE_OCCUPANT, userDn ) );
+ ld = getAdminConnection();
+ modify( ld, dn, mods, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "deassign role name [" + entity.getName() + "] user dn [" + userDn
+ + "] caught LdapException=" + e.getMessage();
+ throw new UpdateException( GlobalErrIds.ROLE_USER_DEASSIGN_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return entity;
+ }
+
+
+ /**
+ * @param role
+ * @throws RemoveException
+ */
+ public final void remove( Role role )
+ throws RemoveException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( role.getName(), role.getContextId() );
+
+ try
+ {
+ ld = getAdminConnection();
+ delete( ld, dn, role );
+ }
+ catch ( LdapException e )
+ {
+ String error = "remove role name=" + role.getName() + " LdapException=" + e.getMessage();
+ throw new RemoveException( GlobalErrIds.ROLE_DELETE_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ }
+
+
+ /**
+ * @param role
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ *
+ */
+ public final Role getRole( Role role )
+ throws FinderException
+ {
+ Role entity = null;
+ LdapConnection ld = null;
+ String dn = getDn( role.getName(), role.getContextId() );
+
+ try
+ {
+ ld = getAdminConnection();
+ Entry findEntry = read( ld, dn, ROLE_ATRS );
+ if(findEntry != null)
+ {
+ entity = unloadLdapEntry( findEntry, 0, role.getContextId() );
+ }
+ if ( entity == null )
+ {
+ String warning = "getRole no entry found dn [" + dn + "]";
+ throw new FinderException( GlobalErrIds.ROLE_NOT_FOUND, warning );
+ }
+ }
+ catch ( LdapNoSuchObjectException e )
+ {
+ String warning = "getRole Obj COULD NOT FIND ENTRY for dn [" + dn + "]";
+ throw new FinderException( GlobalErrIds.ROLE_NOT_FOUND, warning );
+ }
+ catch ( LdapException e )
+ {
+ String error = "getRole dn [" + dn + "] LEXCD=" + e;
+ throw new FinderException( GlobalErrIds.ROLE_READ_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return entity;
+ }
+
+
+ /**
+ * @param role
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ *
+ */
+ public final List<Role> findRoles( Role role )
+ throws FinderException
+ {
+ List<Role> roleList = new ArrayList<>();
+ LdapConnection ld = null;
+ String roleRoot = getRootDn( role.getContextId(), GlobalIds.ROLE_ROOT );
+ String filter = null;
+
+ try
+ {
+ String searchVal = encodeSafeText( role.getName(), GlobalIds.ROLE_LEN );
+ filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")("
+ + ROLE_NM + "=" + searchVal + "*))";
+ ld = getAdminConnection();
+ SearchCursor searchResults = search( ld, roleRoot,
+ SearchScope.ONELEVEL, filter, ROLE_ATRS, false, GlobalIds.BATCH_SIZE );
+ long sequence = 0;
+
+ while ( searchResults.next() )
+ {
+ roleList.add( unloadLdapEntry( searchResults.getEntry(), sequence++, role.getContextId() ) );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e );
+ }
+ catch ( CursorException e )
+ {
+ String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return roleList;
+ }
+
+
+ /**
+ * @param role
+ * @param limit
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ *
+ */
+ public final List<String> findRoles( Role role, int limit )
+ throws FinderException
+ {
+ List<String> roleList = new ArrayList<>();
+ LdapConnection ld = null;
+ String roleRoot = getRootDn( role.getContextId(), GlobalIds.ROLE_ROOT );
+ String filter = null;
+
+ try
+ {
+ String searchVal = encodeSafeText( role.getName(), GlobalIds.ROLE_LEN );
+ filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")("
+ + ROLE_NM + "=" + searchVal + "*))";
+ ld = getAdminConnection();
+ SearchCursor searchResults = search( ld, roleRoot,
+ SearchScope.ONELEVEL, filter, ROLE_NM_ATR, false, GlobalIds.BATCH_SIZE, limit );
+
+ while ( searchResults.next() )
+ {
+ Entry entry = searchResults.getEntry();
+ roleList.add( getAttribute( entry, ROLE_NM ) );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e );
+ }
+ catch ( CursorException e )
+ {
+ String error = "findRoles filter [" + filter + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return roleList;
+ }
+
+
+ /**
+ *
+ * @param userDn
+ * @param contextId
+ * @return
+ * @throws FinderException
+ */
+ public final List<String> findAssignedRoles( String userDn, String contextId )
+ throws FinderException
+ {
+ List<String> roleNameList = new ArrayList<>();
+ LdapConnection ld = null;
+ String roleRoot = getRootDn( contextId, GlobalIds.ROLE_ROOT );
+
+ try
+ {
+ String filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")";
+ filter += "(" + ROLE_OCCUPANT + "=" + userDn + "))";
+ ld = getAdminConnection();
+ SearchCursor searchResults = search( ld, roleRoot,
+ SearchScope.ONELEVEL, filter, ROLE_NM_ATR, false, GlobalIds.BATCH_SIZE );
+
+ while ( searchResults.next() )
+ {
+ roleNameList.add( getAttribute( searchResults.getEntry(), ROLE_NM ) );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "findAssignedRoles userDn [" + userDn + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_OCCUPANT_SEARCH_FAILED, error, e );
+ }
+ catch ( CursorException e )
+ {
+ String error = "findAssignedRoles userDn [" + userDn + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_OCCUPANT_SEARCH_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return roleNameList;
+ }
+
+
+ /**
+ *
+ * @param contextId
+ * @return
+ * @throws FinderException
+ */
+ public final List<Graphable> getAllDescendants( String contextId )
+ throws FinderException
+ {
+ String[] DESC_ATRS =
+ { ROLE_NM, GlobalIds.PARENT_NODES };
+ List<Graphable> descendants = new ArrayList<>();
+ LdapConnection ld = null;
+ String roleRoot = getRootDn( contextId, GlobalIds.ROLE_ROOT );
+ String filter = null;
+
+ try
+ {
+ filter = GlobalIds.FILTER_PREFIX + GlobalIds.ROLE_OBJECT_CLASS_NM + ")("
+ + GlobalIds.PARENT_NODES + "=*))";
+ ld = getAdminConnection();
+ SearchCursor searchResults = search( ld, roleRoot,
+ SearchScope.ONELEVEL, filter, DESC_ATRS, false, GlobalIds.BATCH_SIZE );
+ long sequence = 0;
+
+ while ( searchResults.next() )
+ {
+ descendants.add( unloadDescendants( searchResults.getEntry(), sequence++, contextId ) );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "getAllDescendants filter [" + filter + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e );
+ }
+ catch ( CursorException e )
+ {
+ String error = "getAllDescendants filter [" + filter + "] caught LdapException=" + e.getMessage();
+ throw new FinderException( GlobalErrIds.ROLE_SEARCH_FAILED, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return descendants;
+ }
+
+
+ /**
+ *
+ * @param le
+ * @param sequence
+ * @param contextId
+ * @return
+ * @throws LdapInvalidAttributeValueException
+ * @throws LdapException
+ */
+ private Graphable unloadDescendants( Entry le, long sequence, String contextId )
+ throws LdapInvalidAttributeValueException
+ {
+ Role entity = new ObjectFactory().createRole();
+ entity.setSequenceId( sequence );
+ entity.setName( getAttribute( le, ROLE_NM ) );
+ entity.setParents( getAttributeSet( le, GlobalIds.PARENT_NODES ) );
+ return entity;
+ }
+
+
+ /**
+ *
+ * @param le
+ * @param sequence
+ * @param contextId
+ * @return
+ * @throws LdapInvalidAttributeValueException
+ * @throws LdapException
+ */
+ private Role unloadLdapEntry( Entry le, long sequence, String contextId ) throws LdapInvalidAttributeValueException
+ {
+ Role entity = new ObjectFactory().createRole();
+ entity.setSequenceId( sequence );
+ entity.setId( getAttribute( le, GlobalIds.FT_IID ) );
+ entity.setName( getAttribute( le, ROLE_NM ) );
+ entity.setDescription( getAttribute( le, GlobalIds.DESC ) );
+ entity.setOccupants( getAttributes( le, ROLE_OCCUPANT ) );
+ //entity.setParents(RoleUtil.getParents(entity.getName().toUpperCase(), contextId));
+ entity.setChildren( RoleUtil.getChildren( entity.getName().toUpperCase(), contextId ) );
+ entity.setParents( getAttributeSet( le, GlobalIds.PARENT_NODES ) );
+ unloadTemporal( le, entity );
+
+ return entity;
+ }
+
+
+ private String getDn( String name, String contextId )
+ {
+ return GlobalIds.CN + "=" + name + "," + getRootDn( contextId, GlobalIds.ROLE_ROOT );
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/directory-fortress-core/blob/687ee1ad/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java
new file mode 100755
index 0000000..f4d25b6
--- /dev/null
+++ b/src/main/java/org/apache/directory/fortress/core/rbac/dao/apache/SdDAO.java
@@ -0,0 +1,633 @@
+/*
+ * 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.rbac.dao.apache;
+
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.entry.DefaultModification;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.entry.Modification;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.ldap.client.api.LdapConnection;
+
+import org.apache.directory.fortress.core.CreateException;
+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.ObjectFactory;
+import org.apache.directory.fortress.core.RemoveException;
+import org.apache.directory.fortress.core.UpdateException;
+import org.apache.directory.fortress.core.ldap.ApacheDsDataProvider;
+import org.apache.directory.fortress.core.rbac.Role;
+import org.apache.directory.fortress.core.rbac.RoleUtil;
+import org.apache.directory.fortress.core.rbac.SDSet;
+import org.apache.directory.fortress.core.util.attr.VUtil;
+
+
+/**
+ * This class performs persistence on the RBAC Static Separation of Duties and Dynamic Separation of Duties data sets.
+ * <p/>
+ * The Fortress SDSet entity is a composite of the following other Fortress structural and aux object classes:
+ * <h4>1. organizationalRole Structural Object Class is used to store basic attributes like cn and description</h4>
+ * <ul>
+ * <li> ------------------------------------------
+ * <li> <code>objectclass ( 2.5.6.8 NAME 'organizationalRole'</code>
+ * <li> <code>DESC 'RFC2256: an organizational role'</code>
+ * <li> <code>SUP top STRUCTURAL</code>
+ * <li> <code>MUST cn</code>
+ * <li> <code>MAY ( x121Address $ registeredAddress $ destinationIndicator $</code>
+ * <li> <code>preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $</code>
+ * <li> <code>telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $</code>
+ * <li> <code>seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $</code>
+ * <li> <code>postOfficeBox $ postalCode $ postalAddress $</code>
+ * <li> <code>physicalDeliveryOfficeName $ ou $ st $ l $ description ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <h4>2. The RBAC Separation of Duties</h4>
+ * <ul>
+ * <li> ---Static Separation of Duties Set-------
+ * <li> <code>objectclass ( 1.3.6.1.4.1.38088.2.4</code>
+ * <li> <code>NAME 'ftSSDSet'</code>
+ * <li> <code>DESC 'Fortress Role Static Separation of Duty Set Object Class'</code>
+ * <li> <code>SUP organizationalrole</code>
+ * <li> <code>STRUCTURAL</code>
+ * <li> <code>MUST ( ftId $ ftSetName $ ftSetCardinality )</code>
+ * <li> <code>MAY ( ftRoles $ description ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <p/>
+ * OR
+ * <h4>Dynamic Separation of Duties Set</h4>
+ * <ul>
+ * <li>
+ * <li> <code>objectclass ( 1.3.6.1.4.1.38088.2.5</code>
+ * <li> <code>NAME 'ftDSDSet'</code>
+ * <li> <code>DESC 'Fortress Role Dynamic Separation of Duty Set Object Class'</code>
+ * <li> <code>SUP organizationalrole</code>
+ * <li> <code>STRUCTURAL</code>
+ * <li> <code>MUST ( ftId $ ftSetName $ ftSetCardinality )</code>
+ * <li> <code>MAY ( ftRoles $ description ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <h4>3. ftMods AUXILIARY Object Class is used to store Fortress audit variables on target entity</h4>
+ * <ul>
+ * <li> <code>objectclass ( 1.3.6.1.4.1.38088.3.4</code>
+ * <li> <code>NAME 'ftMods'</code>
+ * <li> <code>DESC 'Fortress Modifiers AUX Object Class'</code>
+ * <li> <code>AUXILIARY</code>
+ * <li> <code>MAY (</code>
+ * <li> <code>ftModifier $</code>
+ * <li> <code>ftModCode $</code>
+ * <li> <code>ftModId ) )</code>
+ * <li> ------------------------------------------
+ * </ul>
+ * <p/>
+ * This class is thread safe.
+ * <p/>
+ *
+ * @author Shawn McKinney
+ */
+public final class SdDAO extends ApacheDsDataProvider implements org.apache.directory.fortress.core.rbac.dao.SdDAO
+{
+ private static final String SD_SET_NM = "ftSetName";
+ private static final String ROLES = "ftRoles";
+ private static final String SD_SET_CARDINALITY = "ftSetCardinality";
+
+ private static final String SSD_OBJECT_CLASS_NM = "ftSSDSet";
+ private static final String SSD_OBJ_CLASS[] =
+ {
+ GlobalIds.TOP, SSD_OBJECT_CLASS_NM, GlobalIds.FT_MODIFIER_AUX_OBJECT_CLASS_NAME
+ };
+
+ private static final String DSD_OBJECT_CLASS_NM = "ftDSDSet";
+ private static final String DSD_OBJ_CLASS[] =
+ {
+ GlobalIds.TOP, DSD_OBJECT_CLASS_NM, GlobalIds.FT_MODIFIER_AUX_OBJECT_CLASS_NAME
+ };
+
+ private static final String[] SD_SET_ATRS =
+ {
+ GlobalIds.FT_IID, SD_SET_NM, GlobalIds.DESC, ROLES, SD_SET_CARDINALITY
+ };
+
+
+ /**
+ * @param entity
+ * @return
+ * @throws org.apache.directory.fortress.core.CreateException
+ */
+ public final SDSet create( SDSet entity ) throws CreateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+ String[] objectClass = SSD_OBJ_CLASS;
+
+ if ( entity.getType() == SDSet.SDType.DYNAMIC )
+ {
+ objectClass = DSD_OBJ_CLASS;
+ }
+
+ try
+ {
+ Entry entry = new DefaultEntry( dn );
+ entry.add( createAttributes( GlobalIds.OBJECT_CLASS, objectClass ) );
+ entity.setId();
+ entry.add( GlobalIds.FT_IID, entity.getId() );
+ entry.add( SD_SET_NM, entity.getName() );
+
+ // description field is optional on this object class:
+ if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+ {
+ entry.add( GlobalIds.DESC, entity.getDescription() );
+ }
+
+ // CN attribute is required for this object class:
+ entry.add( GlobalIds.CN, entity.getName() );
+ loadAttrs( entity.getMembers(), entry, ROLES );
+ entry.add( SD_SET_CARDINALITY, "" + entity.getCardinality() );
+
+ ld = getAdminConnection();
+ add( ld, entry, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "create SD set name [" + entity.getName() + "] type [" + entity.getType()
+ + "] caught LdapException=" + e.getMessage();
+ int errCode;
+ if ( entity.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_ADD_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_ADD_FAILED;
+ }
+
+ throw new CreateException( errCode, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return entity;
+ }
+
+
+ /**
+ * @param entity
+ * @return
+ * @throws org.apache.directory.fortress.core.UpdateException
+ */
+ public final SDSet update( SDSet entity ) throws UpdateException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+
+ try
+ {
+ List<Modification> mods = new ArrayList<Modification>();
+
+ if ( VUtil.isNotNullOrEmpty( entity.getDescription() ) )
+ {
+ mods.add( new DefaultModification(
+ ModificationOperation.REPLACE_ATTRIBUTE, GlobalIds.DESC, entity.getDescription() ) );
+ }
+
+ if ( entity.getCardinality() != null )
+ {
+ mods.add( new DefaultModification(
+ ModificationOperation.REPLACE_ATTRIBUTE, SD_SET_CARDINALITY, entity.getCardinality().toString() ) );
+ }
+
+ loadAttrs( entity.getMembers(), mods, ROLES );
+
+ if ( mods.size() > 0 )
+ {
+ ld = getAdminConnection();
+ modify( ld, dn, mods, entity );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "update name [" + entity.getName() + "] type [" + entity.getType()
+ + "] caught LdapException=" + e.getMessage();
+ int errCode;
+ if ( entity.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_UPDATE_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_UPDATE_FAILED;
+ }
+
+ throw new UpdateException( errCode, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return entity;
+ }
+
+
+ /**
+ * @param entity
+ * @throws org.apache.directory.fortress.core.RemoveException
+ */
+ public final SDSet remove( SDSet entity ) throws RemoveException
+ {
+ LdapConnection ld = null;
+ String dn = getDn( entity.getName(), entity.getContextId() );
+
+ try
+ {
+ ld = getAdminConnection();
+ delete( ld, dn, entity );
+ }
+ catch ( LdapException e )
+ {
+ String error = "remove SD name=" + entity.getName() + " type [" + entity.getType() + "] LdapException="
+ + e.getMessage();
+ int errCode;
+ if ( entity.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_DELETE_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_DELETE_FAILED;
+ }
+
+ throw new RemoveException( errCode, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return entity;
+ }
+
+
+ /**
+ * @param sdSet
+ * @return
+ * @throws FinderException
+ */
+ public final SDSet getSD( SDSet sdSet ) throws FinderException
+ {
+ SDSet entity = null;
+ LdapConnection ld = null;
+ String dn = getDn( sdSet.getName(), sdSet.getContextId() );
+
+ try
+ {
+ ld = getAdminConnection();
+ Entry findEntry = read( ld, dn, SD_SET_ATRS );
+ entity = unloadLdapEntry( findEntry, 0 );
+
+ if ( entity == null )
+ {
+ String warning = "getSD no entry found dn [" + dn + "]";
+ throw new FinderException( GlobalErrIds.SSD_NOT_FOUND, warning );
+ }
+ }
+ catch ( LdapNoSuchObjectException e )
+ {
+ String warning = "getSD Obj COULD NOT FIND ENTRY for dn [" + dn + "]";
+ throw new FinderException( GlobalErrIds.SSD_NOT_FOUND, warning );
+ }
+ catch ( LdapException e )
+ {
+ String error = "getSSD dn [" + dn + "] LEXCD=" + e;
+ int errCode;
+
+ if ( sdSet.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_READ_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_READ_FAILED;
+ }
+
+ throw new FinderException( errCode, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return entity;
+ }
+
+
+ /**
+ * Given an SSD name and type, find matching object in the directory.
+ * @param sdset requires name and type.
+ * @return List of matching SDSets.
+ * @throws org.apache.directory.fortress.core.FinderException
+ */
+ public final List<SDSet> search( SDSet sdset ) throws FinderException
+ {
+ List<SDSet> sdList = new ArrayList<>();
+ LdapConnection ld = null;
+ String ssdRoot = getSdRoot( sdset.getContextId() );
+ String objectClass = SSD_OBJECT_CLASS_NM;
+
+ if ( sdset.getType() == SDSet.SDType.DYNAMIC )
+ {
+ objectClass = DSD_OBJECT_CLASS_NM;
+ }
+
+ try
+ {
+ String searchVal = encodeSafeText( sdset.getName(), GlobalIds.ROLE_LEN );
+ String filter = GlobalIds.FILTER_PREFIX + objectClass + ")(" + SD_SET_NM + "=" + searchVal + "*))";
+ ld = getAdminConnection();
+ SearchCursor searchResults = search( ld, ssdRoot,
+ SearchScope.SUBTREE, filter, SD_SET_ATRS, false, GlobalIds.BATCH_SIZE );
+ long sequence = 0;
+
+ while ( searchResults.next() )
+ {
+ sdList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "search sdset name [" + sdset.getName() + "] type [" + sdset.getType()
+ + "] caught LdapException=" + e.getMessage();
+ int errCode;
+
+ if ( sdset.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_SEARCH_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_SEARCH_FAILED;
+ }
+
+ throw new FinderException( errCode, error, e );
+ }
+ catch ( CursorException e )
+ {
+ String error = "search sdset name [" + sdset.getName() + "] type [" + sdset.getType()
+ + "] caught LdapException=" + e.getMessage();
+ int errCode;
+
+ if ( sdset.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_SEARCH_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_SEARCH_FAILED;
+ }
+
+ throw new FinderException( errCode, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+ return sdList;
+ }
+
+
+ /**
+ * @param role
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ */
+ public final List<SDSet> search( Role role, SDSet.SDType type ) throws FinderException
+ {
+ List<SDSet> sdList = new ArrayList<>();
+ LdapConnection ld = null;
+ String ssdRoot = getSdRoot( role.getContextId() );
+ String objectClass = SSD_OBJECT_CLASS_NM;
+
+ if ( type == SDSet.SDType.DYNAMIC )
+ {
+ objectClass = DSD_OBJECT_CLASS_NM;
+ }
+
+ try
+ {
+ String roleVal = encodeSafeText( role.getName(), GlobalIds.ROLE_LEN );
+ //String filter = GlobalIds.FILTER_PREFIX + SSD_OBJECT_CLASS_NM + ")(" + ROLES + "=" + roleVal + "))";
+ String filter = GlobalIds.FILTER_PREFIX + objectClass + ")(";
+ // Include any parents target role may have:
+ Set<String> roles = RoleUtil.getAscendants( role.getName(), role.getContextId() );
+
+ if ( VUtil.isNotNullOrEmpty( roles ) )
+ {
+ filter += "|(" + ROLES + "=" + roleVal + ")";
+
+ for ( String uRole : roles )
+ {
+ filter += "(" + ROLES + "=" + uRole + ")";
+ }
+ filter += ")";
+ }
+ else
+ {
+ filter += ROLES + "=" + roleVal + ")";
+ }
+
+ filter += ")";
+ ld = getAdminConnection();
+ SearchCursor searchResults = search( ld, ssdRoot,
+ SearchScope.SUBTREE, filter, SD_SET_ATRS, false, GlobalIds.BATCH_SIZE );
+
+ long sequence = 0;
+
+ while ( searchResults.next() )
+ {
+ sdList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) );
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "search role [" + role.getName() + "] type [" + type + "] caught LdapException="
+ + e.getMessage();
+ int errCode;
+
+ if ( type == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_SEARCH_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_SEARCH_FAILED;
+ }
+
+ throw new FinderException( errCode, error, e );
+ }
+ catch ( CursorException e )
+ {
+ String error = "search role [" + role.getName() + "] type [" + type + "] caught LdapException="
+ + e.getMessage();
+ int errCode;
+
+ if ( type == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_SEARCH_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_SEARCH_FAILED;
+ }
+
+ throw new FinderException( errCode, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return sdList;
+ }
+
+
+ /**
+ * @param roles
+ * @param sdSet
+ * @return
+ * @throws org.apache.directory.fortress.core.FinderException
+ */
+ public final Set<SDSet> search( Set<String> roles, SDSet sdSet ) throws FinderException
+ {
+ Set<SDSet> sdList = new HashSet<>();
+ LdapConnection ld = null;
+ String ssdRoot = getSdRoot( sdSet.getContextId() );
+ String objectClass = SSD_OBJECT_CLASS_NM;
+
+ if ( sdSet.getType() == SDSet.SDType.DYNAMIC )
+ {
+ objectClass = DSD_OBJECT_CLASS_NM;
+ }
+
+ try
+ {
+ if ( VUtil.isNotNullOrEmpty( roles ) )
+ {
+ String filter = GlobalIds.FILTER_PREFIX + objectClass + ")(|";
+ for ( String rle : roles )
+ {
+ filter += "(" + ROLES + "=" + rle + ")";
+ }
+ filter += "))";
+ ld = getAdminConnection();
+ SearchCursor searchResults = search( ld, ssdRoot,
+ SearchScope.SUBTREE, filter, SD_SET_ATRS, false, GlobalIds.BATCH_SIZE );
+ long sequence = 0;
+
+ while ( searchResults.next() )
+ {
+ sdList.add( unloadLdapEntry( searchResults.getEntry(), sequence++ ) );
+ }
+ }
+ }
+ catch ( LdapException e )
+ {
+ String error = "search type [" + sdSet.getType() + "] caught LdapException=" + e.getMessage();
+ int errCode;
+
+ if ( sdSet.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_SEARCH_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_SEARCH_FAILED;
+ }
+ throw new FinderException( errCode, error, e );
+ }
+ catch ( CursorException e )
+ {
+ String error = "search type [" + sdSet.getType() + "] caught LdapException=" + e.getMessage();
+ int errCode;
+
+ if ( sdSet.getType() == SDSet.SDType.DYNAMIC )
+ {
+ errCode = GlobalErrIds.DSD_SEARCH_FAILED;
+ }
+ else
+ {
+ errCode = GlobalErrIds.SSD_SEARCH_FAILED;
+ }
+ throw new FinderException( errCode, error, e );
+ }
+ finally
+ {
+ closeAdminConnection( ld );
+ }
+
+ return sdList;
+ }
+
+
+ /**
+ * @param le
+ * @return
+ * @throws LdapInvalidAttributeValueException
+ * @throws LdapException
+ */
+ private SDSet unloadLdapEntry( Entry le, long sequence ) throws LdapInvalidAttributeValueException
+ {
+ SDSet entity = new ObjectFactory().createSDset();
+ entity.setSequenceId( sequence );
+ entity.setId( getAttribute( le, GlobalIds.FT_IID ) );
+ entity.setName( getAttribute( le, SD_SET_NM ) );
+ entity.setDescription( getAttribute( le, GlobalIds.DESC ) );
+ entity.setMembers( getAttributeSet( le, ROLES ) );
+ String szCard = getAttribute( le, SD_SET_CARDINALITY );
+ entity.setCardinality( new Integer( szCard ) );
+
+ return entity;
+ }
+
+
+ private String getDn( String name, String contextId )
+ {
+ return GlobalIds.CN + "=" + name + "," + getSdRoot( contextId );
+ }
+
+
+ private String getSdRoot( String contextId )
+ {
+ return getRootDn( contextId, GlobalIds.SD_ROOT );
+ }
+}