001    /*
002     * Copyright 2011 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.kfs.sec.service.impl;
017    
018    import java.util.Map;
019    
020    import org.apache.commons.lang.StringUtils;
021    import org.kuali.kfs.sec.SecConstants;
022    import org.kuali.kfs.sec.service.AccessPermissionEvaluator;
023    import org.kuali.rice.kim.bo.Person;
024    
025    
026    /**
027     * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator
028     */
029    public class AccessPermissionEvaluatorImpl implements AccessPermissionEvaluator {
030        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccessSecurityServiceImpl.class);
031    
032        protected String constraintCode;
033        protected String operatorCode;
034        protected String propertyValue;
035        protected Map<String, Object> otherKeyFieldValues;
036        protected Person person;
037        protected String[] matchValues;
038        protected boolean performEqualMatch;
039        protected boolean performLessThanMatch;
040        protected boolean performGreaterThanMatch;
041        protected boolean allowConstraint;
042        protected boolean notOperator;
043    
044        public AccessPermissionEvaluatorImpl() {
045            super();
046    
047            performEqualMatch = false;
048            performLessThanMatch = false;
049            performGreaterThanMatch = false;
050            allowConstraint = false;
051            notOperator = false;
052        }
053    
054        /**
055         * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator#valueIsAllowed(java.lang.String)
056         */
057        public boolean valueIsAllowed(String value) {
058            boolean allowed = false;
059    
060            initializeAfterPropsSet();
061    
062            boolean match = false;
063            for (int i = 0; i < matchValues.length; i++) {
064                String matchValue = matchValues[i];
065    
066                if (isMatch(matchValue, value)) {
067                    match = true;
068                    break;
069                }
070            }
071    
072            if ((allowConstraint && notOperator) || (!allowConstraint && !notOperator)) {
073                allowed = !match;
074            }
075            else {
076                allowed = match;
077            }
078    
079            return allowed;
080        }
081    
082        /**
083         * Determines whether two values match performing an equal, greater than, or less than check and also considering wildcards
084         * 
085         * @param matchValue String value to match, can contain the * wildcard
086         * @param value String value to compare
087         * @return boolean true if values match, false otherwise
088         */
089        protected boolean isMatch(String matchValue, String value) {
090            boolean match = false;
091    
092            boolean performWildcardMatch = false;
093            if (StringUtils.contains(matchValue, SecConstants.SecurityValueSpecialCharacters.WILDCARD_CHARACTER)) {
094                matchValue = StringUtils.remove(matchValue, SecConstants.SecurityValueSpecialCharacters.WILDCARD_CHARACTER);
095                performWildcardMatch = true;
096            }
097    
098            if (performEqualMatch) {
099                if (performWildcardMatch) {
100                    match = value.startsWith(matchValue);
101                }
102                else {
103                    match = value.equals(matchValue);
104                }
105            }
106    
107            if (!match && performLessThanMatch) {
108                match = value.compareTo(matchValue) < 0;
109            }
110    
111            if (!match && performGreaterThanMatch) {
112                match = value.compareTo(matchValue) > 0;
113            }
114    
115            return match;
116        }
117    
118        /**
119         * Hooks for permission evaluators to do additional setup after properties have been set
120         */
121        protected void initializeAfterPropsSet() {
122            if (StringUtils.contains(constraintCode, SecConstants.SecurityConstraintCodes.ALLOWED)) {
123                allowConstraint = true;
124            }
125    
126            if (SecConstants.SecurityDefinitionOperatorCodes.EQUAL.equals(operatorCode) || SecConstants.SecurityDefinitionOperatorCodes.NOT_EQUAL.equals(operatorCode) || SecConstants.SecurityDefinitionOperatorCodes.LESS_THAN_EQUAL.equals(operatorCode)
127                    || SecConstants.SecurityDefinitionOperatorCodes.GREATER_THAN_EQUAL.equals(operatorCode)) {
128                performEqualMatch = true;
129            }
130    
131            if (SecConstants.SecurityDefinitionOperatorCodes.LESS_THAN.equals(operatorCode) || SecConstants.SecurityDefinitionOperatorCodes.LESS_THAN_EQUAL.equals(operatorCode)) {
132                performLessThanMatch = true;
133            }
134    
135            if (SecConstants.SecurityDefinitionOperatorCodes.GREATER_THAN.equals(operatorCode) || SecConstants.SecurityDefinitionOperatorCodes.GREATER_THAN_EQUAL.equals(operatorCode)) {
136                performGreaterThanMatch = true;
137            }
138            
139            if (SecConstants.SecurityDefinitionOperatorCodes.NOT_EQUAL.equals(operatorCode)) {
140                notOperator = true;
141            }
142    
143            setMatchValues();
144        }
145    
146        /**
147         * Sets the values to match on based on given value and other properties
148         */
149        protected void setMatchValues() {
150            if (StringUtils.contains(propertyValue, SecConstants.SecurityValueSpecialCharacters.MULTI_VALUE_SEPERATION_CHARACTER)) {
151                matchValues = StringUtils.split(propertyValue, SecConstants.SecurityValueSpecialCharacters.MULTI_VALUE_SEPERATION_CHARACTER);
152            }
153            else {
154                matchValues = new String[1];
155                matchValues[0] = propertyValue;
156            }
157        }
158    
159        /**
160         * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator#setConstraintCode(java.lang.String)
161         */
162        public void setConstraintCode(String constraintCode) {
163            this.constraintCode = constraintCode;
164        }
165    
166        /**
167         * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator#setOperatorCode(java.lang.String)
168         */
169        public void setOperatorCode(String operatorCode) {
170            this.operatorCode = operatorCode;
171        }
172    
173        /**
174         * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator#setPropertyValue(java.lang.String)
175         */
176        public void setPropertyValue(String propertyValue) {
177            this.propertyValue = propertyValue;
178        }
179    
180        /**
181         * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator#setOtherKeyFieldValueMap(java.util.Map)
182         */
183        public void setOtherKeyFieldValueMap(Map<String, Object> otherKeyFieldValues) {
184            this.otherKeyFieldValues = otherKeyFieldValues;
185        }
186    
187        /**
188         * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator#setPerson(org.kuali.rice.kim.bo.Person)
189         */
190        public void setPerson(Person person) {
191            this.person = person;
192        }
193    
194    }