001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.krad.uif.view; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.CoreApiServiceLocator; 020import org.kuali.rice.core.api.config.property.ConfigurationService; 021import org.kuali.rice.kim.api.KimConstants; 022import org.kuali.rice.kim.api.identity.Person; 023import org.kuali.rice.krad.bo.DataObjectAuthorizerBase; 024import org.kuali.rice.krad.datadictionary.AttributeSecurity; 025import org.kuali.rice.krad.datadictionary.parse.BeanTag; 026import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 027import org.kuali.rice.krad.uif.component.Component; 028import org.kuali.rice.krad.uif.component.ComponentSecurity; 029import org.kuali.rice.krad.uif.component.DataBinding; 030import org.kuali.rice.krad.uif.container.CollectionGroup; 031import org.kuali.rice.krad.uif.container.Group; 032import org.kuali.rice.krad.uif.element.Action; 033import org.kuali.rice.krad.uif.field.DataField; 034import org.kuali.rice.krad.uif.field.DataFieldSecurity; 035import org.kuali.rice.krad.uif.field.Field; 036import org.kuali.rice.krad.uif.field.FieldSecurity; 037import org.kuali.rice.krad.uif.util.ObjectPropertyUtils; 038import org.kuali.rice.krad.uif.widget.Widget; 039import org.kuali.rice.krad.util.KRADConstants; 040import org.kuali.rice.krad.util.KRADUtils; 041 042import java.util.HashMap; 043import java.util.HashSet; 044import java.util.Map; 045import java.util.Set; 046 047/** 048 * Implementation of {@link ViewAuthorizer} that verifies authorization with KIM permission checks 049 * 050 * <p> 051 * Each permission goes through one of the isAuthorized methods provided by 052 * {@link org.kuali.rice.krad.bo.DataObjectAuthorizer}, these in turn call {@link #addPermissionDetails(Object, java.util.Map)} 053 * and {@link #addRoleQualification(Object, java.util.Map)} for building the permission and role maps to send with 054 * the permission check. Subclasses can override these methods to add additional attributes 055 * </p> 056 * 057 * @author Kuali Rice Team (rice.collab@kuali.org) 058 */ 059@BeanTag(name = "viewAuthorizer") 060public class ViewAuthorizerBase extends DataObjectAuthorizerBase implements ViewAuthorizer { 061 private static final long serialVersionUID = -2687378084630965412L; 062 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ViewAuthorizerBase.class); 063 064 private ConfigurationService configurationService; 065 066 private RequestAuthorizationCache requestAuthorizationCache; 067 068 /** 069 * @see ViewAuthorizer#getActionFlags(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 070 * org.kuali.rice.kim.api.identity.Person, java.util.Set<java.lang.String>) 071 */ 072 public Set<String> getActionFlags(View view, ViewModel model, Person user, Set<String> actions) { 073 if (actions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT) && !canEditView(view, model, user)) { 074 actions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT); 075 } 076 077 return actions; 078 } 079 080 /** 081 * @see ViewAuthorizer#getEditModes(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 082 * org.kuali.rice.kim.api.identity.Person, java.util.Set<java.lang.String>) 083 */ 084 public Set<String> getEditModes(View view, ViewModel model, Person user, Set<String> editModes) { 085 Set<String> unauthorizedEditModes = new HashSet<String>(); 086 087 Object dataObjectForContext = getDataObjectContext(view, model); 088 089 // loop through supplied editModes and make sure KIM permission exists 090 for (String editMode : editModes) { 091 Map<String, String> additionalPermissionDetails = new HashMap<String, String>(); 092 additionalPermissionDetails.put(KimConstants.AttributeConstants.EDIT_MODE, editMode); 093 additionalPermissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, view.getId()); 094 boolean exists = permissionExistsByTemplate(dataObjectForContext, KRADConstants.KRAD_NAMESPACE, 095 KimConstants.PermissionTemplateNames.USE_VIEW, additionalPermissionDetails); 096 if (exists) { 097 boolean authorized = isAuthorizedByTemplate(dataObjectForContext, KRADConstants.KRAD_NAMESPACE, 098 KimConstants.PermissionTemplateNames.USE_VIEW, user.getPrincipalId(), 099 additionalPermissionDetails, null); 100 if (!authorized) { 101 unauthorizedEditModes.add(editMode); 102 } 103 } 104 } 105 editModes.removeAll(unauthorizedEditModes); 106 107 return editModes; 108 } 109 110 /** 111 * Checks for an open view permission for the view id, and if found verifies the user has that permission 112 * 113 * @see ViewAuthorizer#canOpenView(View, ViewModel, org.kuali.rice.kim.api.identity.Person) 114 */ 115 public boolean canOpenView(View view, ViewModel model, Person user) { 116 Map<String, String> additionalPermissionDetails = new HashMap<String, String>(); 117 additionalPermissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, view.getNamespaceCode()); 118 additionalPermissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, model.getViewId()); 119 120 if (permissionExistsByTemplate(model, KRADConstants.KRAD_NAMESPACE, 121 KimConstants.PermissionTemplateNames.OPEN_VIEW, additionalPermissionDetails)) { 122 return isAuthorizedByTemplate(model, KRADConstants.KRAD_NAMESPACE, 123 KimConstants.PermissionTemplateNames.OPEN_VIEW, user.getPrincipalId(), additionalPermissionDetails, 124 null); 125 } 126 127 return true; 128 } 129 130 /** 131 * Checks for an edit view permission for the view id, and if found verifies the user has that permission 132 * 133 * @see ViewAuthorizer#canEditView(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 134 * org.kuali.rice.kim.api.identity.Person) 135 */ 136 public boolean canEditView(View view, ViewModel model, Person user) { 137 Map<String, String> additionalPermissionDetails = new HashMap<String, String>(); 138 additionalPermissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, view.getNamespaceCode()); 139 additionalPermissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, model.getViewId()); 140 141 if (permissionExistsByTemplate(model, KRADConstants.KRAD_NAMESPACE, 142 KimConstants.PermissionTemplateNames.EDIT_VIEW, additionalPermissionDetails)) { 143 return isAuthorizedByTemplate(model, KRADConstants.KRAD_NAMESPACE, 144 KimConstants.PermissionTemplateNames.EDIT_VIEW, user.getPrincipalId(), additionalPermissionDetails, 145 null); 146 } 147 148 return true; 149 } 150 151 /** 152 * @see ViewAuthorizer#canUnmaskField(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 153 * org.kuali.rice.krad.uif.field.DataField, java.lang.String, org.kuali.rice.kim.api.identity.Person) 154 */ 155 public boolean canUnmaskField(View view, ViewModel model, DataField field, String propertyName, Person user) { 156 if (field.getDataFieldSecurity() == null) { 157 return true; 158 } 159 160 // check mask authz flag is set 161 AttributeSecurity attributeSecurity = field.getDataFieldSecurity().getAttributeSecurity(); 162 if (attributeSecurity == null || !attributeSecurity.isMask()) { 163 return true; 164 } 165 166 // for non-production environments the ability to unmask can be disabled by a system parameter 167 if (isNonProductionEnvAndUnmaskingTurnedOff()) { 168 return false; 169 } 170 171 Object dataObjectForContext = getDataObjectContext(view, model); 172 173 Map<String, String> permissionDetails = new HashMap<String, String>(); 174 permissionDetails = KRADUtils.getNamespaceAndComponentSimpleName(dataObjectForContext.getClass()); 175 permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, propertyName); 176 // TODO: check for namespace, component, attribute override on attribute security 177 178 if (field.getComponentSecurity().getAdditionalPermissionDetails() != null) { 179 permissionDetails.putAll(field.getComponentSecurity().getAdditionalPermissionDetails()); 180 } 181 182 Map<String, String> roleQualifications = new HashMap<String, String>(); 183 if (field.getComponentSecurity().getAdditionalRoleQualifiers() != null) { 184 roleQualifications.putAll(field.getComponentSecurity().getAdditionalRoleQualifiers()); 185 } 186 187 return isAuthorizedByTemplate(dataObjectForContext, KRADConstants.KNS_NAMESPACE, 188 KimConstants.PermissionTemplateNames.FULL_UNMASK_FIELD, user.getPrincipalId(), permissionDetails, 189 roleQualifications); 190 } 191 192 /** 193 * @see ViewAuthorizer#canPartialUnmaskField(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 194 * org.kuali.rice.krad.uif.field.DataField, java.lang.String, org.kuali.rice.kim.api.identity.Person) 195 */ 196 public boolean canPartialUnmaskField(View view, ViewModel model, DataField field, String propertyName, 197 Person user) { 198 if (field.getDataFieldSecurity() == null) { 199 return true; 200 } 201 202 // check partial mask authz flag is set 203 AttributeSecurity attributeSecurity = field.getDataFieldSecurity().getAttributeSecurity(); 204 if (attributeSecurity == null || !attributeSecurity.isPartialMask()) { 205 return true; 206 } 207 208 // for non-production environments the ability to unmask can be disabled by a system parameter 209 if (isNonProductionEnvAndUnmaskingTurnedOff()) { 210 return false; 211 } 212 213 Object dataObjectForContext = getDataObjectContext(view, model); 214 215 Map<String, String> permissionDetails = new HashMap<String, String>(); 216 permissionDetails = KRADUtils.getNamespaceAndComponentSimpleName(dataObjectForContext.getClass()); 217 permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, propertyName); 218 // TODO: check for namespace, component, attribute override on attribute security 219 220 if (field.getComponentSecurity().getAdditionalPermissionDetails() != null) { 221 permissionDetails.putAll(field.getComponentSecurity().getAdditionalPermissionDetails()); 222 } 223 224 Map<String, String> roleQualifications = new HashMap<String, String>(); 225 if (field.getComponentSecurity().getAdditionalRoleQualifiers() != null) { 226 roleQualifications.putAll(field.getComponentSecurity().getAdditionalRoleQualifiers()); 227 } 228 229 return isAuthorizedByTemplate(dataObjectForContext, KRADConstants.KNS_NAMESPACE, 230 KimConstants.PermissionTemplateNames.PARTIAL_UNMASK_FIELD, user.getPrincipalId(), permissionDetails, 231 roleQualifications); 232 } 233 234 /** 235 * @see ViewAuthorizer#canEditField(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 236 * org.kuali.rice.krad.uif.field.Field, java.lang.String, org.kuali.rice.kim.api.identity.Person) 237 */ 238 public boolean canEditField(View view, ViewModel model, Field field, String propertyName, Person user) { 239 ComponentSecurity componentSecurity = field.getComponentSecurity(); 240 241 // check component security exists 242 if (componentSecurity == null) { 243 return true; 244 } 245 246 // first check hide flag is set (lower precedence) 247 if (componentSecurity.isEditAuthz() == null && !isDataFieldAttributeSecurityHide(field)) { 248 return true; 249 } 250 251 // then check edit authz is set (higher precedence) 252 if (componentSecurity.isEditAuthz() != null && !componentSecurity.isEditAuthz().booleanValue()) { 253 return true; 254 } 255 256 return isAuthorizedByTemplate(view, field, model, KimConstants.PermissionTemplateNames.EDIT_FIELD, user, null, 257 null, false); 258 } 259 260 /** 261 * @see ViewAuthorizer#canViewField(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 262 * org.kuali.rice.krad.uif.field.Field, java.lang.String, org.kuali.rice.kim.api.identity.Person) 263 */ 264 public boolean canViewField(View view, ViewModel model, Field field, String propertyName, Person user) { 265 ComponentSecurity componentSecurity = field.getComponentSecurity(); 266 267 // check component security exists 268 if (componentSecurity == null) { 269 return true; 270 } 271 272 // first check hide flag is set (lower precedence) 273 if (componentSecurity.isViewAuthz() == null && !isDataFieldAttributeSecurityHide(field)) { 274 return true; 275 } 276 277 // then check view authz is set (higher precedence) 278 if (componentSecurity.isViewAuthz() != null && !componentSecurity.isViewAuthz().booleanValue()) { 279 return true; 280 } 281 282 return isAuthorizedByTemplate(view, field, model, KimConstants.PermissionTemplateNames.VIEW_FIELD, user, null, 283 null, false); 284 } 285 286 /** 287 * @see ViewAuthorizer#canEditGroup(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 288 * org.kuali.rice.krad.uif.container.Group, java.lang.String, org.kuali.rice.kim.api.identity.Person) 289 */ 290 public boolean canEditGroup(View view, ViewModel model, Group group, String groupId, Person user) { 291 ComponentSecurity componentSecurity = group.getComponentSecurity(); 292 293 // check component security exists 294 if (componentSecurity == null) { 295 return true; 296 } 297 298 // check edit group authz flag is set 299 if (componentSecurity.isEditAuthz() == null || !componentSecurity.isEditAuthz().booleanValue()) { 300 return true; 301 } 302 303 return isAuthorizedByTemplate(view, group, model, KimConstants.PermissionTemplateNames.EDIT_GROUP, user, null, 304 null, false); 305 } 306 307 /** 308 * @see ViewAuthorizer#canViewGroup(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 309 * org.kuali.rice.krad.uif.container.Group, java.lang.String, org.kuali.rice.kim.api.identity.Person) 310 */ 311 public boolean canViewGroup(View view, ViewModel model, Group group, String groupId, Person user) { 312 ComponentSecurity componentSecurity = group.getComponentSecurity(); 313 314 // check component security exists 315 if (componentSecurity == null) { 316 return true; 317 } 318 319 // check view group authz flag is set 320 if (componentSecurity.isViewAuthz() == null || !componentSecurity.isViewAuthz().booleanValue()) { 321 return true; 322 } 323 324 return isAuthorizedByTemplate(view, group, model, KimConstants.PermissionTemplateNames.VIEW_GROUP, user, null, 325 null, false); 326 } 327 328 /** 329 * @see ViewAuthorizer#canEditWidget(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 330 * org.kuali.rice.krad.uif.widget.Widget, java.lang.String, org.kuali.rice.kim.api.identity.Person) 331 */ 332 public boolean canEditWidget(View view, ViewModel model, Widget widget, String widgetId, Person user) { 333 ComponentSecurity componentSecurity = widget.getComponentSecurity(); 334 335 // check component security exists 336 if (componentSecurity == null) { 337 return true; 338 } 339 340 // check edit widget authz flag is set 341 if (componentSecurity.isEditAuthz() == null || !componentSecurity.isEditAuthz().booleanValue()) { 342 return true; 343 } 344 345 return isAuthorizedByTemplate(view, widget, model, KimConstants.PermissionTemplateNames.EDIT_WIDGET, user, null, 346 null, false); 347 } 348 349 /** 350 * @see ViewAuthorizer#canViewWidget(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 351 * org.kuali.rice.krad.uif.widget.Widget, java.lang.String, org.kuali.rice.kim.api.identity.Person) 352 */ 353 public boolean canViewWidget(View view, ViewModel model, Widget widget, String widgetId, Person user) { 354 ComponentSecurity componentSecurity = widget.getComponentSecurity(); 355 356 // check component security exists 357 if (componentSecurity == null) { 358 return true; 359 } 360 361 // check view widget authz flag is set 362 if (componentSecurity.isViewAuthz() == null || !componentSecurity.isViewAuthz().booleanValue()) { 363 return true; 364 } 365 366 return isAuthorizedByTemplate(view, widget, model, KimConstants.PermissionTemplateNames.VIEW_WIDGET, user, null, 367 null, false); 368 } 369 370 /** 371 * @see ViewAuthorizer#canPerformAction(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel, 372 * org.kuali.rice.krad.uif.element.Action, java.lang.String, java.lang.String, org.kuali.rice.kim.api.identity.Person) 373 */ 374 public boolean canPerformAction(View view, ViewModel model, Action action, String actionEvent, 375 String actionId, Person user) { 376 // check action authz flag is set 377 if ((action.getActionSecurity() == null) || !action.getActionSecurity().isPerformActionAuthz()) { 378 return true; 379 } 380 381 Map<String, String> additionalPermissionDetails = new HashMap<String, String>(); 382 if (StringUtils.isNotBlank(actionEvent)) { 383 additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_EVENT, actionEvent); 384 } 385 386 return isAuthorizedByTemplate(view, action, model, KimConstants.PermissionTemplateNames.PERFORM_ACTION, 387 user, additionalPermissionDetails, null, false); 388 } 389 390 public boolean canEditLine(View view, ViewModel model, CollectionGroup collectionGroup, 391 String collectionPropertyName, Object line, Person user) { 392 // check edit line authz flag is set 393 if ((collectionGroup.getCollectionGroupSecurity() == null) || !collectionGroup.getCollectionGroupSecurity() 394 .isEditLineAuthz()) { 395 return true; 396 } 397 398 return isAuthorizedByTemplate(view, collectionGroup, model, KimConstants.PermissionTemplateNames.EDIT_LINE, 399 user, null, null, false); 400 } 401 402 public boolean canViewLine(View view, ViewModel model, CollectionGroup collectionGroup, 403 String collectionPropertyName, Object line, Person user) { 404 // check view line authz flag is set 405 if ((collectionGroup.getCollectionGroupSecurity() == null) || !collectionGroup.getCollectionGroupSecurity() 406 .isViewLineAuthz()) { 407 return true; 408 } 409 410 return isAuthorizedByTemplate(view, collectionGroup, model, KimConstants.PermissionTemplateNames.VIEW_LINE, 411 user, null, null, false); 412 } 413 414 public boolean canEditLineField(View view, ViewModel model, CollectionGroup collectionGroup, 415 String collectionPropertyName, Object line, Field field, String propertyName, Person user) { 416 FieldSecurity fieldSecurity = field.getFieldSecurity(); 417 418 // check field security exists 419 if (fieldSecurity == null) { 420 return true; 421 } 422 423 // first check hide flag is set (lower precedence) 424 if (fieldSecurity.isEditInLineAuthz() == null && !isDataFieldAttributeSecurityHide(field)) { 425 return true; 426 } 427 428 // then check edit line field authz flag is set (higher precedence) 429 if (fieldSecurity.isEditInLineAuthz() != null && !fieldSecurity.isEditInLineAuthz().booleanValue()) { 430 return true; 431 } 432 433 Map<String, String> additionalPermissionDetails = new HashMap<String, String>(); 434 additionalPermissionDetails.put(KimConstants.AttributeConstants.GROUP_ID, collectionGroup.getId()); 435 additionalPermissionDetails.put(KimConstants.AttributeConstants.COLLECTION_PROPERTY_NAME, 436 collectionGroup.getPropertyName()); 437 438 return isAuthorizedByTemplate(view, field, model, 439 KimConstants.PermissionTemplateNames.EDIT_LINE_FIELD, user, additionalPermissionDetails, null, false); 440 } 441 442 public boolean canViewLineField(View view, ViewModel model, CollectionGroup collectionGroup, 443 String collectionPropertyName, Object line, Field field, String propertyName, Person user) { 444 FieldSecurity fieldSecurity = field.getFieldSecurity(); 445 446 // check field security exists 447 if (fieldSecurity == null) { 448 return true; 449 } 450 451 // first check hide flag is set (lower precedence) 452 if (fieldSecurity.isViewInLineAuthz() == null && !isDataFieldAttributeSecurityHide(field)) { 453 return true; 454 } 455 456 // then check view line field authz flag is set (higher precedence) 457 if (fieldSecurity.isViewInLineAuthz() != null && !fieldSecurity.isViewInLineAuthz().booleanValue()) { 458 return true; 459 } 460 461 Map<String, String> additionalPermissionDetails = new HashMap<String, String>(); 462 additionalPermissionDetails.put(KimConstants.AttributeConstants.GROUP_ID, collectionGroup.getId()); 463 additionalPermissionDetails.put(KimConstants.AttributeConstants.COLLECTION_PROPERTY_NAME, 464 collectionGroup.getPropertyName()); 465 466 return isAuthorizedByTemplate(view, field, model, 467 KimConstants.PermissionTemplateNames.VIEW_LINE_FIELD, user, additionalPermissionDetails, null, false); 468 } 469 470 public boolean canPerformLineAction(View view, ViewModel model, CollectionGroup collectionGroup, 471 String collectionPropertyName, Object line, Action action, String actionEvent, String actionId, 472 Person user) { 473 // check perform line action authz flag is set 474 if ((action.getActionSecurity() == null) || !action.getActionSecurity().isPerformLineActionAuthz()) { 475 return true; 476 } 477 478 Map<String, String> additionalPermissionDetails = new HashMap<String, String>(); 479 additionalPermissionDetails.put(KimConstants.AttributeConstants.GROUP_ID, collectionGroup.getId()); 480 additionalPermissionDetails.put(KimConstants.AttributeConstants.COLLECTION_PROPERTY_NAME, 481 collectionGroup.getPropertyName()); 482 if (StringUtils.isNotBlank(actionEvent)) { 483 additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_EVENT, actionEvent); 484 } 485 486 return isAuthorizedByTemplate(view, action, model, 487 KimConstants.PermissionTemplateNames.PERFORM_LINE_ACTION, user, additionalPermissionDetails, null, 488 false); 489 } 490 491 /** 492 * Retrieves the object from the model that is used as the context for permission checks 493 * 494 * <p> 495 * Used to derive namespace and component details. Subclasses can override to return the object to be used 496 * </p> 497 * 498 * @param view view instance the permission checks are being done for 499 * @param model model object containing the data and from which the data object should be pulled 500 * @return data object instance to use 501 */ 502 protected Object getDataObjectContext(View view, ViewModel model) { 503 Object dataObject = model; 504 505 if (StringUtils.isNotBlank(view.getDefaultBindingObjectPath())) { 506 Object defaultObject = ObjectPropertyUtils.getPropertyValue(model, view.getDefaultBindingObjectPath()); 507 if (defaultObject != null) { 508 dataObject = defaultObject; 509 } 510 } 511 512 return dataObject; 513 } 514 515 /** 516 * Builds the permission details map for a field which includes the component namespace, component name, and 517 * field id, in addition to property name for data binding fields 518 * 519 * @param view view instance the field belongs to 520 * @param dataObject default object from the data model (used for subclasses to build details) 521 * @param field field instance the details are being built for 522 * @return permission details for the field 523 */ 524 protected Map<String, String> getFieldPermissionDetails(View view, Object dataObject, Field field) { 525 Map<String, String> permissionDetails = new HashMap<String, String>(); 526 527 permissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, view.getNamespaceCode()); 528 permissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, view.getId()); 529 permissionDetails.put(KimConstants.AttributeConstants.FIELD_ID, field.getId()); 530 531 if (field instanceof DataBinding) { 532 permissionDetails.put(KimConstants.AttributeConstants.PROPERTY_NAME, 533 ((DataBinding) field).getPropertyName()); 534 } 535 536 return permissionDetails; 537 } 538 539 /** 540 * Builds the permission details map for a group which includes the component namespace, component name, and 541 * group id, in addition to property name for collection groups 542 * 543 * @param view view instance the group belongs to 544 * @param dataObject default object from the data model (used for subclasses to build details) 545 * @param group group instance the details are being built for 546 * @return permission details for the group 547 */ 548 protected Map<String, String> getGroupPermissionDetails(View view, Object dataObject, Group group) { 549 Map<String, String> permissionDetails = new HashMap<String, String>(); 550 551 permissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, view.getNamespaceCode()); 552 permissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, view.getId()); 553 permissionDetails.put(KimConstants.AttributeConstants.GROUP_ID, group.getId()); 554 555 if (group instanceof CollectionGroup) { 556 permissionDetails.put(KimConstants.AttributeConstants.COLLECTION_PROPERTY_NAME, 557 ((CollectionGroup) group).getPropertyName()); 558 } 559 560 return permissionDetails; 561 } 562 563 /** 564 * Builds the permission details map for a widget which includes the namespace, view id, and 565 * widget id 566 * 567 * @param view view instance the widget belongs to 568 * @param dataObject default object from the data model (used for subclasses to build details) 569 * @param widget group instance the details are being built for 570 * @return permission details for group 571 */ 572 protected Map<String, String> getWidgetPermissionDetails(View view, Object dataObject, Widget widget) { 573 Map<String, String> permissionDetails = new HashMap<String, String>(); 574 575 permissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, view.getNamespaceCode()); 576 permissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, view.getId()); 577 permissionDetails.put(KimConstants.AttributeConstants.WIDGET_ID, widget.getId()); 578 579 return permissionDetails; 580 } 581 582 /** 583 * Builds the permission details map for an action which includes the namespace, view id, and 584 * action id and event 585 * 586 * @param view view instance the widget belongs to 587 * @param dataObject default object from the data model (used for subclasses to build details) 588 * @param action action instance the details are being built for 589 * @return permission details for action 590 */ 591 protected Map<String, String> getActionPermissionDetails(View view, Object dataObject, Action action) { 592 Map<String, String> permissionDetails = new HashMap<String, String>(); 593 594 permissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, view.getNamespaceCode()); 595 permissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, view.getId()); 596 permissionDetails.put(KimConstants.AttributeConstants.FIELD_ID, action.getId()); 597 598 return permissionDetails; 599 } 600 601 /** 602 * Performs a permission check for the given template name in the context of the given view and component 603 * 604 * <p> 605 * First standard permission details are added based on the type of component the permission check is being 606 * done for. 607 * Then the {@link ComponentSecurity} of the given component is used to pick up additional permission details and 608 * role qualifiers. 609 * </p> 610 * 611 * @param view view instance the component belongs to 612 * @param component component instance the permission check is being done for 613 * @param model object containing the views data 614 * @param permissionTemplateName template name for the permission to check 615 * @param user user to perform the authorization for 616 * @param additionalPermissionDetails additional key/value pairs to pass with the permission details 617 * @param additionalRoleQualifications additional key/value paris to pass with the role qualifiers 618 * @param checkPermissionExistence boolean indicating whether the existence of the permission should be checked 619 * before performing the authorization 620 * @return whether or not the user has authorization; this will be the case if the user has been 621 * granted the permission or checkPermissionExistence is true and the permission does not exist 622 */ 623 protected boolean isAuthorizedByTemplate(View view, Component component, ViewModel model, 624 String permissionTemplateName, Person user, Map<String, String> additionalPermissionDetails, 625 Map<String, String> additionalRoleQualifications, boolean checkPermissionExistence) { 626 Map<String, String> permissionDetails = new HashMap<String, String>(); 627 Map<String, String> roleQualifications = new HashMap<String, String>(); 628 629 if (additionalPermissionDetails != null) { 630 permissionDetails.putAll(additionalPermissionDetails); 631 } 632 633 if (additionalRoleQualifications != null) { 634 roleQualifications.putAll(additionalRoleQualifications); 635 } 636 637 Object dataObjectForContext = getDataObjectContext(view, model); 638 639 // add permission details depending on the type of component 640 if (component instanceof Field) { 641 permissionDetails.putAll(getFieldPermissionDetails(view, dataObjectForContext, (Field) component)); 642 } else if (component instanceof Group) { 643 permissionDetails.putAll(getGroupPermissionDetails(view, dataObjectForContext, (Group) component)); 644 } else if (component instanceof Widget) { 645 permissionDetails.putAll(getWidgetPermissionDetails(view, dataObjectForContext, (Widget) component)); 646 } else if (component instanceof Action) { 647 permissionDetails.putAll(getActionPermissionDetails(view, dataObjectForContext, (Action) component)); 648 } 649 650 // pick up additional attributes and overrides from component security 651 ComponentSecurity componentSecurity = component.getComponentSecurity(); 652 653 // add configured overrides 654 if (componentSecurity != null) { 655 if (StringUtils.isNotBlank(componentSecurity.getNamespaceAttribute())) { 656 permissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, 657 componentSecurity.getNamespaceAttribute()); 658 } 659 660 if (StringUtils.isNotBlank(componentSecurity.getComponentAttribute())) { 661 permissionDetails.put(KimConstants.AttributeConstants.COMPONENT_NAME, 662 componentSecurity.getComponentAttribute()); 663 } 664 665 if (StringUtils.isNotBlank(componentSecurity.getIdAttribute())) { 666 if (component instanceof Field) { 667 permissionDetails.put(KimConstants.AttributeConstants.FIELD_ID, componentSecurity.getIdAttribute()); 668 } else if (component instanceof Group) { 669 permissionDetails.put(KimConstants.AttributeConstants.GROUP_ID, componentSecurity.getIdAttribute()); 670 } else if (component instanceof Widget) { 671 permissionDetails.put(KimConstants.AttributeConstants.WIDGET_ID, 672 componentSecurity.getIdAttribute()); 673 } 674 } 675 676 if (componentSecurity.getAdditionalPermissionDetails() != null) { 677 permissionDetails.putAll(componentSecurity.getAdditionalPermissionDetails()); 678 } 679 680 if (componentSecurity.getAdditionalRoleQualifiers() != null) { 681 roleQualifications.putAll(componentSecurity.getAdditionalRoleQualifiers()); 682 } 683 } 684 685 boolean result = true; 686 if (!checkPermissionExistence || (checkPermissionExistence && permissionExistsByTemplate(dataObjectForContext, 687 KRADConstants.KRAD_NAMESPACE, permissionTemplateName, permissionDetails))) { 688 result = isAuthorizedByTemplate(dataObjectForContext, KRADConstants.KRAD_NAMESPACE, permissionTemplateName, 689 user.getPrincipalId(), permissionDetails, roleQualifications); 690 691 if (LOG.isDebugEnabled()) { 692 LOG.debug("Performed permission check for: " + permissionTemplateName + " and got result: " + result); 693 } 694 } 695 696 return result; 697 } 698 699 /** 700 * Indicates whether the environment is non production and unmasking is not enabled by system parameter 701 * 702 * @return true if unmasking is turned off, false if unmasking is allowed 703 */ 704 private boolean isNonProductionEnvAndUnmaskingTurnedOff() { 705 return !getConfigurationService().getPropertyValueAsString(KRADConstants.PROD_ENVIRONMENT_CODE_KEY). 706 equalsIgnoreCase(getConfigurationService().getPropertyValueAsString(KRADConstants.ENVIRONMENT_KEY)) 707 && !getConfigurationService().getPropertyValueAsBoolean(KRADConstants.ENABLE_NONPRODUCTION_UNMASKING); 708 } 709 710 /** 711 * Determines whether {@code AttributeSecurity} is set on the {@code DataField} and if it is, whether its hide 712 * attribute is enabled. 713 * 714 * @param field the field to check for the hide attribute 715 * 716 * @return true if the hide attribute is enabled, false otherwise 717 */ 718 private boolean isDataFieldAttributeSecurityHide(Field field) { 719 if (field instanceof DataField) { 720 DataField dataField = (DataField) field; 721 DataFieldSecurity dataFieldSecurity = dataField.getDataFieldSecurity(); 722 723 if (dataFieldSecurity == null) { 724 return false; 725 } 726 727 if (dataFieldSecurity.getAttributeSecurity() == null || !dataFieldSecurity.getAttributeSecurity().isHide()) { 728 return false; 729 } 730 731 return true; 732 } else { 733 return false; 734 } 735 } 736 737 @BeanTagAttribute(name="configurationService",type= BeanTagAttribute.AttributeType.SINGLEBEAN) 738 protected ConfigurationService getConfigurationService() { 739 if (configurationService == null) { 740 return CoreApiServiceLocator.getKualiConfigurationService(); 741 } 742 return configurationService; 743 } 744 745 public void setConfigurationService(ConfigurationService configurationService) { 746 this.configurationService = configurationService; 747 } 748 749 protected RequestAuthorizationCache getRequestAuthorizationCache() { 750 return requestAuthorizationCache; 751 } 752 753 /** 754 * {@inheritDoc} 755 */ 756 @Override 757 public void setRequestAuthorizationCache(RequestAuthorizationCache requestAuthorizationCache) { 758 this.requestAuthorizationCache = requestAuthorizationCache; 759 } 760 761}