001 /** 002 * Copyright 2004-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.hr.time.roles; 017 018 import java.util.HashMap; 019 import java.util.HashSet; 020 import java.util.List; 021 import java.util.Map; 022 import java.util.Set; 023 024 import org.apache.commons.collections.CollectionUtils; 025 import org.apache.commons.collections.MapUtils; 026 import org.apache.commons.lang.StringUtils; 027 import org.kuali.hr.core.document.calendar.CalendarDocumentContract; 028 import org.kuali.hr.job.Job; 029 import org.kuali.hr.time.assignment.Assignment; 030 import org.kuali.hr.time.department.Department; 031 import org.kuali.hr.time.service.base.TkServiceLocator; 032 import org.kuali.hr.time.timesheet.TimesheetDocument; 033 import org.kuali.hr.time.util.TKContext; 034 import org.kuali.hr.time.util.TKUtils; 035 import org.kuali.hr.time.util.TkConstants; 036 import org.kuali.rice.krad.util.GlobalVariables; 037 038 /** 039 * TkUserRoles encapsulates the concept of roles for a single user and provides 040 * lookup methods for quick Role checking. This object will be stored in TkUser. 041 */ 042 public class TkUserRoles implements UserRoles { 043 private boolean synchronousAssignments = false; 044 private TkRole globalViewOnly; 045 private TkRole systemAdmin; 046 private String principalId; 047 048 private Map<String, TkRole> orgAdminRolesDept = new HashMap<String, TkRole>(); 049 private Map<String, TkRole> orgAdminRolesChart = new HashMap<String, TkRole>(); 050 private Map<Long, TkRole> approverRoles = new HashMap<Long, TkRole>(); 051 private Map<Long, TkRole> approverDelegateRoles = new HashMap<Long, TkRole>(); 052 private Map<Long, TkRole> reviewerRoles = new HashMap<Long, TkRole>(); 053 054 private Map<String, TkRole> deptViewOnlyRoles = new HashMap<String, TkRole>(); 055 private Set<String> activeAssignmentIds = new HashSet<String>(); 056 057 public static TkUserRoles getUserRoles(String principalId) { 058 List<TkRole> roles = TkServiceLocator.getTkRoleService().getRoles(principalId, TKUtils.getCurrentDate()); 059 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(principalId, TKUtils.getCurrentDate()); 060 061 return new TkUserRoles(principalId, roles, assignments); 062 } 063 064 /** 065 * Does not keep reference to the assignment objects. We just need the IDs, 066 * so in future refactoring, if we have a lighter weight call to obtain 067 * assignments, we could use that and modify this code. 068 * 069 * @param roles 070 * @param assignments 071 */ 072 private TkUserRoles(String principalId, List<TkRole> roles, List<Assignment> assignments) { 073 this.principalId = principalId; 074 setRoles(roles); 075 setAssignments(assignments); 076 } 077 078 @Override 079 public boolean isLocationAdmin() { 080 return CollectionUtils.isNotEmpty(getOrgAdminCharts()); 081 } 082 083 @Override 084 public boolean isDepartmentAdmin() { 085 return CollectionUtils.isNotEmpty(getOrgAdminDepartments()); 086 } 087 088 public String getPrincipalId() { 089 return principalId; 090 } 091 092 public void setPrincipalId(String principalId) { 093 this.principalId = principalId; 094 } 095 096 @Override 097 public Set<Long> getApproverWorkAreas() { 098 Set<Long> workAreas = new HashSet<Long>(); 099 workAreas.addAll(approverRoles.keySet()); 100 workAreas.addAll(approverDelegateRoles.keySet()); 101 return workAreas; 102 } 103 104 @Override 105 public Set<Long> getReviewerWorkAreas() { 106 return reviewerRoles.keySet(); 107 } 108 109 @Override 110 public Set<String> getOrgAdminDepartments() { 111 return orgAdminRolesDept.keySet(); 112 } 113 114 @Override 115 public Set<String> getOrgAdminCharts() { 116 return orgAdminRolesChart.keySet(); 117 } 118 119 @Override 120 public Set<String> getDepartmentViewOnlyDepartments() { 121 return deptViewOnlyRoles.keySet(); 122 } 123 124 /** 125 * Accessor method to obtain the Set of active Assignment ids for the 126 * current employee. 127 * 128 * @return a Set of active assignment IDs 129 */ 130 @Override 131 public Set<String> getActiveAssignmentIds() { 132 return activeAssignmentIds; 133 } 134 135 @Override 136 public boolean isSystemAdmin() { 137 return systemAdmin != null; 138 } 139 140 @Override 141 public boolean isGlobalViewOnly() { 142 return globalViewOnly != null; 143 } 144 145 public boolean isDeptViewOnly() { 146 return MapUtils.isNotEmpty(deptViewOnlyRoles); 147 } 148 149 @Override 150 public boolean isSynchronous() { 151 return synchronousAssignments; 152 } 153 154 public boolean isReviewer() { 155 return CollectionUtils.isNotEmpty(TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getReviewerWorkAreas()); 156 } 157 158 public boolean isApprover() { 159 return CollectionUtils.isNotEmpty(TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getApproverWorkAreas()); 160 } 161 162 /** 163 * Place the TkRole objects in the provided List into their appropriate 164 * buckets for fast lookup. 165 * 166 * @param roles A List of TkRole objects for the current user. 167 */ 168 public void setRoles(List<TkRole> roles) { 169 for (TkRole role : roles) { 170 if (role.getRoleName().equals(TkConstants.ROLE_TK_APPROVER)) { 171 approverRoles.put(role.getWorkArea(), role); 172 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_APPROVER_DELEGATE)) { 173 approverDelegateRoles.put(role.getWorkArea(), role); 174 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_LOCATION_ADMIN) || 175 role.getRoleName().equals(TkConstants.ROLE_LV_DEPT_ADMIN)) { 176 if (!StringUtils.isEmpty(role.getChart())) { 177 orgAdminRolesChart.put(role.getChart(), role); 178 List<Department> ds = TkServiceLocator.getDepartmentService().getDepartments(role.getChart(), TKUtils.getCurrentDate()); 179 for (Department d : ds) { 180 orgAdminRolesDept.put(d.getDept(), role); 181 } 182 } 183 } else if (StringUtils.equals(role.getRoleName(), TkConstants.ROLE_TK_LOCATION_VO)) { 184 if (!StringUtils.isEmpty(role.getChart())) { 185 List<Department> ds = TkServiceLocator.getDepartmentService().getDepartments(role.getChart(), TKUtils.getCurrentDate()); 186 for (Department dept : ds) { 187 deptViewOnlyRoles.put(dept.getDept(), role); 188 } 189 190 } 191 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_SYS_ADMIN)) { 192 systemAdmin = role; 193 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_DEPT_VO)) { 194 deptViewOnlyRoles.put(role.getDepartment(), role); 195 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_DEPT_ADMIN)) { 196 orgAdminRolesDept.put(role.getDepartment(), role); 197 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_GLOBAL_VO)) { 198 globalViewOnly = role; 199 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_REVIEWER)) { 200 reviewerRoles.put(role.getWorkArea(), role); 201 } 202 } 203 } 204 205 public void setAssignments(List<Assignment> assignments) { 206 for (Assignment a : assignments) { 207 activeAssignmentIds.add(a.getTkAssignmentId()); 208 if (a.isSynchronous()) 209 synchronousAssignments = true; 210 } 211 } 212 213 @Override 214 public boolean isActiveEmployee() { 215 return CollectionUtils.isNotEmpty(this.activeAssignmentIds); 216 } 217 218 @Override 219 public boolean isTimesheetApprover() { 220 return MapUtils.isNotEmpty(this.approverRoles) || MapUtils.isNotEmpty(this.approverDelegateRoles); 221 } 222 223 public boolean isTimesheetReviewer() { 224 return CollectionUtils.isNotEmpty(this.getReviewerWorkAreas()); 225 } 226 227 @Override 228 public boolean isAnyApproverActive() { 229 return MapUtils.isNotEmpty(this.approverRoles) || MapUtils.isNotEmpty(this.approverDelegateRoles); 230 } 231 232 //Todo: rename method. this is also used for leave calendar 233 @Override 234 public boolean isApproverForTimesheet(CalendarDocumentContract doc) { 235 boolean approver = false; 236 237 if (this.isSystemAdmin()) { 238 return true; 239 } 240 241 List<Assignment> assignments = doc.getAssignments(); 242 for (Assignment assignment : assignments) { 243 if (this.approverRoles.containsKey(assignment.getWorkArea()) || this.approverDelegateRoles.containsKey(assignment.getWorkArea())) { 244 return true; 245 } 246 } 247 248 return approver; 249 } 250 251 //Todo: rename method. this is also used for leave calendar 252 @Override 253 public boolean isApproverForTimesheet(String docId) { 254 boolean approver = false; 255 256 TimesheetDocument doc = TkServiceLocator.getTimesheetService().getTimesheetDocument(docId); 257 if (doc != null) 258 approver = isApproverForTimesheet(doc); 259 260 return approver; 261 } 262 263 @Override 264 public boolean isDocumentWritable(CalendarDocumentContract document) { 265 boolean writable = false; 266 267 // Quick escape. 268 if (document == null) 269 return writable; 270 271 // Sysadmin 272 writable = this.isSystemAdmin(); 273 // Owner (and not enroute/final) 274 writable |= (StringUtils.equals(this.principalId, document.getDocumentHeader().getPrincipalId()) 275 && (StringUtils.equals(TkConstants.ROUTE_STATUS.INITIATED, document.getDocumentHeader().getDocumentStatus()) || 276 StringUtils.equals(TkConstants.ROUTE_STATUS.SAVED, document.getDocumentHeader().getDocumentStatus()) || 277 (StringUtils.equals(TkConstants.ROUTE_STATUS.ENROUTE, document.getDocumentHeader().getDocumentStatus())))); 278 279 280 if (!writable) { 281 // Departmental View Only? || Reviewer || Org Admin || Approver 282 // (document object iteration) 283 List<Assignment> assignments = document.getAssignments(); 284 for (Assignment assignment : assignments) { 285 String dept = assignment.getDept(); 286 Long wa = assignment.getWorkArea(); 287 // Dept admins should not have write access 288 //writable |= this.orgAdminRolesDept.containsKey(dept); 289 writable |= this.approverRoles.containsKey(wa); 290 writable |= this.approverDelegateRoles.containsKey(wa); 291 writable |= this.reviewerRoles.containsKey(wa); 292 } 293 } 294 295 return writable; 296 } 297 298 @Override 299 public boolean isDocumentWritable(String documentId) { 300 return isDocumentWritable(TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId)); 301 } 302 303 @Override 304 public boolean isDocumentReadable(String documentId) { 305 boolean readable = false; 306 307 if (documentId != null) { 308 return isDocumentReadable(TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId)); 309 } 310 311 return readable; 312 } 313 314 @Override 315 public boolean isDocumentReadable(CalendarDocumentContract document) { 316 boolean readable = false; 317 318 // Quick escape. 319 if (document == null) 320 return readable; 321 322 // Sysadmin 323 readable = this.isSystemAdmin(); 324 // Owner 325 readable |= StringUtils.equals(this.principalId, document.getDocumentHeader().getPrincipalId()); 326 // Global VO 327 readable |= this.isGlobalViewOnly(); 328 329 if (!readable) { 330 // Departmental View Only? || Reviewer || Org Admin || Approver 331 // (document object iteration) 332 List<Assignment> assignments = document.getAssignments(); 333 for (Assignment assignment : assignments) { 334 String dept = assignment.getDept(); 335 Long wa = assignment.getWorkArea(); 336 337 readable |= this.orgAdminRolesDept.containsKey(dept); 338 readable |= this.approverRoles.containsKey(wa); 339 readable |= this.approverDelegateRoles.containsKey(wa); 340 readable |= this.reviewerRoles.containsKey(wa); 341 readable |= this.deptViewOnlyRoles.containsKey(dept); 342 readable |= this.reviewerRoles.containsKey(wa); 343 } 344 } 345 346 return readable; 347 } 348 349 private boolean isLocationAdmin(CalendarDocumentContract doc) { 350 for (Assignment assign : doc.getAssignments()) { 351 String location = assign.getJob().getLocation(); 352 return this.orgAdminRolesChart.containsKey(location); 353 } 354 return false; 355 } 356 357 private boolean isDepartmentAdmin(CalendarDocumentContract doc) { 358 for (Assignment assign : doc.getAssignments()) { 359 String dept = assign.getDept(); 360 return this.orgAdminRolesDept.containsKey(dept); 361 } 362 return false; 363 } 364 365 @Override 366 public boolean canSubmitTimesheet(CalendarDocumentContract doc) { 367 if (StringUtils.equals(TKContext.getPrincipalId(), doc.getDocumentHeader().getPrincipalId())) { 368 return true; 369 } 370 371 if (this.isApproverForTimesheet(doc)) { 372 return true; 373 } 374 375 //System admins can route the document as well as the employee 376 if (this.isSystemAdmin()) { 377 return true; 378 } 379 return false; 380 } 381 382 @Override 383 public boolean canSubmitTimesheet(String docId) { 384 TimesheetDocument doc = TkServiceLocator.getTimesheetService().getTimesheetDocument(docId); 385 return canSubmitTimesheet(doc); 386 } 387 388 @Override 389 public boolean isApproverForPerson(String principalId) { 390 List<Assignment> lstAssignment = TkServiceLocator.getAssignmentService().getAssignments(principalId, TKUtils.getCurrentDate()); 391 392 Set<Long> workAreas = getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getApproverWorkAreas(); 393 for (Assignment assignment : lstAssignment) { 394 if (workAreas.contains(assignment.getWorkArea())) { 395 return true; 396 } 397 } 398 399 return false; 400 401 } 402 403 @Override 404 public boolean isDepartmentAdminForPerson(String principalId) { 405 List<Job> jobs = TkServiceLocator.getJobService().getJobs(principalId,TKUtils.getCurrentDate()); 406 for (Job job : jobs) { 407 if (getOrgAdminDepartments().contains(job.getDept())) { 408 return true; 409 } 410 } 411 return false; 412 } 413 414 @Override 415 public boolean isDeptViewOnlyForPerson(String principalId) { 416 List<Job> jobs = TkServiceLocator.getJobService().getJobs(principalId,TKUtils.getCurrentDate()); 417 for (Job job : jobs) { 418 if (getDepartmentViewOnlyDepartments().contains(job.getDept())) { 419 return true; 420 } 421 } 422 return false; 423 } 424 425 @Override 426 public boolean isLocationAdminForPerson(String principalId) { 427 List<TkRole> roles = TkServiceLocator.getTkRoleService().getRoles(principalId, TKUtils.getCurrentDate()); 428 429 if (CollectionUtils.isNotEmpty(roles)) { 430 for (TkRole role : roles) { 431 if (this.getOrgAdminCharts().contains(role.getChart())) { 432 return true; 433 } 434 } 435 } 436 437 return false; 438 } 439 440 @Override 441 public boolean isTimesheetReviewerForPerson(String principalId) { 442 List<Assignment> lstAssignment = TkServiceLocator.getAssignmentService().getAssignments(principalId, TKUtils.getCurrentDate()); 443 444 for (Assignment assignment : lstAssignment) { 445 if (getReviewerWorkAreas().contains(assignment.getWorkArea())) { 446 return true; 447 } 448 } 449 return false; 450 } 451 }