Coverage Report - org.kuali.rice.kew.doctype.service.impl.DocumentSecurityServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentSecurityServiceImpl
0%
0/122
0%
0/78
6.636
 
 1  
 /*
 2  
  * Copyright 2007-2009 The Kuali Foundation
 3  
  * 
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  * 
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  * 
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kew.doctype.service.impl;
 17  
 
 18  
 import java.lang.reflect.Field;
 19  
 import java.util.Calendar;
 20  
 import java.util.Collection;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 
 24  
 import org.apache.commons.lang.StringUtils;
 25  
 import org.kuali.rice.core.api.datetime.DateTimeService;
 26  
 import org.kuali.rice.core.api.CoreConstants;
 27  
 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
 28  
 import org.kuali.rice.core.util.AttributeSet;
 29  
 import org.kuali.rice.core.util.KeyValue;
 30  
 import org.kuali.rice.kew.docsearch.DocSearchDTO;
 31  
 import org.kuali.rice.kew.doctype.DocumentTypeSecurity;
 32  
 import org.kuali.rice.kew.doctype.SecurityAttribute;
 33  
 import org.kuali.rice.kew.doctype.SecurityPermissionInfo;
 34  
 import org.kuali.rice.kew.doctype.SecuritySession;
 35  
 import org.kuali.rice.kew.doctype.bo.DocumentType;
 36  
 import org.kuali.rice.kew.doctype.service.DocumentSecurityService;
 37  
 import org.kuali.rice.kew.dto.RouteHeaderDTO;
 38  
 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
 39  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 40  
 import org.kuali.rice.kew.user.UserUtils;
 41  
 import org.kuali.rice.kew.util.KEWConstants;
 42  
 import org.kuali.rice.kim.api.group.Group;
 43  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 44  
 import org.kuali.rice.kim.bo.Person;
 45  
 import org.kuali.rice.kns.UserSession;
 46  
 
 47  
 
 48  0
 public class DocumentSecurityServiceImpl implements DocumentSecurityService {
 49  0
   public static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentSecurityServiceImpl.class);
 50  
 
 51  
   @Override
 52  
 public boolean docSearchAuthorized(UserSession userSession, DocSearchDTO docCriteriaDTO, SecuritySession session) {
 53  0
       return checkAuthorization(userSession, session, docCriteriaDTO.getDocTypeName(), docCriteriaDTO.getDocumentId(), docCriteriaDTO.getInitiatorWorkflowId());
 54  
   }
 55  
 
 56  
   @Override
 57  
 public boolean routeLogAuthorized(UserSession userSession, DocumentRouteHeaderValue routeHeader, SecuritySession session) {
 58  0
       return checkAuthorization(userSession, session, routeHeader.getDocumentType().getName(), routeHeader.getDocumentId(), routeHeader.getInitiatorWorkflowId());
 59  
   }
 60  
 
 61  
   protected boolean checkAuthorization(UserSession userSession, SecuritySession session, String documentTypeName, String documentId, String initiatorPrincipalId) {
 62  0
       DocumentTypeSecurity security = null;
 63  
       try {
 64  0
           security = getDocumentTypeSecurity(userSession, documentTypeName, session);
 65  0
           if (security == null || !security.isActive()) {
 66  
             // Security is not enabled for this doctype.  Everyone can see this doc.
 67  0
             return true;
 68  
           }
 69  0
           if (isAdmin(session)) {
 70  0
               return true;
 71  
           }
 72  0
           for (SecurityAttribute securityAttribute : security.getSecurityAttributes()) {
 73  0
               Boolean authorized = securityAttribute.docSearchAuthorized(userSession.getPerson(), documentTypeName, documentId, initiatorPrincipalId);
 74  0
               if (authorized != null) {
 75  0
                   return authorized.booleanValue();
 76  
               }
 77  0
           }
 78  
       } 
 79  0
       catch (Exception e) {
 80  0
           LOG.warn("Not able to retrieve DocumentTypeSecurity from remote system for doctype: " + documentTypeName, e);
 81  0
           return false;
 82  0
       }
 83  0
       return checkStandardAuthorization(security, userSession, documentTypeName, documentId, initiatorPrincipalId, session);
 84  
   }
 85  
 
 86  
   protected boolean isAdmin(SecuritySession session) {
 87  0
           if (session.getUserSession() == null) {
 88  0
                   return false;
 89  
           }
 90  0
           return KimApiServiceLocator.getIdentityManagementService().isAuthorized(session.getUserSession().getPrincipalId(), KEWConstants.KEW_NAMESPACE,        KEWConstants.PermissionNames.UNRESTRICTED_DOCUMENT_SEARCH, new AttributeSet(), new AttributeSet());
 91  
   }
 92  
 
 93  
   protected boolean checkStandardAuthorization(DocumentTypeSecurity security, UserSession userSession, String docTypeName, String documentId, String initiatorPrincipalId, SecuritySession session) {
 94  0
         Person user = userSession.getPerson();
 95  
 
 96  0
     LOG.debug("auth check user=" + user.getPrincipalId() +" docId=" + documentId);
 97  
 
 98  
     // Doc Initiator Authorization
 99  0
     if (security.getInitiatorOk() != null && security.getInitiatorOk()) {
 100  0
       boolean isInitiator = StringUtils.equals(initiatorPrincipalId, user.getPrincipalId());
 101  0
       if (isInitiator) {
 102  0
         return true;
 103  
       }
 104  
     }
 105  
 
 106  
     // Role authorization
 107  
     /* Removing in Rice 1.1
 108  
     List<String> allowedRoles = security.getAllowedRoles();
 109  
     List<String> disallowedRoles = security.getDisallowedRoles();
 110  
     // only execute role security if they have it defined
 111  
     if ((allowedRoles != null && !allowedRoles.isEmpty()) ||
 112  
                     (disallowedRoles != null && !disallowedRoles.isEmpty())) {
 113  
             Boolean passesRoleSecurity = session.getPassesRoleSecurity().get(docTypeName);
 114  
             if (passesRoleSecurity != null) {
 115  
                     if (passesRoleSecurity) {
 116  
                             return true;
 117  
                     }
 118  
             } else {
 119  
                     passesRoleSecurity = isRoleAuthenticated(allowedRoles, disallowedRoles, userSession, session);
 120  
                     session.getPassesRoleSecurity().put(docTypeName, passesRoleSecurity);
 121  
                     if (passesRoleSecurity) {
 122  
                             return true;
 123  
                     }
 124  
             }
 125  
     }
 126  
     */
 127  
     
 128  
     // Permission Authorization
 129  0
     List<SecurityPermissionInfo> securityPermissions = security.getPermissions();
 130  0
     if (securityPermissions != null) {
 131  0
             for (SecurityPermissionInfo securityPermission : securityPermissions) {
 132  0
                     if (isAuthenticatedByPermission(documentId, securityPermission.getPermissionNamespaceCode(), securityPermission.getPermissionName(), securityPermission.getPermissionDetails(), securityPermission.getQualifications(), session)) {
 133  0
                             return true;
 134  
                     }
 135  
             }
 136  
     }
 137  
 
 138  
     //  Workgroup Authorization
 139  0
     List<Group> securityWorkgroups = security.getWorkgroups();
 140  0
     if (securityWorkgroups != null) {
 141  0
       for (Group securityWorkgroup : securityWorkgroups) {
 142  0
         if (isWorkgroupAuthenticated(securityWorkgroup.getNamespaceCode(), securityWorkgroup.getName(), session)) {
 143  0
                 return true;
 144  
         }
 145  
       }
 146  
     }
 147  
 
 148  
     // Searchable Attribute Authorization
 149  0
     Collection searchableAttributes = security.getSearchableAttributes();
 150  0
     if (searchableAttributes != null) {
 151  0
       for (Iterator iterator = searchableAttributes.iterator(); iterator.hasNext();) {
 152  0
         KeyValue searchableAttr = (KeyValue) iterator.next();
 153  0
         String attrName = searchableAttr.getKey();
 154  0
         String idType = searchableAttr.getValue();
 155  0
         String idValue = UserUtils.getIdValue(idType, user);
 156  0
         if (!StringUtils.isEmpty(idValue)) {
 157  0
           if (KEWServiceLocator.getRouteHeaderService().hasSearchableAttributeValue(documentId, attrName, idValue)) {
 158  0
             return true;
 159  
           }
 160  
         }
 161  0
       }
 162  
     }
 163  
 
 164  
     // Route Log Authorization
 165  0
     if (security.getRouteLogAuthenticatedOk() != null && security.getRouteLogAuthenticatedOk()) {
 166  0
       boolean isInitiator = StringUtils.equals(initiatorPrincipalId, user.getPrincipalId());
 167  0
       if (isInitiator) {
 168  0
         return true;
 169  
       }
 170  0
       boolean hasTakenAction = KEWServiceLocator.getActionTakenService().hasUserTakenAction(user.getPrincipalId(), documentId);
 171  0
       if (hasTakenAction) {
 172  0
         return true;
 173  
       }
 174  0
       boolean hasRequest = KEWServiceLocator.getActionRequestService().doesPrincipalHaveRequest(user.getPrincipalId(), documentId);
 175  0
       if (hasRequest) {
 176  0
         return true;
 177  
       }
 178  
     }
 179  
 
 180  0
     LOG.debug("user not authorized");
 181  0
     return false;
 182  
   }
 183  
 
 184  
 protected DocumentTypeSecurity getDocumentTypeSecurity(UserSession userSession, String documentTypeName, SecuritySession session) {
 185  0
       if (session == null) {
 186  0
           session = new SecuritySession(userSession);
 187  
       }
 188  0
           DocumentTypeSecurity security = session.getDocumentTypeSecurity().get(documentTypeName);
 189  0
           if (security == null) {
 190  0
                   DocumentType docType = KEWServiceLocator.getDocumentTypeService().findByName(documentTypeName);
 191  0
                   security = docType.getDocumentTypeSecurity();
 192  0
                   session.getDocumentTypeSecurity().put(documentTypeName, security);
 193  
           }
 194  0
           return security;
 195  
   }
 196  
 
 197  
   protected boolean isWorkgroupAuthenticated(String namespace, String workgroupName, SecuritySession session) {
 198  0
           String key = namespace.trim() + KEWConstants.KIM_GROUP_NAMESPACE_NAME_DELIMITER_CHARACTER + workgroupName.trim();
 199  0
       Boolean existingAuth = session.getAuthenticatedWorkgroups().get(key);
 200  0
           if (existingAuth != null) {
 201  0
                   return existingAuth;
 202  
           }
 203  0
           boolean memberOfGroup = isMemberOfGroupWithName(namespace, workgroupName, session.getUserSession().getPrincipalId());
 204  0
           session.getAuthenticatedWorkgroups().put(key, memberOfGroup);
 205  0
           return memberOfGroup;
 206  
   }
 207  
 
 208  
         private boolean isMemberOfGroupWithName(String namespace, String groupName, String principalId) {
 209  0
                 for (Group group : KimApiServiceLocator.getIdentityManagementService().getGroupsForPrincipal(principalId)) {
 210  0
                         if (StringUtils.equals(namespace, group.getNamespaceCode()) && StringUtils.equals(groupName, group.getName())) {
 211  0
                                 return true;
 212  
                         }
 213  
                 }
 214  0
                 return false;
 215  
         }
 216  
 
 217  
         protected boolean isAuthenticatedByPermission(String documentId, String permissionNamespaceCode,
 218  
                         String permissionName, AttributeSet permissionDetails,
 219  
                         AttributeSet qualification, SecuritySession session)  {
 220  
                 
 221  
                 RouteHeaderDTO routeHeader;
 222  
                 try {
 223  0
                         routeHeader = KEWServiceLocator.getWorkflowUtilityService().getRouteHeader(documentId);
 224  
                         
 225  0
                         for (String qualificationKey : qualification.keySet()){
 226  0
                                 String qualificationValue = qualification.get(qualificationKey);
 227  0
                                 String replacementValue = getReplacementString(routeHeader, qualificationValue);
 228  0
                         qualification.put(qualificationKey, replacementValue);
 229  0
                         }
 230  
                         
 231  0
                         for (String permissionDetailKey : permissionDetails.keySet()){
 232  0
                                 String detailValue = qualification.get(permissionDetailKey);
 233  0
                                 String replacementValue = getReplacementString(routeHeader, detailValue);
 234  0
                         qualification.put(permissionDetailKey, replacementValue);
 235  0
                         }
 236  0
                 } catch (Exception e) {
 237  0
                         LOG.error(e.getMessage(), e);
 238  0
                         return false;
 239  0
                 }
 240  0
                 return KimApiServiceLocator.getIdentityManagementService().isAuthorized(session.getUserSession().getPrincipalId(), permissionNamespaceCode, permissionName, permissionDetails, qualification);
 241  
         }
 242  
 
 243  
         private String getReplacementString(RouteHeaderDTO routeHeader, String value) throws Exception {
 244  0
                 String startsWith = "${document.";
 245  0
                 String endsWith = "}";
 246  0
                 if (value.startsWith(startsWith)) {
 247  0
                         String replacementValue = "";
 248  0
                         int tokenStart = value.indexOf(startsWith);
 249  0
             int tokenEnd = value.indexOf(endsWith, tokenStart + startsWith.length());
 250  0
             if (tokenEnd == -1) {
 251  0
                 throw new RuntimeException("No ending bracket on token in value " +value);
 252  
             }
 253  0
             String token = value.substring(tokenStart + startsWith.length(), tokenEnd);
 254  
                 
 255  0
             return getRouteHeaderVariableValue(routeHeader, token);
 256  
                 }
 257  0
                 return value;
 258  
                 
 259  
         }
 260  
         private String getRouteHeaderVariableValue(RouteHeaderDTO routeHeader, String variableName) throws Exception {
 261  0
                 Field field = routeHeader.getClass().getDeclaredField(variableName);
 262  0
                 field.setAccessible(true);
 263  0
                 Object fieldValue = field.get(routeHeader);
 264  0
                 Class clazzType = field.getType();
 265  0
                 if (clazzType.equals(String.class)) {
 266  0
                         return (String)fieldValue;
 267  0
                 } else if (clazzType.getName().equals("boolean") || clazzType.getName().equals("java.lang.Boolean")) {
 268  0
                         if ((Boolean)fieldValue) {
 269  0
                                 return "Y";
 270  
                         } 
 271  0
                         return "N";
 272  0
                 } else if (clazzType.getName().equals("java.util.Calendar")) {
 273  
                 
 274  0
                         DateTimeService dateTimeService = GlobalResourceLoader.getService(CoreConstants.Services.DATETIME_SERVICE);
 275  0
                         return dateTimeService.toDateString(((Calendar)fieldValue).getTime());
 276  
                 }
 277  0
                 return String.valueOf(fieldValue);
 278  
         }
 279  
         
 280  
 /*
 281  
   protected boolean isRoleAuthenticated(List<String> allowedRoles, List<String> disallowedRoles, UserSession userSession, SecuritySession session) {
 282  
           boolean disallowed = false;
 283  
           boolean allowed = false;
 284  
           
 285  
 
 286  
           allowed =  KIMServiceLocatorInternal.getRoleService().principalHasRole(session.getUserSession().getPrincipalId(), allowedRoles, null);
 287  
           disallowed = KIMServiceLocatorInternal.getRoleService().principalHasRole(session.getUserSession().getPrincipalId(), disallowedRoles, null);
 288  
           //KIMServiceLocatorInternal.getRoleService().principalHasRole(principalId, roleIds, qualification)
 289  
           //boolean memberOfRole = isMemberOfRole
 290  
           final Collection<Authentication> auths = (Collection<Authentication>) userSession.retrieveObject(KEWConstants.AUTHENTICATIONS);
 291  
           if (auths != null) {
 292  
                   for (Authentication auth : auths) {
 293  
                           String role = auth.getAuthority();
 294  
                           if (disallowedRoles.contains(role)) {
 295  
                                   disallowed = true;
 296  
                           }
 297  
                           if (allowedRoles.contains(role)) {
 298  
                                   allowed = true;
 299  
                           }
 300  
                   }                  
 301  
           }
 302  
           
 303  
 
 304  
           if (allowed) {
 305  
                   // allowed takes precedence over disallowed
 306  
                   return true;
 307  
           } else if (disallowed) {
 308  
                   // we know that we haven't been allowed at this point, if we're disallowed than we're not authenticated
 309  
                   return false;
 310  
           } else if (allowedRoles.isEmpty()) {
 311  
                   // if allowedRoles is empty, that means that disallowed roles are not empty and we know because of the previous condition
 312  
                   // that the user has not been disallowed, therefore the user should be allowed if they aren't in the disallow set
 313  
                   return true;
 314  
           }
 315  
           return false;
 316  
   }
 317  
 */
 318  
 }