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 }