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