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

openmrs / openmrs-core / 36476868921

28 Sep 2026 08:06PM UTC coverage: 66.046% (-0.06%) from 66.105%
36476868921

push

github

ibacher
Test improvements: in-memory search index and speed-up metadata reads

25524 of 38646 relevant lines covered (66.05%)

0.66 hits per line

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

87.23
/api/src/main/java/org/openmrs/api/context/UserContext.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.context;
11

12
import org.apache.commons.lang3.StringUtils;
13
import org.openmrs.Location;
14
import org.openmrs.PrivilegeListener;
15
import org.openmrs.Role;
16
import org.openmrs.User;
17
import org.openmrs.UserSessionListener;
18
import org.openmrs.UserSessionListener.Event;
19
import org.openmrs.UserSessionListener.Status;
20
import org.openmrs.api.APIAuthenticationException;
21
import org.openmrs.api.LocationService;
22
import org.openmrs.api.cache.RolePrivilegeCache;
23
import org.openmrs.api.cache.RolePrivileges;
24
import org.openmrs.util.LocaleUtility;
25
import org.openmrs.util.OpenmrsConstants;
26
import org.openmrs.util.RoleConstants;
27
import org.slf4j.Logger;
28
import org.slf4j.LoggerFactory;
29

30
import java.io.Serializable;
31
import java.util.ArrayList;
32
import java.util.Arrays;
33
import java.util.Collections;
34
import java.util.HashSet;
35
import java.util.List;
36
import java.util.Locale;
37
import java.util.Objects;
38
import java.util.Set;
39
import java.util.concurrent.atomic.AtomicBoolean;
40

41
/**
42
 * Represents an OpenMRS <code>User Context</code> which stores the current user information. Only
43
 * one <code>User</code> may be authenticated within a UserContext at any given time. The
44
 * UserContext should not be accessed directly, but rather used through the <code>Context</code>.
45
 * This class should be kept light-weight. There is one instance of this class per user that is
46
 * logged into the system.
47
 *
48
 * @see org.openmrs.api.context.Context
49
 */
