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