• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmrs / openmrs-core / 18321298560

07 Oct 2025 05:43PM UTC coverage: 65.263% (-0.001%) from 65.264%
18321298560

push

github

web-flow
TRUNK-6435: Password resets must go through service API (#5379)

58 of 76 new or added lines in 3 files covered. (76.32%)

6 existing lines in 5 files now uncovered.

23689 of 36298 relevant lines covered (65.26%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.28
/api/src/main/java/org/openmrs/api/db/hibernate/HibernateUserDAO.java
1
/**
2
 * This Source Code Form is subject to the terms of the Mozilla Public License,
3
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
4
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6
 *
7
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8
 * graphic logo is a trademark of OpenMRS Inc.
9
 */
10
package org.openmrs.api.db.hibernate;
11

12
import javax.persistence.Query;
13
import javax.persistence.criteria.CriteriaBuilder;
14
import javax.persistence.criteria.CriteriaQuery;
15
import javax.persistence.criteria.Join;
16
import javax.persistence.criteria.Predicate;
17
import javax.persistence.criteria.Root;
18
import java.util.ArrayList;
19
import java.util.Date;
20
import java.util.HashMap;
21
import java.util.Iterator;
22
import java.util.List;
23
import java.util.Map;
24

25
import org.apache.commons.collections.CollectionUtils;
26
import org.apache.commons.lang3.StringUtils;
27
import org.hibernate.Session;
28
import org.hibernate.SessionFactory;
29
import org.openmrs.Person;
30
import org.openmrs.PersonName;
31
import org.openmrs.Privilege;
32
import org.openmrs.Role;
33
import org.openmrs.User;
34
import org.openmrs.api.context.Context;
35
import org.openmrs.api.context.Daemon;
36
import org.openmrs.api.db.DAOException;
37
import org.openmrs.api.db.LoginCredential;
38
import org.openmrs.api.db.UserDAO;
39
import org.openmrs.api.impl.UserServiceImpl;
40
import org.openmrs.patient.impl.LuhnIdentifierValidator;
41
import org.openmrs.util.OpenmrsConstants;
42
import org.openmrs.util.Security;
43
import org.openmrs.util.UserByNameComparator;
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

47
/**
48
 * Hibernate specific database methods for the UserService
49
 * 
50
 * @see org.openmrs.api.context.Context
51
 * @see org.openmrs.api.db.UserDAO
52
 * @see org.openmrs.api.UserService
53
 */
54
public class HibernateUserDAO implements UserDAO {
1✔
55
        
56
        private static final Logger log = LoggerFactory.getLogger(HibernateUserDAO.class);
1✔
57
        
58
        /**
59
         * Hibernate session factory
60
         */
61
        private SessionFactory sessionFactory;
62
        
63
        /**
64
         * Set session factory
65
         * 
66
         * @param sessionFactory
67
         */
68
        public void setSessionFactory(SessionFactory sessionFactory) {
69
                this.sessionFactory = sessionFactory;
1✔
70
        }
1✔
71
        
72
        /**
73
         * @see org.openmrs.api.UserService#saveUser(org.openmrs.User, java.lang.String)
74
         */
75
        @Override
76
        public User saveUser(User user, String password) {
77
                StackTraceElement[] stack = new Exception().getStackTrace();
1✔
78
                if (stack.length < 2) {
1✔
NEW
79
                        throw new DAOException("Could not determine where change password was called from");
×
80
                }
81
                StackTraceElement caller = stack[1];
1✔
82
                String callerClass = caller.getClassName();
1✔
83

84
                if (!"org.openmrs.api.db.UserDAOTest".equals(callerClass) &&
1✔
85
                        !UserServiceImpl.class.getName().equals(callerClass) &&
1✔
86
                    !HibernateUserDAO.class.getName().equals(callerClass)) {
1✔
NEW
87
                        throw new DAOException("Illegal attempt to change user password from unknown caller");
×
88
                }
89
                
90
                // only change the user's password when creating a new user
91
                boolean isNewUser = user.getUserId() == null;
1✔
92
                
93
                sessionFactory.getCurrentSession().saveOrUpdate(user);
1✔
94
                
95
                if (isNewUser && password != null) {
1✔
96
                        /* In OpenMRS, we are using generation strategy as native which will convert to IDENTITY 
97
                         for MySQL and SEQUENCE for PostgreSQL. When using IDENTITY strategy, hibernate directly 
98
                         issues insert statements where as with  SEQUENCE strategy hibernate only increments 
99
                         sequences and issues insert on session flush ( batching is possible) . 
100
                         PostgreSQL behaves differently than MySQL because it makes use of SEQUENCE strategy. 
101
                        */
102
                        sessionFactory.getCurrentSession().flush();
1✔
103
                        
104
                        //update the new user with the password
105
                        String salt = Security.getRandomToken();
1✔
106
                        String hashedPassword = Security.encodeString(password + salt);
1✔
107
                        
108
                        updateUserPassword(hashedPassword, salt, Context.getAuthenticatedUser().getUserId(), new Date(), user
1✔
109
                                .getUserId());
1✔
110
                }
111
                
112
                return user;
1✔
113
        }
114
        
115
        /**
116
         * @see org.openmrs.api.UserService#getUserByUsername(java.lang.String)
117
         */
118
        @Override
119
        @SuppressWarnings("unchecked")
120
        public User getUserByUsername(String username) {
121
                Query query = sessionFactory.getCurrentSession().createQuery(
1✔
122
                    "from User u where u.retired = '0' and (u.username = ?0 or u.systemId = ?1)");
123
                query.setParameter(0, username);
1✔
124
                query.setParameter(1, username);
1✔
125
                List<User> users = query.getResultList();
1✔
126
                
127
                if (users == null || users.isEmpty()) {
1✔
128
                        log.warn("request for username '" + username + "' not found");
1✔
129
                        return null;
1✔
130
                }
131
                
132
                return users.get(0);
1✔
133
        }
134
        
135
        /**
136
         * @see org.openmrs.api.UserService#getUserByEmail(java.lang.String)
137
         */
138
        @Override
139
        public User getUserByEmail(String email) {
140
                Session session = sessionFactory.getCurrentSession();
1✔
141
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
142
                CriteriaQuery<User> cq = cb.createQuery(User.class);
1✔
143
                Root<User> root = cq.from(User.class);
1✔
144

145
                cq.where(cb.equal(cb.lower(root.get("email")), email.toLowerCase()));
1✔
146

147
                return session.createQuery(cq).uniqueResult();
1✔
148
        }
149
        
150
        /**
151
         * @see org.openmrs.api.db.UserDAO#getLoginCredentialByActivationKey(java.lang.String)
152
         */
153
        @Override
154
        public LoginCredential getLoginCredentialByActivationKey(String activationKey) {
155
                String key = Security.encodeString(activationKey);
1✔
156
                Session session = sessionFactory.getCurrentSession();
1✔
157
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
158
                CriteriaQuery<LoginCredential> cq = cb.createQuery(LoginCredential.class);
1✔
159
                Root<LoginCredential> root = cq.from(LoginCredential.class);
1✔
160

161
                cq.where(cb.like(cb.lower(root.get("activationKey")), MatchMode.START.toCaseSensitivePattern(key)));
1✔
162

163
                LoginCredential loginCred = session.createQuery(cq).uniqueResult();
1✔
164

165
                if(loginCred != null) {
1✔
166
                        String[] credTokens = loginCred.getActivationKey().split(":");
1✔
167
                        if(credTokens[0].equals(key)){
1✔
168
                                return loginCred;
1✔
169
                        }
170
                }
171
                return null;
1✔
172
        }
173
        
174
        /**
175
         * @see org.openmrs.api.UserService#hasDuplicateUsername(org.openmrs.User)
176
         */
177
        @Override
178
        public boolean hasDuplicateUsername(String username, String systemId, Integer userId) {
179
                if (username == null || username.length() == 0) {
1✔
180
                        username = "-";
1✔
181
                }
182
                if (systemId == null || systemId.length() == 0) {
1✔
183
                        systemId = "-";
×
184
                }
185
                
186
                if (userId == null) {
1✔
187
                        userId = -1;
1✔
188
                }
189
                
190
                String usernameWithCheckDigit = username;
1✔
191
                try {
192
                        //Hardcoding in Luhn since past user IDs used this validator.
193
                        usernameWithCheckDigit = new LuhnIdentifierValidator().getValidIdentifier(username);
1✔
194
                }
195
                catch (Exception e) {}
1✔
196
                
197
                Query query = sessionFactory
1✔
198
                        .getCurrentSession()
1✔
199
                        .createQuery(
1✔
200
                            "select count(*) from User u where (u.username = :uname1 or u.systemId = :uname2 or u.username = :sysid1 or u.systemId = :sysid2 or u.systemId = :uname3) and u.userId <> :uid");
201
                query.setParameter("uname1", username);
1✔
202
                query.setParameter("uname2", username);
1✔
203
                query.setParameter("sysid1", systemId);
1✔
204
                query.setParameter("sysid2", systemId);
1✔
205
                query.setParameter("uname3", usernameWithCheckDigit);
1✔
206
                query.setParameter("uid", userId);
1✔
207
                
208
                Long count = JpaUtils.getSingleResultOrNull(query);
1✔
209
                
210
                log.debug("# users found: " + count);
1✔
211
                return (count != null && count != 0);
1✔
212
        }
213
        
214
        /**
215
         * @see org.openmrs.api.UserService#getUser(java.lang.Integer)
216
         */
217
        @Override
218
        public User getUser(Integer userId) {
219

220
                return sessionFactory.getCurrentSession().get(User.class, userId);
1✔
221
        }
222
        
223
        /**
224
         * @see org.openmrs.api.UserService#getAllUsers()
225
         */
226
        @Override
227
        @SuppressWarnings("unchecked")
228
        public List<User> getAllUsers() throws DAOException {
229
                return sessionFactory.getCurrentSession().createQuery("from User where not uuid = :daemonUserUuid order by userId")
1✔
230
                        .setParameter("daemonUserUuid", Daemon.getDaemonUserUuid()).list();
1✔
231
        }
232
        
233
        /**
234
         * @see org.openmrs.api.UserService#deleteUser(org.openmrs.User)
235
         */
236
        @Override
237
        public void deleteUser(User user) {
238
                sessionFactory.getCurrentSession().delete(user);
1✔
239
        }
1✔
240
        
241
        /**
242
         * @see org.openmrs.api.UserService#getUsersByRole(org.openmrs.Role)
243
         */
244
        public List<User> getUsersByRole(Role role) {
245
                Session session = sessionFactory.getCurrentSession();
×
246
                CriteriaBuilder cb = session.getCriteriaBuilder();
×
247
                CriteriaQuery<User> cq = cb.createQuery(User.class);
×
248
                Root<User> root = cq.from(User.class);
×
249
                Join<User, Role> roles = root.join("roles");
×
250

251
                Predicate roleLike = cb.like(roles.get("role"), role.getRole());
×
252
                Predicate uuidNotEqual = cb.notEqual(root.get("uuid"), Daemon.getDaemonUserUuid());
×
253

254
                cq.where(roleLike, uuidNotEqual).orderBy(cb.asc(root.get("username")));
×
255

256
                return session.createQuery(cq).getResultList();
×
257
        }
258
        
259
        /**
260
         * @see org.openmrs.api.UserService#getAllPrivileges()
261
         */
262
        @Override
263
        @SuppressWarnings("unchecked")
264
        public List<Privilege> getAllPrivileges() throws DAOException {
265
                return sessionFactory.getCurrentSession().createQuery("from Privilege p order by p.privilege").list();
1✔
266
        }
267
        
268
        /**
269
         * @see org.openmrs.api.UserService#getPrivilege(String)
270
         */
271
        @Override
272
        public Privilege getPrivilege(String p) throws DAOException {
273
                return sessionFactory.getCurrentSession().get(Privilege.class, p);
1✔
274
        }
275
        
276
        /**
277
         * @see org.openmrs.api.db.UserDAO#deletePrivilege(org.openmrs.Privilege)
278
         */
279
        @Override
280
        public void deletePrivilege(Privilege privilege) throws DAOException {
281
                sessionFactory.getCurrentSession().delete(privilege);
1✔
282
        }
1✔
283
        
284
        /**
285
         * @see org.openmrs.api.db.UserDAO#savePrivilege(org.openmrs.Privilege)
286
         */
287
        @Override
288
        public Privilege savePrivilege(Privilege privilege) throws DAOException {
289
                sessionFactory.getCurrentSession().saveOrUpdate(privilege);
1✔
290
                return privilege;
1✔
291
        }
292
        
293
        /**
294
         * @see org.openmrs.api.UserService#purgeRole(org.openmrs.Role)
295
         */
296
        @Override
297
        public void deleteRole(Role role) throws DAOException {
298
                sessionFactory.getCurrentSession().delete(role);
1✔
299
        }
1✔
300
        
301
        /**
302
         * @see org.openmrs.api.UserService#saveRole(org.openmrs.Role)
303
         */
304
        @Override
305
        public Role saveRole(Role role) throws DAOException {
306
                sessionFactory.getCurrentSession().saveOrUpdate(role);
1✔
307
                return role;
1✔
308
        }
309
        
310
        /**
311
         * @see org.openmrs.api.UserService#getAllRoles()
312
         */
313
        @Override
314
        @SuppressWarnings("unchecked")
315
        public List<Role> getAllRoles() throws DAOException {
316
                return sessionFactory.getCurrentSession().createQuery("from Role r order by r.role").list();
1✔
317
        }
318
        
319
        /**
320
         * @see org.openmrs.api.UserService#getRole(String)
321
         */
322
        @Override
323
        public Role getRole(String r) throws DAOException {
324
                return sessionFactory.getCurrentSession().get(Role.class, r);
1✔
325
        }
326
        
327
        /**
328
         * @see org.openmrs.api.db.UserDAO#changePassword(org.openmrs.User, java.lang.String)
329
         */
330
        public void changePassword(User u, String pw) throws DAOException {
331
                StackTraceElement[] stack = new Exception().getStackTrace();
1✔
332
                if (stack.length < 2) {
1✔
NEW
333
                        throw new DAOException("Could not determine where change password was called from");
×
334
                }
335
                StackTraceElement caller = stack[1];
1✔
336
                String callerClass = caller.getClassName();
1✔
337

338
                if (!"org.openmrs.api.db.UserDAOTest".equals(callerClass) &&
1✔
339
                        !UserServiceImpl.class.getName().equals(callerClass)) {
1✔
340
                        throw new DAOException("Illegal attempt to change user password from unknown caller");
1✔
341
                }
342
                
343
                User authUser = Context.getAuthenticatedUser();
1✔
344
                
345
                if (authUser == null) {
1✔
346
                        authUser = u;
×
347
                }
348
                
349
                String salt = getLoginCredential(u).getSalt();
1✔
350
                if (StringUtils.isBlank(salt)) {
1✔
351
                        salt = Security.getRandomToken();
1✔
352
                }
353
                String newHashedPassword = Security.encodeString(pw + salt);
1✔
354
                
355
                updateUserPassword(newHashedPassword, salt, authUser.getUserId(), new Date(), u.getUserId());
1✔
356
        }
1✔
357
        
358
        /**
359
         * @see org.openmrs.api.db.UserDAO#changeHashedPassword(User, String, String)
360
         */
361
        @Override
362
        public void changeHashedPassword(User user, String hashedPassword, String salt) throws DAOException {
363
                StackTraceElement[] stack = new Exception().getStackTrace();
1✔
364
                if (stack.length < 2) {
1✔
NEW
365
                        throw new DAOException("Could not determine where change password was called from");
×
366
                }
367
                StackTraceElement caller = stack[1];
1✔
368
                String callerClass = caller.getClassName();
1✔
369

370
                if (!"org.openmrs.api.db.UserDAOTest".equals(callerClass) &&
1✔
371
                        !UserServiceImpl.class.getName().equals(callerClass)) {
1✔
NEW
372
                        throw new DAOException("Illegal attempt to change user password from unknown caller");
×
373
                }
374
                
375
                User authUser = Context.getAuthenticatedUser();
1✔
376
                updateUserPassword(hashedPassword, salt, authUser.getUserId(), new Date(), user.getUserId());
1✔
377
        }
1✔
378
        
379
        /**
380
         * @param newHashedPassword
381
         * @param salt
382
         * @param userId
383
         * @param date
384
         * @param userId2
385
         */
386
        private void updateUserPassword(String newHashedPassword, String salt, Integer changedBy, Date dateChanged,
387
                Integer userIdToChange) {
388
                User changeForUser = getUser(userIdToChange);
1✔
389
                if (changeForUser == null) {
1✔
390
                        throw new DAOException("Couldn't find user to set password for userId=" + userIdToChange);
×
391
                }
392
                User changedByUser = getUser(changedBy);
1✔
393
                LoginCredential credentials = getLoginCredential(changeForUser);
1✔
394
                credentials.setUserId(userIdToChange);
1✔
395
                credentials.setHashedPassword(newHashedPassword);
1✔
396
                credentials.setSalt(salt);
1✔
397
                credentials.setChangedBy(changedByUser);
1✔
398
                credentials.setDateChanged(dateChanged);
1✔
399
                credentials.setUuid(changeForUser.getUuid());
1✔
400
                
401
                sessionFactory.getCurrentSession().merge(credentials);
1✔
402
                
403
                // reset lockout 
404
                changeForUser.setUserProperty(OpenmrsConstants.USER_PROPERTY_LOCKOUT_TIMESTAMP, "");
1✔
405
                changeForUser.setUserProperty(OpenmrsConstants.USER_PROPERTY_LOGIN_ATTEMPTS, OpenmrsConstants.ZERO_LOGIN_ATTEMPTS_VALUE);
1✔
406
                saveUser(changeForUser, null);
1✔
407
        }
1✔
408
        
409
        /**
410
         * @see org.openmrs.api.UserService#changePassword(java.lang.String, java.lang.String)
411
         */
412
        @Override
413
        public void changePassword(String oldPassword, String newPassword) throws DAOException {
414
                StackTraceElement[] stack = new Exception().getStackTrace();
1✔
415
                if (stack.length < 2) {
1✔
NEW
416
                        throw new DAOException("Could not determine where change password was called from");
×
417
                }
418
                StackTraceElement caller = stack[1];
1✔
419
                String callerClass = caller.getClassName();
1✔
420

421
                if (!"org.openmrs.api.db.UserDAOTest".equals(callerClass) &&
1✔
NEW
422
                        !UserServiceImpl.class.getName().equals(callerClass)) {
×
NEW
423
                        throw new DAOException("Illegal attempt to change user password from unknown caller");
×
424
                }
425
                
426
                User u = Context.getAuthenticatedUser();
1✔
427
                LoginCredential credentials = getLoginCredential(u);
1✔
428
                if (!credentials.checkPassword(oldPassword)) {
1✔
429
                        log.error("Passwords don't match");
×
430
                        throw new DAOException("Passwords don't match");
×
431
                }
432
                
433
                log.info("updating password for {}", u.getUsername());
1✔
434
                
435
                // update the user with the new password
436
                String salt = credentials.getSalt();
1✔
437
                String newHashedPassword = Security.encodeString(newPassword + salt);
1✔
438
                updateUserPassword(newHashedPassword, salt, u.getUserId(), new Date(), u.getUserId());
1✔
439
        }
1✔
440
        
441
        /**
442
         * @see org.openmrs.api.UserService#changeQuestionAnswer(java.lang.String, java.lang.String,
443
         *      java.lang.String)
444
         */
445
        @Override
446
        public void changeQuestionAnswer(String pw, String question, String answer) throws DAOException {
447
                User u = Context.getAuthenticatedUser();
1✔
448
                
449
                LoginCredential credentials = getLoginCredential(u);
1✔
450
                if (!credentials.checkPassword(pw)) {
1✔
451
                        log.error("Passwords don't match");
×
452
                        throw new DAOException("Passwords don't match");
×
453
                }
454
                
455
                changeQuestionAnswer(u, question, answer);
1✔
456
        }
1✔
457
        
458
        /**
459
         * @see org.openmrs.api.UserService#changeQuestionAnswer(User, String, String)
460
         */
461
        @Override
462
        public void changeQuestionAnswer(User u, String question, String answer) throws DAOException {
463
                log.info("Updating secret question and answer for " + u.getUsername());
1✔
464
                
465
                LoginCredential credentials = getLoginCredential(u);
1✔
466
                credentials.setSecretQuestion(question);
1✔
467
                String hashedAnswer = Security.encodeString(answer.toLowerCase() + credentials.getSalt());
1✔
468
                credentials.setSecretAnswer(hashedAnswer);
1✔
469
                credentials.setDateChanged(new Date());
1✔
470
                credentials.setChangedBy(u);
1✔
471
                
472
                updateLoginCredential(credentials);
1✔
473
        }
1✔
474
        
475
        /**
476
         * @see org.openmrs.api.UserService#isSecretAnswer(User, java.lang.String)
477
         */
478
        @Override
479
        public boolean isSecretAnswer(User u, String answer) throws DAOException {
480
                
481
                if (StringUtils.isEmpty(answer)) {
1✔
482
                        return false;
×
483
                }
484
                
485
                LoginCredential credentials = getLoginCredential(u);
1✔
486
                String answerOnRecord = credentials.getSecretAnswer();
1✔
487
                String hashedAnswer = Security.encodeString(answer.toLowerCase() + credentials.getSalt());
1✔
488
                return (hashedAnswer.equals(answerOnRecord));
1✔
489
        }
490
        
491
        /**
492
         * @see UserDAO#getUsers(String, List, boolean, Integer, Integer)
493
         */
494
        @Override
495
        @SuppressWarnings("unchecked")
496
        public List<User> getUsers(String name, List<Role> roles, boolean includeRetired, Integer start, Integer length) {
497
                
498
                String hqlSelectStart = "select distinct user from User as user inner join user.person.names as name ";
1✔
499
                Query query = createUserSearchQuery(name, roles, includeRetired, hqlSelectStart);
1✔
500
                
501
                if (start != null) {
1✔
502
                        query.setFirstResult(start);
×
503
                }
504
                if (length != null && length > 0) {
1✔
505
                        query.setMaxResults(length);
×
506
                }
507
                
508
                List<User> returnList = query.getResultList();
1✔
509
                
510
                if (!CollectionUtils.isEmpty(returnList)) {
1✔
511
                        returnList.sort(new UserByNameComparator());
1✔
512
                }
513
                
514
                return returnList;
1✔
515
        }
516
        
517
        /**
518
         * @see org.openmrs.api.UserService#generateSystemId()
519
         */
520
        @Override
521
        public Integer generateSystemId() {
522
                
523
                String hql = "select max(userId) from User";
1✔
524
                
525
                Query query = sessionFactory.getCurrentSession().createQuery(hql);
1✔
526
                
527
                Object object = JpaUtils.getSingleResultOrNull(query);
1✔
528
                
529
                Integer id;
530
                if (object instanceof Number) {
1✔
531
                        id = ((Number) JpaUtils.getSingleResultOrNull(query)).intValue() + 1;
1✔
532
                } else {
533
                        log.warn("What is being returned here? Definitely nothing expected object value: '" + object + "' of class: "
×
534
                                + object.getClass());
×
535
                        id = 1;
×
536
                }
537
                
538
                return id;
1✔
539
        }
540
        
541
        /**
542
         * @see org.openmrs.api.UserService#getUsersByName(java.lang.String, java.lang.String, boolean)
543
         */
544
        @Override
545
        public List<User> getUsersByName(String givenName, String familyName, boolean includeRetired) {
546
                Session session = sessionFactory.getCurrentSession();
1✔
547
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
548
                CriteriaQuery<User> cq = cb.createQuery(User.class);
1✔
549
                Root<User> root = cq.from(User.class);
1✔
550

551
                Join<User, Person> personJoin = root.join("person");
1✔
552
                Join<Person, PersonName> nameJoin = personJoin.join("names");
1✔
553

554
                List<Predicate> predicates = new ArrayList<>();
1✔
555
                predicates.add(cb.equal(nameJoin.get("givenName"), givenName));
1✔
556
                predicates.add(cb.equal(nameJoin.get("familyName"), familyName));
1✔
557
                predicates.add(cb.notEqual(root.get("uuid"), Daemon.getDaemonUserUuid()));
1✔
558

559

560
                if (!includeRetired) {
1✔
561
                        predicates.add(cb.isFalse(root.get("retired")));
1✔
562
                }
563

564
                cq.where(predicates.toArray(predicates.toArray(new Predicate[]{}))).distinct(true);
1✔
565

566
                return new ArrayList<>(session.createQuery(cq).getResultList());
1✔
567
        }
568
        
569
        /**
570
         * @see org.openmrs.api.db.UserDAO#getPrivilegeByUuid(java.lang.String)
571
         */
572
        @Override
573
        public Privilege getPrivilegeByUuid(String uuid) {
574
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, Privilege.class, uuid);
1✔
575
        }
576
        
577
        /**
578
         * @see org.openmrs.api.db.UserDAO#getRoleByUuid(java.lang.String)
579
         */
580
        @Override
581
        public Role getRoleByUuid(String uuid) {
582
                return HibernateUtil.getUniqueEntityByUUID(sessionFactory, Role.class, uuid);
1✔
583
        }
584
        
585
        /**
586
         * @see org.openmrs.api.db.UserDAO#getUserByUuid(java.lang.String)
587
         */
588
        @Override
589
        public User getUserByUuid(String uuid) {
590
                User ret = null;
1✔
591
                
592
                if (uuid != null) {
1✔
593
                        uuid = uuid.trim();
1✔
594
                        ret = HibernateUtil.getUniqueEntityByUUID(sessionFactory, User.class, uuid);
1✔
595
                }
596
                
597
                return ret;
1✔
598
        }
599
        
600
        /**
601
         * @see org.openmrs.api.db.UserDAO#getLoginCredential(org.openmrs.User)
602
         */
603
        @Override
604
        public LoginCredential getLoginCredential(User user) {
605
                return sessionFactory.getCurrentSession().get(LoginCredential.class, user.getUserId());
1✔
606
        }
607
        
608
        /**
609
         * @see org.openmrs.api.db.UserDAO#getLoginCredential(org.openmrs.User)
610
         */
611
        @Override
612
        public LoginCredential getLoginCredentialByUuid(String uuid) {
613
                if (uuid == null) {
×
614
                        return null;
×
615
                } else {
616
                        return HibernateUtil.getUniqueEntityByUUID(sessionFactory, LoginCredential.class, uuid.trim());
×
617
                }
618
        }
619
        
620
        /**
621
         * @see org.openmrs.api.db.UserDAO#updateLoginCredential(LoginCredential)
622
         */
623
        @Override
624
        public void updateLoginCredential(LoginCredential credential) {
625
                sessionFactory.getCurrentSession().update(credential);
1✔
626
        }
1✔
627
        
628
        /**
629
         * @see org.openmrs.api.db.UserDAO#getUsersByPerson(org.openmrs.Person, boolean)
630
         */
631
        @Override
632
        public List<User> getUsersByPerson(Person person, boolean includeRetired) {
633
                Session session = sessionFactory.getCurrentSession();
1✔
634
                CriteriaBuilder cb = session.getCriteriaBuilder();
1✔
635
                CriteriaQuery<User> cq = cb.createQuery(User.class);
1✔
636
                Root<User> root = cq.from(User.class);
1✔
637

638
                List<Predicate> predicates = new ArrayList<>();
1✔
639
                predicates.add(cb.notEqual(root.get("uuid"), Daemon.getDaemonUserUuid()));
1✔
640

641
                if (person != null) {
1✔
642
                        predicates.add(cb.equal(root.get("person"), person));
1✔
643
                }
644
                if (!includeRetired) {
1✔
645
                        predicates.add(cb.isFalse(root.get("retired")));
1✔
646
                }
647

648
                cq.where(predicates.toArray(new Predicate[]{}));
1✔
649
                return session.createQuery(cq).getResultList();
1✔
650
        }
651
        
652
        /**
653
         * @see org.openmrs.api.db.UserDAO#getCountOfUsers(String, List, boolean)
654
         */
655
        @Override
656
        public Integer getCountOfUsers(String name, List<Role> roles, boolean includeRetired) {
657
                String hqlSelectStart = "select count(distinct user) from User as user inner join user.person.names as name ";
×
658
                Query query = createUserSearchQuery(name, roles, includeRetired, hqlSelectStart);
×
659
                
660
                return ((Long) JpaUtils.getSingleResultOrNull(query)).intValue();
×
661
        }
662
        
663
        /**
664
         * Utility methods that creates a hibernate query object from the specified arguments
665
         * 
666
         * @param name The name of the user to search against
667
         * @param roles the roles to match against
668
         * @param includeRetired Specifies if retired users should be included or not
669
         * @param hqlSelectStart The starting phrase of the select statement that includes the joined
670
         *            tables
671
         * @return the created hibernate query object
672
         */
673
        private Query createUserSearchQuery(String name, List<Role> roles, boolean includeRetired, String hqlSelectStart) {
674
                
675
                log.debug("name: " + name);
1✔
676
                
677
                name = HibernateUtil.escapeSqlWildcards(name, sessionFactory);
1✔
678
                
679
                // Create an HQL query like this:
680
                // select distinct user
681
                // from User as user inner join user.person.names as name inner join user.roles as role
682
                // where (user.username like :name1 or ...and for systemId givenName familyName familyName2...)
683
                //   and (user.username like :name2 or ...and for systemId givenName familyName familyName2...)
684
                //   ...repeat for all name fragments...
685
                //         and role in :roleList 
686
                //   and user.retired = false
687
                // order by username asc
688
                List<String> criteria = new ArrayList<>();
1✔
689
                int counter = 0;
1✔
690
                Map<String, String> namesMap = new HashMap<>();
1✔
691
                if (name != null) {
1✔
692
                        name = name.replace(", ", " ");
1✔
693
                        String[] names = name.split(" ");
1✔
694
                        for (String n : names) {
1✔
695
                                if (n != null && n.length() > 0) {
1✔
696
                                        // compare each fragment of the query against username, systemId, given, middle, family, and family2
697
                                        String key = "name" + ++counter;
1✔
698
                                        String value = n + "%";
1✔
699
                                        namesMap.put(key, value);
1✔
700
                                        criteria.add("(user.username like :" + key + " or user.systemId like :" + key
1✔
701
                                                + " or name.givenName like :" + key + " or name.middleName like :" + key
702
                                                + " or name.familyName like :" + key + " or name.familyName2 like :" + key + ")");
703
                                }
704
                        }
705
                }
706
                
707
                if (!includeRetired) {
1✔
708
                        criteria.add("user.retired = false");
1✔
709
                }
710
                
711
                // build the hql query
712
                StringBuilder hql = new StringBuilder(hqlSelectStart);
1✔
713
                boolean searchOnRoles = false;
1✔
714
                
715
                if (CollectionUtils.isNotEmpty(roles)) {
1✔
716
                        hql.append("inner join user.roles as role ");
1✔
717
                        searchOnRoles = true;
1✔
718
                }
719
                hql.append("where user.uuid != :DAEMON_USER_UUID ");
1✔
720
                
721
                if (!criteria.isEmpty() || searchOnRoles) {
1✔
722
                        hql.append("and ");
1✔
723
                }
724
                for (Iterator<String> i = criteria.iterator(); i.hasNext();) {
1✔
725
                        hql.append(i.next()).append(" ");
1✔
726
                        if (i.hasNext()) {
1✔
727
                                hql.append("and ");
1✔
728
                        }
729
                }
730
                
731
                //Match against the specified roles
732
                if (searchOnRoles) {
1✔
733
                        if (!criteria.isEmpty()) {
1✔
734
                                hql.append(" and ");
1✔
735
                        }
736
                        hql.append(" role in (:roleList)");
1✔
737
                }
738
                
739
                Query query = sessionFactory.getCurrentSession().createQuery(hql.toString());
1✔
740
                query.setParameter("DAEMON_USER_UUID", Daemon.getDaemonUserUuid());
1✔
741
                for (Map.Entry<String, String> e : namesMap.entrySet()) {
1✔
742
                        query.setParameter(e.getKey(), e.getValue());
1✔
743
                }
1✔
744
                
745
                if (searchOnRoles) {
1✔
746
                        query.setParameter("roleList", roles);
1✔
747
                }
748
                
749
                return query;
1✔
750
        }
751
        
752
        /**
753
         * @see org.openmrs.api.db.UserDAO#createActivationKey(org.openmrs.User)
754
         */
755
        @Override
756
        public void setUserActivationKey(LoginCredential credentials) {                
757
                        sessionFactory.getCurrentSession().merge(credentials);        
1✔
758
        }
1✔
759

760
        /**
761
         * @see org.openmrs.api.db.UserDAO#getLastLoginTime(org.openmrs.User)
762
         */
763
        @Override
764
        public String getLastLoginTime(User user) {
765
                return user.getUserProperty(OpenmrsConstants.USER_PROPERTY_LAST_LOGIN_TIMESTAMP);
1✔
766
        }
767
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc