001/** 002 * Copyright 2005-2018 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.lifecycle.model; 017 018import org.kuali.rice.kim.api.identity.Person; 019import org.kuali.rice.krad.datadictionary.AttributeSecurity; 020import org.kuali.rice.krad.uif.component.Component; 021import org.kuali.rice.krad.uif.component.DataBinding; 022import org.kuali.rice.krad.uif.container.Group; 023import org.kuali.rice.krad.uif.element.Action; 024import org.kuali.rice.krad.uif.field.ActionField; 025import org.kuali.rice.krad.uif.field.DataField; 026import org.kuali.rice.krad.uif.field.Field; 027import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; 028import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleTaskBase; 029import org.kuali.rice.krad.uif.view.View; 030import org.kuali.rice.krad.uif.view.ViewAuthorizer; 031import org.kuali.rice.krad.uif.view.ViewModel; 032import org.kuali.rice.krad.uif.view.ViewPresentationController; 033import org.kuali.rice.krad.uif.widget.Widget; 034import org.kuali.rice.krad.util.GlobalVariables; 035 036/** 037 * Apply authorization and presentation logic for the component. 038 * 039 * @author Kuali Rice Team (rice.collab@kuali.org) 040 */ 041public class ApplyAuthAndPresentationLogicTask extends ViewLifecycleTaskBase<Component> { 042 043 /** 044 * Default constructor. 045 */ 046 public ApplyAuthAndPresentationLogicTask() { 047 super(Component.class); 048 } 049 050 /** 051 * Invokes the view's configured {@link ViewAuthorizer} and {@link ViewPresentationController} 052 * to set state of the component 053 * 054 * <p> 055 * The following authorization is done here: Fields: edit, view, required, mask, and partial 056 * mask Groups: edit and view Actions: take action 057 * </p> 058 * 059 * <p> 060 * Note additional checks are also done for fields that are part of a collection group. This 061 * authorization is found in {@link org.kuali.rice.krad.uif.container.CollectionGroupBuilder} 062 * </p> 063 * 064 * @see org.kuali.rice.krad.uif.lifecycle.ViewLifecycleTaskBase#performLifecycleTask() 065 */ 066 @Override 067 protected void performLifecycleTask() { 068 ViewModel model = (ViewModel) ViewLifecycle.getModel(); 069 Component component = (Component) getElementState().getElement(); 070 View view = ViewLifecycle.getView(); 071 ViewPresentationController presentationController = view.getPresentationController(); 072 ViewAuthorizer authorizer = view.getAuthorizer(); 073 074 // if user session is not established cannot perform authorization 075 if (GlobalVariables.getUserSession() == null) { 076 return; 077 } 078 079 Person user = GlobalVariables.getUserSession().getPerson(); 080 081 // if component not flagged for render no need to check auth and controller logic 082 if (!component.isRender()) { 083 return; 084 } 085 086 // check top level view edit authorization 087 if (component instanceof View) { 088 if (!Boolean.TRUE.equals(view.getReadOnly())) { 089 if (model.isCanEditView() == null) { 090 boolean canEditView = authorizer.canEditView(view, model, user); 091 if (canEditView) { 092 canEditView = presentationController.canEditView(view, model); 093 } 094 view.setReadOnly(Boolean.valueOf(!canEditView)); 095 model.setCanEditView(Boolean.valueOf(canEditView)); 096 } else { 097 view.setReadOnly(!model.isCanEditView()); 098 } 099 } 100 } 101 102 // perform group authorization and presentation logic 103 else if (component instanceof Group) { 104 Group group = (Group) component; 105 106 // if group is not hidden, do authorization for viewing the group 107 if (!group.isHidden()) { 108 boolean canViewGroup = authorizer.canViewGroup(view, model, group, group.getId(), user); 109 if (canViewGroup) { 110 canViewGroup = presentationController.canViewGroup(view, model, group, group.getId()); 111 } 112 group.setHidden(!canViewGroup); 113 group.setRender(canViewGroup); 114 } 115 116 // if group is editable, do authorization for editing the group 117 if (!Boolean.TRUE.equals(group.getReadOnly())) { 118 boolean canEditGroup = authorizer.canEditGroup(view, model, group, group.getId(), user); 119 if (canEditGroup) { 120 canEditGroup = presentationController.canEditGroup(view, model, group, group.getId()); 121 } 122 group.setReadOnly(!canEditGroup); 123 } 124 } 125 126 // perform field authorization and presentation logic 127 else if (component instanceof Field && !(component instanceof ActionField)) { 128 Field field = (Field) component; 129 130 String propertyName = null; 131 if (field instanceof DataBinding) { 132 propertyName = ((DataBinding) field).getPropertyName(); 133 } 134 135 // if field is not hidden, do authorization for viewing the field 136 if (!field.isHidden()) { 137 boolean canViewField = authorizer.canViewField(view, model, field, propertyName, user); 138 if (canViewField) { 139 canViewField = presentationController.canViewField(view, model, field, propertyName); 140 } 141 field.setHidden(!canViewField); 142 field.setRender(canViewField); 143 } 144 145 // if field is not readOnly, check edit authorization 146 if (!Boolean.TRUE.equals(field.getReadOnly())) { 147 // check field edit authorization 148 boolean canEditField = authorizer.canEditField(view, model, field, propertyName, user); 149 if (canEditField) { 150 canEditField = presentationController.canEditField(view, model, field, propertyName); 151 } 152 field.setReadOnly(!canEditField); 153 } 154 155 // if field is not already required, invoke presentation logic to determine if it should be 156 if ((field.getRequired() == null) || !field.getRequired().booleanValue()) { 157 // boolean fieldIsRequired = 158 presentationController.fieldIsRequired(view, model, field, propertyName); 159 } 160 161 if (field instanceof DataField) { 162 DataField dataField = (DataField) field; 163 164 // check for masking and mask authorization 165 boolean canUnmaskValue = authorizer.canUnmaskField(view, model, dataField, dataField.getPropertyName(), 166 user); 167 boolean canPartiallyUnmaskValue = authorizer.canPartialUnmaskField(view, model, dataField, 168 dataField.getPropertyName(), user); 169 boolean isMasked = isMaskField(dataField); 170 boolean isPartialMask = isPartialMaskField(dataField); 171 172 if (isMasked && !canUnmaskValue) { 173 dataField.setApplyMask(true); 174 dataField.setMaskFormatter(dataField.getDataFieldSecurity().getAttributeSecurity(). 175 getMaskFormatter()); 176 } 177 else if(isMasked && canUnmaskValue) { 178 // do not mask 179 } 180 else if (isPartialMask && !canPartiallyUnmaskValue ) { 181 dataField.setApplyMask(true); 182 dataField.setMaskFormatter( 183 dataField.getDataFieldSecurity().getAttributeSecurity().getPartialMaskFormatter()); 184 } 185 } 186 } 187 188 // perform action authorization and presentation logic 189 else if (component instanceof ActionField || component instanceof Action) { 190 Action action = null; 191 if (component instanceof ActionField) { 192 action = ((ActionField) component).getAction(); 193 } else { 194 action = (Action) component; 195 } 196 197 boolean canTakeAction = authorizer.canPerformAction(view, model, action, action.getActionEvent(), 198 action.getId(), user); 199 if (canTakeAction) { 200 canTakeAction = presentationController.canPerformAction(view, model, action, action.getActionEvent(), 201 action.getId()); 202 } 203 action.setRender(canTakeAction); 204 } 205 206 // perform widget authorization and presentation logic 207 else if (component instanceof Widget) { 208 Widget widget = (Widget) component; 209 210 // if widget is not hidden, do authorization for viewing the widget 211 if (!widget.isHidden()) { 212 boolean canViewWidget = authorizer.canViewWidget(view, model, widget, widget.getId(), user); 213 if (canViewWidget) { 214 canViewWidget = presentationController.canViewWidget(view, model, widget, widget.getId()); 215 } 216 widget.setHidden(!canViewWidget); 217 widget.setRender(canViewWidget); 218 } 219 220 // if widget is not readOnly, check edit authorization 221 if (!Boolean.TRUE.equals(widget.getReadOnly())) { 222 boolean canEditWidget = authorizer.canEditWidget(view, model, widget, widget.getId(), user); 223 if (canEditWidget) { 224 canEditWidget = presentationController.canEditWidget(view, model, widget, widget.getId()); 225 } 226 widget.setReadOnly(!canEditWidget); 227 } 228 } 229 } 230 231 /** 232 * 233 */ 234 private boolean isMaskField(DataField field) { 235 if (field.getDataFieldSecurity() == null) { 236 return false; 237 } 238 239 // check mask authz flag is set 240 AttributeSecurity attributeSecurity = field.getDataFieldSecurity().getAttributeSecurity(); 241 if (attributeSecurity == null || !attributeSecurity.isMask()) { 242 return false; 243 } 244 245 return true; 246 } 247 248 /** 249 * 250 */ 251 private boolean isPartialMaskField(DataField field) { 252 if (field.getDataFieldSecurity() == null) { 253 return false; 254 } 255 256 // check partial mask authz flag is set 257 AttributeSecurity attributeSecurity = field.getDataFieldSecurity().getAttributeSecurity(); 258 if (attributeSecurity == null || !attributeSecurity.isPartialMask()) { 259 return false; 260 } 261 262 return true; 263 } 264 265}