Advertisement
Guest User

Untitled

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