Guest User

Untitled

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