50
public class UserContext implements Serializable {
51
        
52
        private static final long serialVersionUID = -806631231941890648L;
53
        
54
        /**
55
         * Logger - shared by entire class
56
         */
57
        private static final Logger log = LoggerFactory.getLogger(UserContext.class);
1 ✔
58
        
59
        /**
60
         * Guards the one-time warning emitted when the role privilege cache component cannot be obtained
61
         * outside of a context refresh. Static so the warning is emitted once across all user contexts
62
         * rather than once per session.
63
         */
64
        private static final AtomicBoolean rolePrivilegeCacheUnavailableWarned = new AtomicBoolean(false);
1 ✔
65

66
        /**
67
         * User object containing details about the authenticated user
68
         */
69
        private User user = null;
1 ✔
70
        
71
        /**
72
         * User's permission proxies
73
         */
74
        private final List<String> proxies = Collections.synchronizedList(new ArrayList<>());
1 ✔
75
        
76
        /**
77
         * User's locale
78
         */
79
        private Locale locale = null;
1 ✔
80
        
81
        /**
82
         * Cached Role given to all authenticated users
83
         */
84
        private Role authenticatedRole = null;
1 ✔
85
        
86
        /**
87
         * Cache Role given to all users
88
         */
89
        private Role anonymousRole = null;
1 ✔
90
        
91
        /**
92
         * User's defined location
93
         */
94
        private Integer locationId;
95
        
96
        /**
97
         * The authentication scheme for this user
98
         */
99
        private final AuthenticationScheme authenticationScheme;
100
        
101
        /**
102
         * Creates a user context based on the provided auth. scheme.
103
         *
104
         * @param authenticationScheme The auth. scheme that applies for this user context.
105
         * @since 2.3.0
106
         */
107
        public UserContext(AuthenticationScheme authenticationScheme) {
1 ✔
108
                this.authenticationScheme = authenticationScheme;
1 ✔
109
        }
1 ✔
110
        
111
        /**
112
         * Authenticate user with the provided credentials. The authentication scheme must be Spring wired, see {@link Context#getAuthenticationScheme()}.
113
         *
114
         * @param credentials The credentials to use to authenticate
115
         * @return The authenticated client information
116
         * @throws ContextAuthenticationException if authentication fails
117
         * @since 2.3.0
118
         */
119
        public Authenticated authenticate(Credentials credentials)
120
                throws ContextAuthenticationException {
121
                
122
                log.debug("Authenticating client '{}' with scheme '{}'", credentials.getClientName(),
1 ✔
123
                        credentials.getAuthenticationScheme());
1 ✔
124
                
125
                Authenticated authenticated = null;
1 ✔
126
                try {
127
                        authenticated = authenticationScheme.authenticate(credentials);
1 ✔
128
                        this.user = authenticated.getUser();
1 ✔
129
                        notifyUserSessionListener(this.user, Event.LOGIN, Status.SUCCESS);
1 ✔
130
                }
131
                catch (ContextAuthenticationException e) {
1 ✔
132
                        User loggingInUser = new User();
1 ✔
133
                        loggingInUser.setUsername(credentials.getClientName());
1 ✔
134
                        notifyUserSessionListener(loggingInUser, Event.LOGIN, Status.FAIL);
1 ✔
135
                        throw e;
1 ✔
136
                }
1 ✔
137
                
138
                setUserLocation(true);
1 ✔
139
                setUserLocale(true);
1 ✔
140
                
141
                log.debug("Authenticated as: {}", this.user);
1 ✔
142
                
143
                return authenticated;
1 ✔
144
        }
145
        
146
        /**
147
         * Refresh the authenticated user object in this UserContext. This should be used when updating
148
         * information in the database about the current user and it needs to be reflecting in the
149
         * (cached) {@link #getAuthenticatedUser()} User object.
150
         *
151
         * @since 1.5
152
         */
153
        public void refreshAuthenticatedUser() {
154
                log.debug("Refreshing authenticated user");
1 ✔
155
                
156
                if (user != null) {
1 ✔
157
                        user = Context.getUserService().getUser(user.getUserId());
1 ✔
158
                        //update the stored location in the user's session
159
                        setUserLocation(false);
1 ✔
160
                        setUserLocale(false);
1 ✔
161
                }
162
        }
1 ✔
163
        
164
        /**
165
         * Change current authentication to become another user. (You can only do this if you're already
166
         * authenticated as a superuser.)
167
         *
168
         * @param systemId
169
         * @return The new user that this context has been set to. (null means no change was made)
170
         * @throws ContextAuthenticationException
171
         */
172
        public User becomeUser(String systemId) throws ContextAuthenticationException {
173
                if (!Daemon.isDaemonThread() && !Context.getAuthenticatedUser().isSuperUser()) {
1 ✔
174
                        throw new APIAuthenticationException("You must be a superuser to assume another user's identity");
×
175
                }
176
                
177
                log.debug("Turning the authenticated user into user with systemId: {}", systemId);
1 ✔
178
                
179
                User userToBecome = Context.getUserService().getUserByUsername(systemId);
1 ✔
180
                
181
                if (userToBecome == null) {
1 ✔
182
                        throw new ContextAuthenticationException("User not found with systemId: " + systemId);
×
183
                }
184
                
185
                // hydrate the user object
186
                if (userToBecome.getAllRoles() != null) {
1 ✔
187
                        userToBecome.getAllRoles().size();
1 ✔
188
                }
189
                
190
                if (userToBecome.getUserProperties() != null) {
1 ✔
191
                        userToBecome.getUserProperties().size();
1 ✔
192
                }
193
                
194
                if (userToBecome.getPrivileges() != null) {
1 ✔
195
                        userToBecome.getPrivileges().size();
1 ✔
196
                }
197
                
198
                this.user = userToBecome;
1 ✔
199
                
200
                //update the user's location and locale
201
                setUserLocation(false);
1 ✔
202
                setUserLocale(false);
1 ✔
203
                
204
                log.debug("Becoming user: {}", user);
1 ✔
205
                
206
                return userToBecome;
1 ✔
207
        }
208
        
209
        /**
210
         * @return "active" user who has been authenticated, otherwise <code>null</code>
211
         */
212
        public User getAuthenticatedUser() {
213
                return user;
1 ✔
214
        }
215
        
216
        /**
217
         * @return true if user has been authenticated in this UserContext
218
         */
219
        public boolean isAuthenticated() {
220
                return user != null;
1 ✔
221
        }
222
        
223
        /**
224
         * logs out the "active" (authenticated) user within this UserContext
225
         *
226
         * @see #authenticate
227
         */
228
        public void logout() {
229
                log.debug("setting user to null on logout");
1 ✔
230
                notifyUserSessionListener(user, Event.LOGOUT, Status.SUCCESS);
1 ✔
231
                user = null;
1 ✔
232
                locationId = null;
1 ✔
233
                locale = null;
1 ✔
234
                proxies.clear();
1 ✔
235
        }
1 ✔
236
        
237
        /**
238
         * Gives the given privilege to all calls to hasPrivilege. This method was visualized as being
239
         * used as follows (try/finally is important):
240
         *
241
         * <pre>
242
         * try {
243
         *   Context.addProxyPrivilege(&quot;AAA&quot;);
244
         *   Context.get*Service().methodRequiringAAAPrivilege();
245
         * }
246
         * finally {
247
         *   Context.removeProxyPrivilege(&quot;AAA&quot;);
248
         * }
249
         * </pre>
250
         *
251
         * @param privilege to give to users
252
         */
253
        public void addProxyPrivilege(String privilege) {
254
                if (privilege == null) {
1 ✔
255
                        throw new IllegalArgumentException("UserContext.addProxyPrivilege does not accept null privileges");
1 ✔
256
                }
257

258
                log.debug("Adding proxy privilege: {}", privilege);
1 ✔
259
                proxies.add(privilege);
1 ✔
260
        }
1 ✔
261
        
262
        /**
263
         * Will remove one instance of privilege from the privileges that are currently proxied
264
         *
265
         * @param privilege Privilege to remove in string form
266
         */
267
        public void removeProxyPrivilege(String privilege) {
268
                if (privilege == null) {
1 ✔
269
                        return;
1 ✔
270
                }
271

272
                log.debug("Removing privilege: {}", privilege);
1 ✔
273
                proxies.remove(privilege);
1 ✔
274
        }
1 ✔
275
        
276
        /**
277
         * Adds one or more privileges to the list of privileges that that {@link #hasPrivilege(String)} will
278
         * regard as available regardless of whether the user would otherwise have the privilege.
279
         * <p/>
280
         * This is useful for situations where a system process may need access to some piece of data that the
281
         * user would not otherwise have access to, like a GlobalProperty. <strong>This facility should not be
282
         * used to return data to the user that they otherwise would be unable to see.</strong>
283
         * <p/>
284
         * The expected usage is:
285
         * <p/>
286
         * <pre>{@code
287
         * try {
288
         *   Context.addProxyPrivilege(&quot;AAA&quot;);
289
         *   Context.get*Service().methodRequiringAAAPrivilege();
290
         * }
291
         * finally {
292
         *   Context.removeProxyPrivilege(&quot;AAA&quot;);
293
         * }}
294
         * </pre>
295
         * <p/>
296
         *
297
         * @param privileges privileges to add in string form
298
         * @see #hasPrivilege(String)
299
         * @see #removeProxyPrivilege(String...)
300
         */
301
        public void addProxyPrivilege(String... privileges) {
302
                if (privileges == null || Arrays.stream(privileges).anyMatch(Objects::isNull)) {
1 ✔
303
                        throw new IllegalArgumentException("UserContext.addProxyPrivilege does not accept null privileges");
1 ✔
304
                }
305
                
306
                for (String privilege : privileges) {
1 ✔
307
                        addProxyPrivilege(privilege);
1 ✔
308
                }
309
        }
1 ✔
310
        
311
        /**
312
         * Removes one or more privileges to the list of privileges that that {@link #hasPrivilege(String)} will
313
         * regard as available regardless of whether the user would otherwise have the privilege.
314
         * <p/>
315
         * This is the compliment for {@link #addProxyPrivilege(String...)} to clean-up the context.
316
         * <p/>
317
         *
318
         * @param privileges privileges to remove in string form
319
         * @see #hasPrivilege(String)
320
         * @see #addProxyPrivilege(String...)
321
         */
322
        public void removeProxyPrivilege(String... privileges) {
323
                if (privileges == null || Arrays.stream(privileges).allMatch(Objects::isNull)) {
1 ✔
324
                        return;
1 ✔
325
                }
326
                
327
                for (String privilege : privileges) {
1 ✔
328
                        if (privilege != null) {
1 ✔
329
                                removeProxyPrivilege(privilege);
1 ✔
330
                        }
331
                }
332
        }
1 ✔
333

334
        /**
335
         * @return true if there are any proxy privileges
336
         * @since 2.9.0
337
         */
338
        public boolean hasProxyPrivileges() {
339
                return !proxies.isEmpty();
1 ✔
340
        }
341
        
342
        /**
343
         * @param locale new locale for this context
344
         */
345
        public void setLocale(Locale locale) {
346
                this.locale = locale;
1 ✔
347
        }
1 ✔
348
        
349
        /**
350
         * @return current locale for this context
351
         */
352
        public Locale getLocale() {
353
                if (locale == null) {
1 ✔
354
                        // don't cache default locale - allows recognition of changed default at login page
355
                        return LocaleUtility.getDefaultLocale();
1 ✔
356
                }
357
                
358
                return locale;
1 ✔
359
        }
360
        
361
        /**
362
         * Gets all the roles for the (un)authenticated user. Anonymous and Authenticated roles are
363
         * appended if necessary
364
         *
365
         * @return all expanded roles for a user
366
         * @throws Exception
367
         */
368
        public Set<Role> getAllRoles() throws Exception {
369
                return getAllRoles(getAuthenticatedUser());
×
370
        }
371
        
372
        /**
373
         * Gets all the roles for a user. Anonymous and Authenticated roles are appended if necessary
374
         *
375
         * @param user
376
         * @return all expanded roles for a user
377
         * <strong>Should</strong> not fail with null user
378
         * <strong>Should</strong> add anonymous role to all users
379
         * <strong>Should</strong> add authenticated role to all authenticated users
380
         * <strong>Should</strong> return same roles as user getAllRoles method
381
         */
382
        public Set<Role> getAllRoles(User user) throws Exception {
383
                Set<Role> roles = new HashSet<>();
×
384
                
385
                // add the Anonymous Role
386
                roles.add(getAnonymousRole());
×
387
                
388
                // add the Authenticated role
389
                if (getAuthenticatedUser() != null && getAuthenticatedUser().equals(user)) {
×
390
                        roles.addAll(user.getAllRoles());
×
391
                        roles.add(getAuthenticatedRole());
×
392
                }
393
                
394
                return roles;
×
395
        }
396
        
397
        /**
398
         * Tests whether the currently authenticated user has a particular privilege
399
         *
400
         * @param privilege The privilege to check if it's available
401
         * @return true if authenticated user has given privilege
402
         * <strong>Should</strong> authorize if authenticated user has specified privilege
403
         * <strong>Should</strong> authorize if authenticated role has specified privilege
404
         * <strong>Should</strong> authorize if proxied user has specified privilege
405
         * <strong>Should</strong> authorize if anonymous user has specified privilege
406
         * <strong>Should</strong> not authorize if authenticated user does not have specified privilege
407
         * <strong>Should</strong> not authorize if authenticated role does not have specified privilege
408
         * <strong>Should</strong> not authorize if proxied user does not have specified privilege
409
         * <strong>Should</strong> not authorize if anonymous user does not have specified privilege
410
         */
411
        public boolean hasPrivilege(String privilege) {
412
                return hasPrivilege(privilege, true);
1 ✔
413
        }
414

415
        /**
416
         * Tests whether the current user has a particular privilege, optionally excluding proxy privileges.
417
         * <p>
418
         * Passing <code>false</code> resolves the privilege only from the user's roles (and the anonymous
419
         * and authenticated roles), ignoring any {@link #addProxyPrivilege(String...) proxy privileges}.
420
         * This is intended for per-resource access checks that must reflect the user's actual granted roles
421
         * and must not be satisfied by a proxy privilege added merely to invoke the surrounding service
422
         * method. Role privileges are still resolved authoritatively (from the role privilege cache),
423
         * unlike {@link User#hasPrivilege(String)} which reads a potentially stale in-memory role graph.
424
         *
425
         * @param privilege The privilege to check if it's available
426
         * @param includeProxyPrivileges whether proxy privileges may satisfy the check
427
         * @return true if the current user has the given privilege
428
         * @since 3.0.0, 2.9.0, 2.8.9
429
         */
430
        public boolean hasPrivilege(String privilege, boolean includeProxyPrivileges) {
431
                if (includeProxyPrivileges) {
1 ✔
432
                        log.debug("Checking '{}' against proxies: {}", privilege, proxies);
1 ✔
433
                        // check proxied privileges; ArrayList so we have a consistent view
434
                        for (String s : new ArrayList<>(proxies)) {
1 ✔
435
                                if (s.equals(privilege)) {
1 ✔
436
                                        notifyPrivilegeListeners(getAuthenticatedUser(), privilege, true);
1 ✔
437
                                        return true;
1 ✔
438
                                }
439
                        }
1 ✔
440
                }
441

442
                boolean hasPrivilege = resolvePrivilege(privilege);
1 ✔
443
                notifyPrivilegeListeners(getAuthenticatedUser(), privilege, hasPrivilege);
1 ✔
444
                return hasPrivilege;
1 ✔
445
        }
446

447
        /**
448
         * Resolves whether the current user (authenticated or anonymous) holds the given privilege by
449
         * consulting the per-role privilege cache instead of recursively re-expanding the role graph on
450
         * every call. Proxy privileges are handled separately by {@link #hasPrivilege(String)}.
451
         *
452
         * @param privilege the privilege to check
453
         * @return true if the privilege is granted
454
         */
455
        private boolean resolvePrivilege(String privilege) {
456
                RolePrivilegeCache cache = getRolePrivilegeCache();
1 ✔
457

458
                // if a user has logged in, check their privileges
459
                if (isAuthenticated()) {
1 ✔
460
                        // All authenticated users have the "" (empty) privilege, matching User.hasPrivilege.
461
                        if (StringUtils.isEmpty(privilege)) {
1 ✔
462
                                return true;
1 ✔
463
                        }
464

465
                        User authenticatedUser = getAuthenticatedUser();
1 ✔
466
                        if (authenticatedUser.getRoles() != null) {
1 ✔
467
                                for (Role role : authenticatedUser.getRoles()) {
1 ✔
468
                                        if (roleGrants(cache, role, privilege)) {
1 ✔
469
                                                return true;
1 ✔
470
                                        }
471
                                }
1 ✔
472
                        }
473

474
                        if (roleGrants(cache, getAuthenticatedRole(), privilege)) {
1 ✔
475
                                return true;
1 ✔
476
                        }
477
                }
478

479
                return roleGrants(cache, getAnonymousRole(), privilege);
1 ✔
480
        }
481

482
        /**
483
         * Tests whether a single role (and its inherited closure) grants the given privilege, using the
484
         * cached flattening when available and falling back to a direct computation otherwise.
485
         *
486
         * @param cache the role privilege cache, or <code>null</code> if unavailable
487
         * @param role the directly assigned role to test
488
         * @param privilege the privilege to check
489
         * @return true if the role grants superuser status or contains the privilege
490
         */
491
        private boolean roleGrants(RolePrivilegeCache cache, Role role, String privilege) {
492
                RolePrivileges rolePrivileges = (cache != null) ? cache.getRolePrivileges(role)
1 ✔
493
                        : RolePrivilegeCache.computeRolePrivileges(role);
1 ✔
494
                return rolePrivileges.grantsSuperuser() || rolePrivileges.containsPrivilege(privilege);
1 ✔
495
        }
496

497
        /**
498
         * Looks up the {@link RolePrivilegeCache} component, or returns <code>null</code> so callers fall
499
         * back to direct computation. Absence during a context refresh is expected (logged at debug);
500
         * absence otherwise is a misconfiguration that silently drops every check to the uncached path, so
501
         * it is warned once.
502
         *
503
         * @return the cache component, or <code>null</code> if unavailable
504
         */
505
        private RolePrivilegeCache getRolePrivilegeCache() {
506
                try {
507
                        return Context.getRegisteredComponent("rolePrivilegeCache", RolePrivilegeCache.class);
1 ✔
508
                } catch (Exception e) {
×
509
                        if (Context.isRefreshingContext()) {
×
510
                                log.debug("Role privilege cache is unavailable while the context is refreshing; "
×
511
                                        + "computing role privileges directly",
512
                                    e);
513
                        } else if (rolePrivilegeCacheUnavailableWarned.compareAndSet(false, true)) {
×
514
                                log.warn("Could not obtain the rolePrivilegeCache component; privilege checks will recompute role "
×
515
                                        + "privileges on every call until this is resolved",
516
                                    e);
517
                        }
518
                        return null;
×
519
                }
520
        }
521
        
522
        /**
523
         * Convenience method to get the Role in the system designed to be given to all users
524
         *
525
         * @return Role
526
         * <strong>Should</strong> fail if database doesn't contain anonymous role
527
         */
528
        private Role getAnonymousRole() {
529
                if (anonymousRole != null) {
1 ✔
530
                        return anonymousRole;
1 ✔
531
                }
532
                
533
                anonymousRole = Context.getUserService().getRole(RoleConstants.ANONYMOUS);
1 ✔
534
                if (anonymousRole == null) {
1 ✔
535
                        throw new RuntimeException(
×
536
                                "Database out of sync with code: " + RoleConstants.ANONYMOUS + " role does not exist");
537
                }
538
                
539
                return anonymousRole;
1 ✔
540
        }
541
        
542
        /**
543
         * Convenience method to get the Role in the system designed to be given to all users that have
544
         * authenticated in some manner
545
         *
546
         * @return Role
547
         * <strong>Should</strong> fail if database doesn't contain authenticated role
548
         */
549
        private Role getAuthenticatedRole() {
550
                if (authenticatedRole != null) {
1 ✔
551
                        return authenticatedRole;
1 ✔
552
                }
553
                
554
                authenticatedRole = Context.getUserService().getRole(RoleConstants.AUTHENTICATED);
1 ✔
555
                if (authenticatedRole == null) {
1 ✔
556
                        throw new RuntimeException("Database out of sync with code: " + RoleConstants.AUTHENTICATED
×
557
                                + " role does not exist");
558
                }
559
                
560
                return authenticatedRole;
1 ✔
561
        }
562
        
563
        /**
564
         * @return locationId for this user context if any is set
565
         * @since 1.10
566
         */
567
        public Integer getLocationId() {
568
                return locationId;
×
569
        }
570
        
571
        /**
572
         * @param locationId locationId to set
573
         * @since 1.10
574
         */
575
        public void setLocationId(Integer locationId) {
576
                this.locationId = locationId;
1 ✔
577
        }
1 ✔
578
        
579
        /**
580
         * @return current location for this user context if any is set
581
         * @since 1.9
582
         */
583
        public Location getLocation() {
584
                if (locationId == null) {
1 ✔
585
                        return null;
1 ✔
586
                }
587
                return Context.getLocationService().getLocation(locationId);
1 ✔
588
        }
589
        
590
        /**
591
         * @param location the location to set to
592
         * @since 1.9
593
         */
594
        public void setLocation(Location location) {
595
                if (location != null) {
1 ✔
596
                        this.locationId = location.getLocationId();
1 ✔
597
                }
598
        }
1 ✔
599
        
600
        /**
601
         * Convenience method that sets the default location of the currently authenticated user using
602
         * the value of the user's default location property
603
         */
604
        private void setUserLocation(boolean useDefault) {
605
                // location should be null if no user is logged in
606
                if (this.user == null) {
1 ✔
607
                        this.locationId = null;
×
608
                        return;
×
609
                }
610
                
611
                // intended to be when the user initially authenticates
612
                if (this.locationId == null && useDefault) {
1 ✔
613
                        this.locationId = getDefaultLocationId(this.user);
1 ✔
614
                }
615
        }
1 ✔
616

617
        /**
618
         * Convenience method that sets the default locale used by the currently authenticated user, using
619
         * the value of the user's default local property
620
         */
621
        private void setUserLocale(boolean useDefault) {
622
                // local should be null if no user is logged in
623
                if (this.user == null) {
1 ✔
624
                        this.locale = null;
×
625
                        return;
×
626
                }
627

628
                // intended to be when the user initially authenticates
629
                if (user.getUserProperties().containsKey("defaultLocale")) {
1 ✔
630
                        String localeString = user.getUserProperty("defaultLocale");
1 ✔
631
                        locale = LocaleUtility.fromSpecification(localeString);
1 ✔
632
                }
633

634
                if (locale == null && useDefault) {
1 ✔
635
                        locale = LocaleUtility.getDefaultLocale();
1 ✔
636
                }
637

638
        }
1 ✔
639
        
640
        protected Integer getDefaultLocationId(User user) {
641
                String defaultLocation = user.getUserProperty(OpenmrsConstants.USER_PROPERTY_DEFAULT_LOCATION);
1 ✔
642
                if (StringUtils.isNotBlank(defaultLocation)) {
1 ✔
643
                        LocationService ls = Context.getLocationService();
1 ✔
644
                        //only go ahead if it has actually changed OR if wasn't set before
645
                        try {
646
                                int defaultId = Integer.parseInt(defaultLocation);
1 ✔
647
                                if (this.locationId == null || this.locationId != defaultId) {
1 ✔
648
                                        // validate that the id is a valid id
649
                                        if (ls.getLocation(defaultId) != null) {
1 ✔
650
                                                return defaultId;
1 ✔
651
                                        }
652
                                }
653
                        }
654
                        catch (NumberFormatException ignored) {
1 ✔
655
                        }
1 ✔
656

657
                        Location possibleLocation = ls.getLocationByUuid(defaultLocation);
1 ✔
658

659
                        if (possibleLocation != null && (this.locationId == null || !this.locationId.equals(possibleLocation.getId()))) {
1 ✔
660
                                return possibleLocation.getId();
1 ✔
661
                        }
662

663
                        log.warn("The default location for user '{}' is set to '{}', which is not a valid location",
1 ✔
664
                                user.getUsername(), defaultLocation);
1 ✔
665
                }
666
                
667
                return null;
1 ✔
668
        }
669
        
670
        /**
671
         * Notifies privilege listener beans about any privilege check.
672
         * <p>
673
         * It is called by {@link UserContext#hasPrivilege(java.lang.String)}.
674
         *
675
         * @param user         the authenticated user or <code>null</code> if not authenticated
676
         * @param privilege    the checked privilege
677
         * @param hasPrivilege <code>true</code> if the authenticated user has the required privilege or
678
         *                     if it is a proxy privilege
679
         * @see PrivilegeListener
680
         * @since 1.8.4, 1.9.1, 1.10
681
         */
682
        private void notifyPrivilegeListeners(User user, String privilege, boolean hasPrivilege) {
683
                for (PrivilegeListener privilegeListener : Context.getRegisteredComponents(PrivilegeListener.class)) {
1 ✔
684
                        try {
685
                                privilegeListener.privilegeChecked(user, privilege, hasPrivilege);
1 ✔
686
                        }
687
                        catch (Exception e) {
×
688
                                log.error("Privilege listener has failed", e);
×
689
                        }
1 ✔
690
                }
1 ✔
691
        }
1 ✔
692
        
693
        private void notifyUserSessionListener(User user, Event event, Status status) {
694
                for (UserSessionListener userSessionListener : Context.getRegisteredComponents(UserSessionListener.class)) {
1 ✔
695
                        userSessionListener.loggedInOrOut(user, event, status);
1 ✔
696
                }
1 ✔
697
        }
1 ✔
698
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc