Advertisement
Guest User

Untitled

a guest
Jan 21st, 2013
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.49 KB | None | 0 0
  1. /**
  2. * The contents of this file are subject to the OpenMRS Public License
  3. * Version 1.0 (the "License"); you may not use this file except in
  4. * compliance with the License. You may obtain a copy of the License at
  5. * http://license.openmrs.org
  6. *
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  9. * License for the specific language governing rights and limitations
  10. * under the License.
  11. *
  12. * Copyright (C) OpenMRS, LLC. All Rights Reserved.
  13. */
  14. package org.openmrs.api.context;
  15.  
  16. import java.util.HashSet;
  17. import java.util.List;
  18. import java.util.Locale;
  19. import java.util.Set;
  20. import java.util.Vector;
  21.  
  22. import org.apache.commons.lang.StringUtils;
  23. import org.apache.commons.logging.Log;
  24. import org.apache.commons.logging.LogFactory;
  25. import org.openmrs.Location;
  26. import org.openmrs.Role;
  27. import org.openmrs.User;
  28. import org.openmrs.api.APIAuthenticationException;
  29. import org.openmrs.api.context.UserContext;
  30. import org.openmrs.api.db.ContextDAO;
  31. import org.openmrs.util.LocaleUtility;
  32. import org.openmrs.util.OpenmrsConstants;
  33. import org.openmrs.util.RoleConstants;
  34. import java.io.Serializable;
  35.  
  36. /**
  37. * Represents an OpenMRS <code>User Context</code> which stores the current user information. Only
  38. * one <code>User</code> may be authenticated within a UserContext at any given time. The
  39. * UserContext should not be accessed directly, but rather used through the <code>Context</code>.
  40. * This class should be kept light-weight. There is one instance of this class per user that is
  41. * logged into the system.
  42. *
  43. * @see org.openmrs.api.context.Context
  44. */
  45. public class UserContext implements Serializable {
  46.  
  47. private static final long serialVersionUID = -806631231941890648L;
  48.  
  49. /**
  50. * Logger - shared by entire class
  51. */
  52. private static final Log log = LogFactory.getLog(UserContext.class);
  53.  
  54. /**
  55. * User object containing details about the authenticated user
  56. */
  57. private User user = null;
  58.  
  59. /**
  60. * User's permission proxies
  61. */
  62. private List<String> proxies = new Vector<String>();
  63.  
  64. /**
  65. * User's locale
  66. */
  67. private Locale locale = null;
  68.  
  69. /**
  70. * Cached Role given to all authenticated users
  71. */
  72. private Role authenticatedRole = null;
  73.  
  74. /**
  75. * Cache Role given to all users
  76. */
  77. private Role anonymousRole = null;
  78.  
  79. /**
  80. * User's defined locationId
  81. */
  82. private Integer locationId = null;
  83.  
  84. /**
  85. * Default public constructor
  86. */
  87. public UserContext() {
  88. }
  89.  
  90. /**
  91. * Authenticate the user to this UserContext.
  92. *
  93. * @see org.openmrs.api.context.Context#authenticate(String,String)
  94. * @param username String login name
  95. * @param password String login password
  96. * @param contextDAO ContextDAO implementation to use for authentication
  97. * @return User that has been authenticated
  98. * @throws ContextAuthenticationException
  99. */
  100. public User authenticate(String username, String password, ContextDAO contextDAO) throws ContextAuthenticationException {
  101. if (log.isDebugEnabled())
  102. log.debug("Authenticating with username: " + username);
  103.  
  104. this.user = contextDAO.authenticate(username, password);
  105. setUserLocation();
  106. if (log.isDebugEnabled())
  107. log.debug("Authenticated as: " + this.user);
  108.  
  109. return this.user;
  110. }
  111.  
  112. /**
  113. * Refresh the authenticated user object in this UserContext. This should be used when updating
  114. * information in the database about the current user and it needs to be reflecting in the
  115. * (cached) {@link #getAuthenticatedUser()} User object.
  116. *
  117. * @since 1.5
  118. */
  119. public void refreshAuthenticatedUser() {
  120. if (log.isDebugEnabled())
  121. log.debug("Refreshing authenticated user");
  122.  
  123. if (user != null) {
  124. user = Context.getUserService().getUser(user.getUserId());
  125. //update the stored location in the user's session
  126. setUserLocation();
  127. }
  128. }
  129.  
  130. /**
  131. * Change current authentication to become another user. (You can only do this if you're already
  132. * authenticated as a superuser.)
  133. *
  134. * @param systemId
  135. * @return The new user that this context has been set to. (null means no change was made)
  136. * @throws ContextAuthenticationException
  137. */
  138. public User becomeUser(String systemId) throws ContextAuthenticationException {
  139. if (!Context.getAuthenticatedUser().isSuperUser())
  140. throw new APIAuthenticationException("You must be a superuser to assume another user's identity");
  141.  
  142. if (log.isDebugEnabled())
  143. log.debug("Turning the authenticated user into user with systemId: " + systemId);
  144.  
  145. User userToBecome = Context.getUserService().getUserByUsername(systemId);
  146.  
  147. if (userToBecome == null)
  148. throw new ContextAuthenticationException("User not found with systemId: " + systemId);
  149.  
  150. // hydrate the user object
  151. if (userToBecome.getAllRoles() != null)
  152. userToBecome.getAllRoles().size();
  153. if (userToBecome.getUserProperties() != null)
  154. userToBecome.getUserProperties().size();
  155. if (userToBecome.getPrivileges() != null)
  156. userToBecome.getPrivileges().size();
  157.  
  158. this.user = userToBecome;
  159. //update the user's location
  160. setUserLocation();
  161.  
  162. if (log.isDebugEnabled())
  163. log.debug("Becoming user: " + user);
  164.  
  165. return userToBecome;
  166. }
  167.  
  168. /**
  169. * @return "active" user who has been authenticated, otherwise <code>null</code>
  170. */
  171. public User getAuthenticatedUser() {
  172. return user;
  173. }
  174.  
  175. /**
  176. * @return true if user has been authenticated in this UserContext
  177. */
  178. public boolean isAuthenticated() {
  179. return user != null;
  180. }
  181.  
  182. /**
  183. * logs out the "active" (authenticated) user within this UserContext
  184. *
  185. * @see #authenticate
  186. */
  187. public void logout() {
  188. log.debug("setting user to null on logout");
  189. user = null;
  190. }
  191.  
  192. /**
  193. * Gives the given privilege to all calls to hasPrivilege. This method was visualized as being
  194. * used as follows (try/finally is important):
  195. *
  196. * <pre>
  197. * try {
  198. * Context.addProxyPrivilege(&quot;AAA&quot;);
  199. * Context.get*Service().methodRequiringAAAPrivilege();
  200. * }
  201. * finally {
  202. * Context.removeProxyPrivilege(&quot;AAA&quot;);
  203. * }
  204. * </pre>
  205. *
  206. * @param privilege to give to users
  207. */
  208. public void addProxyPrivilege(String privilege) {
  209. if (log.isDebugEnabled())
  210. log.debug("Adding proxy privilege: " + privilege);
  211.  
  212. proxies.add(privilege);
  213. }
  214.  
  215. /**
  216. * Will remove one instance of privilege from the privileges that are currently proxied
  217. *
  218. * @param privilege Privilege to remove in string form
  219. */
  220. public void removeProxyPrivilege(String privilege) {
  221. if (log.isDebugEnabled())
  222. log.debug("Removing proxy privilege: " + privilege);
  223.  
  224. if (proxies.contains(privilege))
  225. proxies.remove(privilege);
  226. }
  227.  
  228. /**
  229. * @param locale new locale for this context
  230. */
  231. public void setLocale(Locale locale) {
  232. this.locale = locale;
  233. }
  234.  
  235. /**
  236. * @return current locale for this context
  237. */
  238. public Locale getLocale() {
  239. if (locale == null)
  240. // don't cache default locale - allows recognition of changed default at login page
  241. return LocaleUtility.getDefaultLocale();
  242.  
  243. return locale;
  244. }
  245.  
  246. /**
  247. * Gets all the roles for the (un)authenticated user. Anonymous and Authenticated roles are
  248. * appended if necessary
  249. *
  250. * @return all expanded roles for a user
  251. * @throws Exception
  252. */
  253. public Set<Role> getAllRoles() throws Exception {
  254. return getAllRoles(getAuthenticatedUser());
  255. }
  256.  
  257. /**
  258. * Gets all the roles for a user. Anonymous and Authenticated roles are appended if necessary
  259. *
  260. * @param user
  261. * @return all expanded roles for a user
  262. * @should not fail with null user
  263. * @should add anonymous role to all users
  264. * @should add authenticated role to all authenticated users
  265. * @should return same roles as user getAllRoles method
  266. */
  267. public Set<Role> getAllRoles(User user) throws Exception {
  268. Set<Role> roles = new HashSet<Role>();
  269.  
  270. // add the Anonymous Role
  271. roles.add(getAnonymousRole());
  272.  
  273. // add the Authenticated role
  274. if (user != null && getAuthenticatedUser() != null && getAuthenticatedUser().equals(user)) {
  275. roles.addAll(user.getAllRoles());
  276. roles.add(getAuthenticatedRole());
  277. }
  278.  
  279. return roles;
  280. }
  281.  
  282. /**
  283. * Tests whether or not currently authenticated user has a particular privilege
  284. *
  285. * @param privilege
  286. * @return true if authenticated user has given privilege
  287. * @should authorize if authenticated user has specified privilege
  288. * @should authorize if authenticated role has specified privilege
  289. * @should authorize if proxied user has specified privilege
  290. * @should authorize if anonymous user has specified privilege
  291. * @should not authorize if authenticated user does not have specified privilege
  292. * @should not authorize if authenticated role does not have specified privilege
  293. * @should not authorize if proxied user does not have specified privilege
  294. * @should not authorize if anonymous user does not have specified privilege
  295. */
  296. public boolean hasPrivilege(String privilege) {
  297.  
  298. // if a user has logged in, check their privileges
  299. if (isAuthenticated()) {
  300.  
  301. // check user's privileges
  302. if (getAuthenticatedUser().hasPrivilege(privilege) || getAuthenticatedRole().hasPrivilege(privilege)) {
  303. Context.getUserService().notifyPrivilegeListeners(getAuthenticatedUser(), privilege, true);
  304. return true;
  305. }
  306.  
  307. }
  308.  
  309. if (log.isDebugEnabled())
  310. log.debug("Checking '" + privilege + "' against proxies: " + proxies);
  311.  
  312. // check proxied privileges
  313. for (String s : proxies) {
  314. if (s.equals(privilege)) {
  315. Context.getUserService().notifyPrivilegeListeners(getAuthenticatedUser(), privilege, true);
  316. return true;
  317. }
  318. }
  319.  
  320. if (getAnonymousRole().hasPrivilege(privilege)) {
  321. Context.getUserService().notifyPrivilegeListeners(getAuthenticatedUser(), privilege, true);
  322. return true;
  323. }
  324.  
  325. // default return value
  326. Context.getUserService().notifyPrivilegeListeners(getAuthenticatedUser(), privilege, false);
  327. return false;
  328. }
  329.  
  330. /**
  331. * Convenience method to get the Role in the system designed to be given to all users
  332. *
  333. * @return Role
  334. * @should fail if database doesn't contain anonymous role
  335. */
  336. private Role getAnonymousRole() {
  337. if (anonymousRole != null)
  338. return anonymousRole;
  339.  
  340. anonymousRole = Context.getUserService().getRole(RoleConstants.ANONYMOUS);
  341. if (anonymousRole == null) {
  342. throw new RuntimeException("Database out of sync with code: " + RoleConstants.ANONYMOUS + " role does not exist");
  343. }
  344.  
  345. return anonymousRole;
  346. }
  347.  
  348. /**
  349. * Convenience method to get the Role in the system designed to be given to all users that have
  350. * authenticated in some manner
  351. *
  352. * @return Role
  353. * @should fail if database doesn't contain authenticated role
  354. */
  355. private Role getAuthenticatedRole() {
  356. if (authenticatedRole != null)
  357. return authenticatedRole;
  358.  
  359. authenticatedRole = Context.getUserService().getRole(RoleConstants.AUTHENTICATED);
  360. if (authenticatedRole == null) {
  361. throw new RuntimeException("Database out of sync with code: " + RoleConstants.AUTHENTICATED
  362. + " role does not exist");
  363. }
  364.  
  365. return authenticatedRole;
  366. }
  367.  
  368. /**
  369. * @return current locationId for this user context if any is set
  370. * @since 1.9
  371. */
  372. public Integer getLocationId() {
  373. return this.locationId;
  374. }
  375.  
  376. /**
  377. * @param locationId the locationId to set to
  378. * @since 1.9
  379. */
  380. public void setLocationId(Integer locationId) {
  381. this.locationId = locationId;
  382. }
  383.  
  384. /**
  385. * Convenience method that sets the default locationId of the currently authenticated user using
  386. * the value of the user's default location property
  387. */
  388. private void setUserLocation() {
  389. if (this.user != null) {
  390. String locationId = this.user.getUserProperty(OpenmrsConstants.USER_PROPERTY_DEFAULT_LOCATION);
  391. if (StringUtils.isNotBlank(locationId)) {
  392. //only go ahead if it has actually changed OR if wasn't set before
  393. if (this.locationId == null || !this.locationId.getName().equalsIgnoreCase(locationId)) {
  394. try {
  395. this.locationId = Context.getLocationService().getLocation(Integer.valueOf(locationId));
  396. }
  397. catch (NumberFormatException e) {
  398. //Drop the stored value since we have no match for the set id
  399. if (this.locationId != null)
  400. this.locationId = null;
  401. log.warn("The value of the default Location property of the user with id:" + this.user.getUserId()
  402. + " should be an integer", e);
  403. }
  404. }
  405. } else {
  406. if (this.locationId != null)
  407. this.locationId = null;
  408. }
  409. }
  410. }
  411. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement