1 /**
2 * Copyright 2005-2012 The Kuali Foundation
3 *
4 * Licensed under the Educational Community License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/ecl2.php
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.kuali.rice.krad;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.config.property.ConfigContext;
20 import org.kuali.rice.core.api.exception.RiceRuntimeException;
21 import org.kuali.rice.kim.api.identity.Person;
22 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
23 import org.kuali.rice.krad.util.SessionTicket;
24
25 import java.io.Serializable;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.concurrent.atomic.AtomicInteger;
32
33 /**
34 * Holds info about the User Session
35 *
36 * @author Kuali Rice Team (rice.collab@kuali.org)
37 */
38 public class UserSession implements Serializable {
39 private static final long serialVersionUID = 4532616762540067557L;
40
41 private Person person;
42 private Person backdoorUser;
43 private AtomicInteger nextObjectKey;
44 private Map<String, Object> objectMap;
45 private String kualiSessionId;
46
47 /**
48 * @return the kualiSessionId
49 */
50 public String getKualiSessionId() {
51 return this.kualiSessionId;
52 }
53
54 /**
55 * @param kualiSessionId the kualiSessionId to set
56 */
57 public void setKualiSessionId(String kualiSessionId) {
58 this.kualiSessionId = kualiSessionId;
59 }
60
61 /**
62 * Take in a netid, and construct the user from that.
63 *
64 * @param principalName
65 */
66 public UserSession(String principalName) {
67 this.person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
68 if (this.person == null) {
69 throw new IllegalArgumentException(
70 "Failed to locate a principal with principal name '" + principalName + "'");
71 }
72 this.nextObjectKey = new AtomicInteger(0);
73 this.objectMap = Collections.synchronizedMap(new HashMap<String, Object>());
74 }
75
76 /**
77 * @return the principalId of the current user in the system, backdoor principalId if backdoor is set
78 */
79 public String getPrincipalId() {
80 if (backdoorUser != null) {
81 return backdoorUser.getPrincipalId();
82 }
83 return person.getPrincipalId();
84 }
85
86 /**
87 * @return the principalName of the current user in the system, backdoor principalName if backdoor is set
88 */
89 public String getPrincipalName() {
90 if (backdoorUser != null) {
91 return backdoorUser.getPrincipalName();
92 }
93 return person.getPrincipalName();
94 }
95
96 /**
97 * This returns who is logged in. If the backdoor is in use, this will return the network id of the person that is
98 * standing in
99 * as the backdoor user.
100 *
101 * @return String
102 */
103 public String getLoggedInUserPrincipalName() {
104 if (person != null) {
105 return person.getPrincipalName();
106 }
107 return "";
108 }
109
110 /**
111 * @return the KualiUser which is the current user in the system, backdoor if backdoor is set
112 */
113 public Person getPerson() {
114 if (backdoorUser != null) {
115 return backdoorUser;
116 }
117 return person;
118 }
119
120 /**
121 * override the current user in the system by setting the backdoor networkId, which is useful when dealing with
122 * 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().isProductionEnvironment();
139 }
140
141 /**
142 * clear the backdoor user
143 */
144 public void clearBackdoorUser() {
145 this.backdoorUser = null;
146 }
147
148 /**
149 * allows adding an arbitrary object to the session and returns a string key that can be used to later access this
150 * object from
151 * the session using the retrieveObject method in this class. This allows for a prefix to be placed in front of the
152 * incremented key. So if the prefix is "searchResults" and the nextObjectKey (local int that holds the key value)
153 * 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.incrementAndGet();
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
166 * object from
167 * the session using the retrieveObject method in this class. The key is generated from an integer and incremented
168 * for every
169 * object added. So the first object added with have a key of "1". This key will be returned from the method.
170 *
171 * @param object
172 */
173 public String addObjectWithGeneratedKey(Object object) {
174 String objectKey = nextObjectKey.incrementAndGet() + "";
175 objectMap.put(objectKey, object);
176 return objectKey;
177 }
178
179 /**
180 * allows adding an arbitrary object to the session with static a string key that can be used to later access this
181 * object from
182 * the session using the retrieveObject method in this class
183 *
184 * @param object
185 */
186 public void addObject(String key, Object object) {
187 objectMap.put(key, object);
188 }
189
190 /**
191 * allows for fetching an object that has been put into the userSession based on the key that would have been
192 * returned when
193 * adding the object
194 *
195 * @param objectKey
196 */
197 public Object retrieveObject(String objectKey) {
198 return this.objectMap.get(objectKey);
199 }
200
201 /**
202 * allows for removal of an object from session that has been put into the userSession based on the key that would
203 * have been
204 * assigned
205 *
206 * @param objectKey
207 */
208 public void removeObject(String objectKey) {
209 this.objectMap.remove(objectKey);
210 }
211
212 /**
213 * allows for removal of an object from session that has been put into the userSession based on a key that starts
214 * with the given
215 * prefix
216 */
217 public void removeObjectsByPrefix(String objectKeyPrefix) {
218 synchronized (objectMap) {
219 List<String> removeKeys = new ArrayList<String>();
220 for (String key : objectMap.keySet()) {
221 if (key.startsWith(objectKeyPrefix)) {
222 removeKeys.add(key);
223 }
224 }
225
226 for (String key : removeKeys) {
227 this.objectMap.remove(key);
228 }
229 }
230 }
231
232 /**
233 * @return boolean indicating if the backdoor is in use
234 */
235 public boolean isBackdoorInUse() {
236 return backdoorUser != null;
237 }
238
239 /**
240 * Adds the given SessionTicket to the objectMap and returns the associated key
241 *
242 * @param ticket - SessionTicket to add
243 * @return the objectMap key for the ticket as a String
244 */
245 public String putSessionTicket(SessionTicket ticket) {
246 return addObjectWithGeneratedKey(ticket);
247 }
248
249 /**
250 * Retrieves all SessionTicket instances currently in the UserSession#objectMap
251 *
252 * @return List<SessionTicket> contained in user session
253 */
254 public List<SessionTicket> getAllSessionTickets() {
255 List<SessionTicket> sessionTickets = new ArrayList<SessionTicket>();
256
257 synchronized (objectMap) {
258 for (Object object : objectMap.values()) {
259 if (object instanceof SessionTicket) {
260 sessionTickets.add((SessionTicket) object);
261 }
262 }
263 }
264
265 return sessionTickets;
266 }
267
268 /**
269 * Retrieves all SessionTicket instances currently in the UserSession#objectMap that are of a given ticket type
270 *
271 * @return List<SessionTicket> contained in user session
272 */
273 public List<SessionTicket> getAllSessionTicketsByType(String ticketTypeName) {
274 List<SessionTicket> sessionTickets = new ArrayList<SessionTicket>();
275
276 for (SessionTicket ticket : getAllSessionTickets()) {
277 if (StringUtils.equalsIgnoreCase(ticket.getTicketTypeName(), ticketTypeName)) {
278 sessionTickets.add(ticket);
279 }
280 }
281
282 return sessionTickets;
283 }
284
285 /**
286 * Determines if the UserSession contains a ticket of the given type that matches the given context. To match context
287 * the ticket must
288 * contain all the same keys at the given context and the values must be equal with the exception of case
289 *
290 * @param ticketTypeName - Name of the ticket type to match
291 * @param matchContext - Map on context parameters to match on
292 * @return true if a ticket was found in the UserSession that matches the request, false if one was not found
293 */
294 public boolean hasMatchingSessionTicket(String ticketTypeName, Map<String, String> matchContext) {
295 boolean hasTicket = false;
296
297 for (SessionTicket ticket : getAllSessionTicketsByType(ticketTypeName)) {
298 Map<String, String> ticketContext = ticket.getTicketContext();
299
300 boolean keySetMatch = ticketContext.keySet().equals(matchContext.keySet());
301 if (keySetMatch) {
302 boolean valuesMatch = true;
303 for (String contextKey : ticketContext.keySet()) {
304 String ticketValue = ticketContext.get(contextKey);
305 String matchValue = matchContext.get(contextKey);
306 if (!StringUtils.equalsIgnoreCase(ticketValue, matchValue)) {
307 valuesMatch = false;
308 }
309 }
310
311 if (valuesMatch) {
312 hasTicket = true;
313 break;
314 }
315 }
316 }
317
318 return hasTicket;
319 }
320
321 /**
322 * retrieves an unmodifiable view of the objectMap.
323 */
324 public Map<String, Object> getObjectMap() {
325 return Collections.unmodifiableMap(this.objectMap);
326 }
327 }