001    /*
002     * Copyright 2006-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    
017    package org.kuali.rice.kns;
018    
019    import org.apache.commons.lang.StringUtils;
020    import org.kuali.rice.core.api.config.property.ConfigContext;
021    import org.kuali.rice.core.api.exception.RiceRuntimeException;
022    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
023    import org.kuali.rice.kim.bo.Person;
024    import org.kuali.rice.kns.util.KNSConstants;
025    import org.kuali.rice.kns.util.SessionTicket;
026    
027    import java.io.Serializable;
028    import java.util.ArrayList;
029    import java.util.Collections;
030    import java.util.HashMap;
031    import java.util.List;
032    import java.util.Map;
033    
034    
035    /**
036     * Holds info about the User Session
037     */
038    public class UserSession implements Serializable {
039    
040        private static final long serialVersionUID = 4532616762540067557L;
041    
042        private Person person;
043        private Person backdoorUser;
044        private int nextObjectKey;
045        private Map<String,Object> objectMap;
046        private String kualiSessionId;
047    
048        /**
049             * @return the kualiSessionId
050             */
051            public String getKualiSessionId() {
052                    return this.kualiSessionId;
053            }
054    
055            /**
056             * @param kualiSessionId the kualiSessionId to set
057             */
058            public void setKualiSessionId(String kualiSessionId) {
059                    this.kualiSessionId = kualiSessionId;
060            }
061    
062        /**
063         * Take in a netid, and construct the user from that.
064         * 
065         * @param principalName
066         */
067        public UserSession(String principalName) {
068            this.person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
069            if (this.person == null) {
070                    throw new IllegalArgumentException("Failed to locate a principal with principal name '" + principalName + "'");
071            }
072            this.nextObjectKey = 0;
073            this.objectMap = new HashMap<String,Object>();
074        }
075    
076        
077        /**
078         * @return the principalId of the current user in the system, backdoor principalId if backdoor is set
079         */
080        public String getPrincipalId() {
081            if (backdoorUser != null) {
082                return backdoorUser.getPrincipalId();
083            }
084            return person.getPrincipalId();
085        }
086    
087        /**
088         * @return the principalName of the current user in the system, backdoor principalName if backdoor is set
089         */
090        public String getPrincipalName() {
091            if (backdoorUser != null) {
092                return backdoorUser.getPrincipalName();
093            }
094            return person.getPrincipalName();
095        }
096    
097        
098        /**
099         * This returns who is logged in. If the backdoor is in use, this will return the network id of the person that is standing in
100         * as the backdoor user.
101         * 
102         * @return String
103         */
104        public String getLoggedInUserPrincipalName() {
105            if ( person != null ) {
106                    return person.getPrincipalName();
107            }
108            return "";
109        }
110    
111        /**
112         * @return the KualiUser which is the current user in the system, backdoor if backdoor is set
113         */
114        public Person getPerson() {
115            if (backdoorUser != null) {
116                return backdoorUser;
117            }
118            return person;
119        }
120    
121        /**
122         * override the current user in the system by setting the backdoor networkId, which is useful when dealing with routing or other
123         * reasons why you would need to assume an identity in the system
124         * 
125         * @param principalName
126         */
127        public void setBackdoorUser(String principalName) {
128           // only allow backdoor in non-production environments
129           if ( !isProductionEnvironment()) {
130            this.backdoorUser = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
131            if (backdoorUser == null) {
132                    throw new RiceRuntimeException(principalName + " is not a valid principalName");
133            }
134           }
135        }
136        
137        private boolean isProductionEnvironment() {
138            return ConfigContext.getCurrentContextConfig().getProperty(KNSConstants.PROD_ENVIRONMENT_CODE_KEY).equalsIgnoreCase(
139                            ConfigContext.getCurrentContextConfig().getProperty(KNSConstants.ENVIRONMENT_KEY));
140        }
141    
142        /**
143         * clear the backdoor user
144         * 
145         */
146        public void clearBackdoorUser() {
147            this.backdoorUser = null;
148        }
149    
150        /**
151         * allows adding an arbitrary object to the session and returns a string key that can be used to later access this object from
152         * the session using the retrieveObject method in this class. This allows for a prefix to be placed in front of the 
153         * incremented key. So if the prefix is "searchResults" and the nextObjectKey (local int that holds the key value) is 2 then
154         * the new key will be "searchResults3". "searchResults3" will be returned from the method.
155         * 
156         * @param object
157         */
158        public String addObjectWithGeneratedKey(Serializable object, String keyPrefix) {
159            String objectKey = keyPrefix + nextObjectKey++;
160            objectMap.put(objectKey, object);
161            return objectKey;
162        }
163        
164        /**
165         * allows adding an arbitrary object to the session and returns a string key that can be used to later access this object from
166         * the session using the retrieveObject method in this class. The key is generated from an integer and incremented for every 
167         * object added.  So the first object added with have a key of "1".  This key will be returned from the method.
168         * 
169         * @param object
170         */
171        public String addObjectWithGeneratedKey(Object object) {
172            String objectKey = nextObjectKey++ + "";
173            objectMap.put(objectKey, object);
174            return objectKey;
175        }
176    
177        /**
178         * allows adding an arbitrary object to the session with static a string key that can be used to later access this object from
179         * the session using the retrieveObject method in this class
180         * 
181         * @param object
182         * 
183         */
184        public void addObject(String key, Object object) {
185    
186            objectMap.put(key, object);
187    
188        }
189    
190        /**
191         * allows for fetching an object that has been put into the userSession based on the key that would have been returned when
192         * adding the object
193         * 
194         * @param objectKey
195         */
196        public Object retrieveObject(String objectKey) {
197            return this.objectMap.get(objectKey);
198        }
199    
200        /**
201         * allows for removal of an object from session that has been put into the userSession based on the key that would have been
202         * assigned
203         * 
204         * @param objectKey
205         */
206        public void removeObject(String objectKey) {
207            this.objectMap.remove(objectKey);
208        }
209    
210        /**
211         * allows for removal of an object from session that has been put into the userSession based on a key that starts with the given
212         * prefix
213         */
214        public void removeObjectsByPrefix(String objectKeyPrefix) {
215            List<String> removeKeys = new ArrayList<String>();
216            for (String key : objectMap.keySet()) {
217                if (key.startsWith(objectKeyPrefix)) {
218                    removeKeys.add(key);
219                }
220            }
221    
222            for (String key : removeKeys) {
223                this.objectMap.remove(key);
224            }
225        }
226    
227        /**
228         * @return boolean indicating if the backdoor is in use
229         */
230        public boolean isBackdoorInUse() {
231            return backdoorUser != null;
232        }
233        
234            /**
235             * Adds the given SessionTicket to the objectMap and returns the associated key
236             * 
237             * @param ticket
238             *            - SessionTicket to add
239             * @return the objectMap key for the ticket as a String
240             */
241            public String putSessionTicket(SessionTicket ticket) {
242                    return addObjectWithGeneratedKey(ticket);
243            }
244    
245            /**
246             * Retrieves all SessionTicket instances currently in the UserSession#objectMap
247             * 
248             * @return List<SessionTicket> contained in user session
249             */
250            public List<SessionTicket> getAllSessionTickets() {
251                    List<SessionTicket> sessionTickets = new ArrayList<SessionTicket>();
252    
253                    for (Object object : objectMap.values()) {
254                            if (object instanceof SessionTicket) {
255                                    sessionTickets.add((SessionTicket) object);
256                            }
257                    }
258    
259                    return sessionTickets;
260            }
261    
262            /**
263             * Retrieves all SessionTicket instances currently in the UserSession#objectMap that are of a given ticket type
264             * 
265             * @return List<SessionTicket> contained in user session
266             */
267            public List<SessionTicket> getAllSessionTicketsByType(String ticketTypeName) {
268                    List<SessionTicket> sessionTickets = new ArrayList<SessionTicket>();
269    
270                    for (SessionTicket ticket : getAllSessionTickets()) {
271                            if (StringUtils.equalsIgnoreCase(ticket.getTicketTypeName(), ticketTypeName)) {
272                                    sessionTickets.add(ticket);
273                            }
274                    }
275    
276                    return sessionTickets;
277            }
278    
279            /**
280             * Determines if the UserSession contains a ticket of the given type that matches the given context. To match context the ticket must
281             * contain all the same keys at the given context and the values must be equal with the exception of case
282             * 
283             * @param ticketTypeName
284             *            - Name of the ticket type to match
285             * @param matchContext
286             *            - Map on context parameters to match on
287             * @return true if a ticket was found in the UserSession that matches the request, false if one was not found
288             */
289            public boolean hasMatchingSessionTicket(String ticketTypeName, Map<String, String> matchContext) {
290                    boolean hasTicket = false;
291    
292                    for (SessionTicket ticket : getAllSessionTicketsByType(ticketTypeName)) {
293                            Map<String, String> ticketContext = ticket.getTicketContext();
294    
295                            boolean keySetMatch = ticketContext.keySet().equals(matchContext.keySet());
296                            if (keySetMatch) {
297                                    boolean valuesMatch = true;
298                                    for (String contextKey : ticketContext.keySet()) {
299                                            String ticketValue = ticketContext.get(contextKey);
300                                            String matchValue = matchContext.get(contextKey);
301                                            if (!StringUtils.equalsIgnoreCase(ticketValue, matchValue)) {
302                                                    valuesMatch = false;
303                                            }
304                                    }
305    
306                                    if (valuesMatch) {
307                                            hasTicket = true;
308                                            break;
309                                    }
310                            }
311                    }
312    
313                    return hasTicket;
314            }
315            
316            /** retrieves an unmodifiable view of the objectMap. */
317            public Map<String, Object> getObjectMap() {
318                    return Collections.unmodifiableMap(this.objectMap);
319            }
320    }