/** * This Source Code Form is subject to the terms of the Mozilla Public License, * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under * the terms of the Healthcare Disclaimer located at http://openmrs.org/license. * * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS * graphic logo is a trademark of OpenMRS Inc. */ package org.openmrs.api; import java.util.List; import java.util.Map; import org.openmrs.Person; import org.openmrs.Privilege; import org.openmrs.PrivilegeListener; import org.openmrs.Role; import org.openmrs.User; import org.openmrs.annotation.Authorized; import org.openmrs.annotation.Logging; import org.openmrs.api.context.UserContext; import org.openmrs.util.PersonByNameComparator; import org.openmrs.util.PrivilegeConstants; /** * Contains methods pertaining to Users in the system Use:<br> * * <pre> * * * List<User> users = Context.getUserService().getAllUsers(); * </pre> * * @see org.openmrs.api.context.Context */ public interface UserService extends OpenmrsService { /** * Create user with given password. * * @param user the user to create * @param password the password for created user * @return created user * @throws APIException */ @Authorized( { PrivilegeConstants.ADD_USERS }) @Logging(ignoredArgumentIndexes = { 1 }) public User createUser(User user, String password) throws APIException; /** * Change user password. * * @param user the user to update password * @param oldPassword the user password to update * @param newPassword the new user password * @throws APIException for not existing user and if old password is weak * @since 1.12 * @should throw APIException if old password is not correct * @should throw APIException if given user does not exist * @should change password for given user if oldPassword is correctly passed * @should change password for given user if oldPassword is null and changing user have privileges * @should throw exception if oldPassword is null and changing user have not privileges * @should throw exception if new password is too short */ @Authorized( { PrivilegeConstants.EDIT_USER_PASSWORDS }) @Logging(ignoredArgumentIndexes = { 1, 2 }) public void changePassword(User user, String oldPassword, String newPassword) throws APIException; /** * Get user by internal user identifier. * * @param userId internal identifier * @return requested user * @throws APIException * @should fetch user with given userId */ @Authorized( { PrivilegeConstants.GET_USERS }) public User getUser(Integer userId) throws APIException; /** * Get user by the given uuid. * * @param uuid * @return user or null * @throws APIException * @should fetch user with given uuid * @should find object given valid uuid * @should return null if no object found with given uuid */ @Authorized( { PrivilegeConstants.GET_USERS }) public User getUserByUuid(String uuid) throws APIException; /** * Get user by username (user's login identifier) * * @param username user's identifier used for authentication * @return requested user * @throws APIException * @should get user by username */ @Authorized( { PrivilegeConstants.GET_USERS }) public User getUserByUsername(String username) throws APIException; /** * true/false if username or systemId is already in db in username or system_id columns * * @param user User to compare * @return boolean * @throws APIException * @should verify that username and system id is unique */ @Authorized( { PrivilegeConstants.GET_USERS }) public boolean hasDuplicateUsername(User user) throws APIException; /** * Get users by role granted * * @param role Role that the Users must have to be returned * @return users with requested role * @throws APIException * @should fetch users assigned given role * @should not fetch user that does not belong to given role */ @Authorized( { PrivilegeConstants.GET_USERS }) public List<User> getUsersByRole(Role role) throws APIException; /** * Updates a given <code>user</code> in the database. * * @param user * @return the saved user * @throws APIException */ @Authorized( { PrivilegeConstants.EDIT_USERS }) public User saveUser(User user) throws APIException; /** * Deactivate a user account so that it can no longer log in. * * @param user * @param reason * @throws APIException * @should retire user and set attributes */ @Authorized( { PrivilegeConstants.EDIT_USERS }) public User retireUser(User user, String reason) throws APIException; /** * Clears retired flag for a user. * * @param user * @throws APIException * @should unretire and unmark all attributes */ @Authorized( { PrivilegeConstants.EDIT_USERS }) public User unretireUser(User user) throws APIException; /** * Completely remove a location from the database (not reversible). This method delegates to * #purgeLocation(location, boolean) method. * * @param user the User to remove from the database. * @should delete given user */ @Authorized( { PrivilegeConstants.PURGE_USERS }) public void purgeUser(User user) throws APIException; /** * Completely remove a user from the database (not reversible). This is a delete from the * database. This is included for troubleshooting and low-level system administration. Ideally, * this method should <b>never</b> be called — <code>Users</code> should be * <em>voided</em> and not <em>deleted</em> altogether (since many foreign key constraints * depend on users, deleting a user would require deleting all traces, and any historical trail * would be lost). This method only clears user roles and attempts to delete the user record. If * the user has been included in any other parts of the database (through a foreign key), the * attempt to delete the user will violate foreign key constraints and fail. * * @param cascade <code>true</code> to delete associated content * @should throw APIException if cascade is true * @should delete given user when cascade equals false * @should not delete user roles for given user when cascade equals false */ @Authorized( { PrivilegeConstants.PURGE_USERS }) public void purgeUser(User user, boolean cascade) throws APIException; /** * Returns all privileges currently possible for any User * * @return Global list of privileges * @throws APIException * @should return all privileges in the system */ public List<Privilege> getAllPrivileges() throws APIException; /** * Returns all roles currently possible for any User * * @return Global list of roles * @throws APIException * @should return all roles in the system */ public List<Role> getAllRoles() throws APIException; /** * Save the given role in the database * * @param role Role to update * @return the saved role * @throws APIException * @should throw error if role inherits from itself * @should save given role to the database */ @Authorized( { PrivilegeConstants.MANAGE_ROLES }) public Role saveRole(Role role) throws APIException; /** * Complete remove a role from the database * * @param role Role to delete from the database * @throws APIException * @should throw error when role is a core role * @should return if role is null * @should delete given role from database */ @Authorized( { PrivilegeConstants.PURGE_ROLES }) public void purgeRole(Role role) throws APIException; /** * Save the given privilege in the database * * @param privilege Privilege to update * @return the saved privilege * @throws APIException * @should save given privilege to the database */ @Authorized( { PrivilegeConstants.MANAGE_PRIVILEGES }) public Privilege savePrivilege(Privilege privilege) throws APIException; /** * Completely remove a privilege from the database * * @param privilege Privilege to delete * @throws APIException * @should delete given privilege from the database * @should throw error when privilege is core privilege */ @Authorized( { PrivilegeConstants.PURGE_PRIVILEGES }) public void purgePrivilege(Privilege privilege) throws APIException; /** * Returns role object with given string role * * @return Role object for specified string * @throws APIException * @should fetch role for given role name */ public Role getRole(String r) throws APIException; /** * Get Role by its UUID * * @param uuid * @return role or null * @should find object given valid uuid * @should return null if no object found with given uuid */ public Role getRoleByUuid(String uuid) throws APIException; /** * Returns Privilege in the system with given String privilege * * @return Privilege * @throws APIException * @should fetch privilege for given name */ public Privilege getPrivilege(String p) throws APIException; /** * Get Privilege by its UUID * * @param uuid * @return privilege or null * @should find object given valid uuid * @should return null if no object found with given uuid * @should fetch privilege for given uuid */ public Privilege getPrivilegeByUuid(String uuid) throws APIException; /** * Returns all users in the system * * @return Global list of users * @throws APIException * @should fetch all users in the system * @should not contains any duplicate users */ @Authorized( { PrivilegeConstants.GET_USERS }) public List<User> getAllUsers() throws APIException; /** * Changes the current user's password. * * @param pw current password * @param pw2 new password * @throws APIException * @should match on correctly hashed sha1 stored password * @should match on incorrectly hashed sha1 stored password * @should match on sha512 hashed password * @should be able to update password multiple times */ @Logging(ignoredArgumentIndexes = { 0, 1 }) public void changePassword(String pw, String pw2) throws APIException; /** * Changes password of {@link User} passed in * @param user user whose password is to be changed * @param newPassword new password to set * @throws APIException * @should update password of given user when logged in user has edit users password privilege * @should not update password of given user when logged in user does not have edit users password privilege */ @Authorized({PrivilegeConstants.EDIT_USER_PASSWORDS}) public void changePassword(User user, String newPassword) throws APIException; /** * Changes the current user's password directly. This is most useful if migrating users from * other systems and you want to retain the existing passwords. This method will simply save the * passed hashed password and salt directly to the database. * * @param user the user whose password you want to change * @param hashedPassword - the <em>already hashed</em> password to store * @param salt - the salt which should be used with this hashed password * @throws APIException * @since 1.5 * @should change the hashed password for the given user */ @Authorized( { PrivilegeConstants.EDIT_USER_PASSWORDS }) public void changeHashedPassword(User user, String hashedPassword, String salt) throws APIException; /** * Changes the passed user's secret question and answer. * * @param u User to change * @param question * @param answer * @throws APIException * @since 1.5 * @should change the secret question and answer for given user */ @Authorized( { PrivilegeConstants.EDIT_USER_PASSWORDS }) @Logging(ignoredArgumentIndexes = { 1, 2 }) public void changeQuestionAnswer(User u, String question, String answer) throws APIException; /** * Changes the current user's secret question and answer. * * @param pw user's password * @param q question * @param a answer * @throws APIException * @should match on correctly hashed stored password * @should match on incorrectly hashed stored password */ @Logging(ignoreAllArgumentValues = true) public void changeQuestionAnswer(String pw, String q, String a) throws APIException; /** * Returns secret question for the given user. * * @param user * @return * @throws APIException * @since 2.0 */ public String getSecretQuestion(User user) throws APIException; /** * Compares <code>answer</code> against the <code>user</code>'s secret answer. * * @param u user * @param answer * @throws APIException * @should return true when given answer matches stored secret answer * @should return false when given answer does not match the stored secret answer */ @Logging(ignoredArgumentIndexes = { 1 }) public boolean isSecretAnswer(User u, String answer) throws APIException; /** * Return a list of users sorted by personName (see {@link PersonByNameComparator}) if any part * of the search matches first/last/system id and the user has one at least one of the given * <code>roles</code> assigned to them * * @param nameSearch string to compare to the beginning of user's given/middle/family/family2 * names * @param roles all the Roles the user must contain * @param includeVoided true/false whether to include voided users * @return list of users matching the given attributes * @should match search to familyName2 * @should fetch voided users if includedVoided is true * @should not fetch voided users if includedVoided is false * @should fetch users with name that contains given nameSearch * @should fetch users with systemId that contains given nameSearch * @should fetch users with at least one of the given role objects * @should not fetch duplicate users * @should fetch all users if nameSearch is empty or null * @should not fail if roles are searched but name is empty */ @Authorized( { PrivilegeConstants.GET_USERS }) public List<User> getUsers(String nameSearch, List<Role> roles, boolean includeVoided) throws APIException; /** * Search for a list of users by exact first name and last name. * * @param givenName * @param familyName * @param includeRetired * @return List<User> object of users matching criteria * @should fetch users exactly matching the given givenName and familyName * @should fetch voided users whenincludeVoided is true * @should not fetch any voided users when includeVoided is false * @should not fetch any duplicate users */ @Authorized( { PrivilegeConstants.GET_USERS }) public List<User> getUsersByName(String givenName, String familyName, boolean includeRetired) throws APIException; /** * Get all user accounts that belong to a given person. * * @param person * @param includeRetired * @return all user accounts that belong to person, including retired ones if specified * @throws APIException * @should fetch all accounts for a person when include retired is true * @should not fetch retired accounts when include retired is false */ @Authorized( { PrivilegeConstants.GET_USERS }) public List<User> getUsersByPerson(Person person, boolean includeRetired) throws APIException; /** * Adds the <code>key</code>/<code>value</code> pair to the given <code>user</code>. * <p> * <b>Implementations of this method should handle privileges</b> * * @param user * @param key * @param value * @return the user that was passed in and added to * @should return null if user is null * @should throw error when user is not authorized to edit users * @should add property with given key and value when key does not already exist * @should modify property with given key and value when key already exists */ public User setUserProperty(User user, String key, String value) throws APIException; /** * Removes the property denoted by <code>key</code> from the <code>user</code>'s properties. * <b>Implementations of this method should handle privileges</b> * * @param user * @param key * @return the user that was passed in and removed from * @should return null if user is null * @should throw error when user is not authorized to edit users * @should remove user property for given user and key */ public User removeUserProperty(User user, String key) throws APIException; /** * Get/generate/find the next system id to be doled out. Assume check digit /not/ applied in * this method * * @return new system id */ public String generateSystemId(); /** * Return a batch of users of a specific size sorted by personName (see * {@link PersonByNameComparator}) if any part of the search matches first/last/system id and * the user has one at least one of the given <code>roles</code> assigned to them. If start and * length are not specified, then all matches are returned, If name is empty or null, then all * all users will be returned taking into consideration the values of start and length * arguments. * * @param name string to compare to the beginning of user's given/middle/family/family2 names * @param roles all the Roles the user must contain * @param includeRetired true/false whether to include voided users * @param start beginning index for the batch * @param length number of users to return in the batch * @return list of matching users of a size based on the specified arguments * @since 1.8 * @should return users whose roles inherit requested roles */ @Authorized( { PrivilegeConstants.GET_USERS }) public List<User> getUsers(String name, List<Role> roles, boolean includeRetired, Integer start, Integer length) throws APIException; /** * Return the number of users with a matching name or system id and have at least one of the * given roles assigned to them * * @param name patient name * @param roles all the Roles the user must contain * @param includeRetired Specifies whether voided users should be included * @return the number of users matching the given attributes * @since 1.8 */ @Authorized( { PrivilegeConstants.GET_USERS }) public Integer getCountOfUsers(String name, List<Role> roles, boolean includeRetired); /** * Notifies privilege listener beans about any privilege check. * <p> * It is called by {@link UserContext#hasPrivilege(java.lang.String)}. * * @see PrivilegeListener * @param user the authenticated user or <code>null</code> if not authenticated * @param privilege the checked privilege * @param hasPrivilege <code>true</code> if the authenticated user has the required privilege or * if it is a proxy privilege * @since 1.8.4, 1.9.1, 1.10 */ public void notifyPrivilegeListeners(User user, String privilege, boolean hasPrivilege); /** * Saves the current key/value as a user property for the current user. * * @param key the authenticated user's property * @param value value of the property * @since 1.10 */ @Authorized public User saveUserProperty(String key, String value); /** * Replaces all user properties with the given map of properties for the current user * * @param properties the authenticated user's properties * @since 1.10 */ @Authorized public User saveUserProperties(Map<String, String> properties); /** * Change user password given the answer to the secret question * @param secretAnswer the answer to secret question * @param pw the new password * @should update password if secret is correct * @should not update password if secret is not correct */ @Authorized public void changePasswordUsingSecretAnswer(String secretAnswer, String pw) throws APIException; }