Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit 855f36b

Browse files
authored
SORMAS-Foundation#2976 Provide the possibility to setup default users for external systems (SORMAS-Foundation#3355)
1 parent 60f5a4d commit 855f36b

8 files changed

Lines changed: 234 additions & 55 deletions

File tree

SERVER_CUSTOMIZATION.md

Lines changed: 33 additions & 32 deletions
Large diffs are not rendered by default.

sormas-api/src/main/java/de/symeda/sormas/api/externaljournal/PatientDiaryConfig.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public class PatientDiaryConfig implements Serializable, Cloneable {
1212
private String authUrl;
1313
private String email;
1414
private String password;
15+
private UserConfig defaultUser;
1516

1617
public String getUrl() {
1718
return url;
@@ -53,6 +54,14 @@ public void setPassword(String password) {
5354
this.password = password;
5455
}
5556

57+
public UserConfig getDefaultUser() {
58+
return defaultUser;
59+
}
60+
61+
public void setDefaultUser(UserConfig defaultUser) {
62+
this.defaultUser = defaultUser;
63+
}
64+
5665
@Override
5766
public boolean equals(Object o) {
5867
if (this == o)
@@ -64,12 +73,13 @@ public boolean equals(Object o) {
6473
&& Objects.equals(externalDataUrl, that.externalDataUrl)
6574
&& Objects.equals(authUrl, that.authUrl)
6675
&& Objects.equals(email, that.email)
67-
&& Objects.equals(password, that.password);
76+
&& Objects.equals(password, that.password)
77+
&& Objects.equals(defaultUser, that.defaultUser);
6878
}
6979

7080
@Override
7181
public int hashCode() {
72-
return Objects.hash(url, externalDataUrl, authUrl, email, password);
82+
return Objects.hash(url, externalDataUrl, authUrl, email, password, defaultUser);
7383
}
7484

7585
@Override

sormas-api/src/main/java/de/symeda/sormas/api/externaljournal/SymptomJournalConfig.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class SymptomJournalConfig implements Serializable, Cloneable {
1111
private String authUrl;
1212
private String clientId;
1313
private String secret;
14+
private UserConfig defaultUser;
1415

1516
public String getUrl() {
1617
return url;
@@ -44,6 +45,14 @@ public void setSecret(String secret) {
4445
this.secret = secret;
4546
}
4647

48+
public UserConfig getDefaultUser() {
49+
return defaultUser;
50+
}
51+
52+
public void setDefaultUser(UserConfig defaultUser) {
53+
this.defaultUser = defaultUser;
54+
}
55+
4756
@Override
4857
public boolean equals(Object o) {
4958
if (this == o)
@@ -54,12 +63,13 @@ public boolean equals(Object o) {
5463
return Objects.equals(url, that.url)
5564
&& Objects.equals(authUrl, that.authUrl)
5665
&& Objects.equals(clientId, that.clientId)
57-
&& Objects.equals(secret, that.secret);
66+
&& Objects.equals(secret, that.secret)
67+
&& Objects.equals(defaultUser, that.defaultUser);
5868
}
5969

6070
@Override
6171
public int hashCode() {
62-
return Objects.hash(url, authUrl, clientId, secret);
72+
return Objects.hash(url, authUrl, clientId, secret, defaultUser);
6373
}
6474

6575
@Override
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* SORMAS® - Surveillance Outbreak Response Management & Analysis System
3+
* Copyright © 2016-2020 Helmholtz-Zentrum für Infektionsforschung GmbH (HZI)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
19+
package de.symeda.sormas.api.externaljournal;
20+
21+
import java.util.Objects;
22+
23+
/**
24+
* @author Alex Vidrean
25+
* @since 28-Oct-20
26+
*/
27+
public class UserConfig {
28+
29+
private String username;
30+
31+
private String password;
32+
33+
public String getUsername() {
34+
return username;
35+
}
36+
37+
public void setUsername(String username) {
38+
this.username = username;
39+
}
40+
41+
public String getPassword() {
42+
return password;
43+
}
44+
45+
public void setPassword(String password) {
46+
this.password = password;
47+
}
48+
49+
@Override
50+
public boolean equals(Object o) {
51+
if (this == o)
52+
return true;
53+
if (o == null || getClass() != o.getClass())
54+
return false;
55+
UserConfig that = (UserConfig) o;
56+
return Objects.equals(username, that.username) && Objects.equals(password, that.password);
57+
}
58+
59+
@Override
60+
public int hashCode() {
61+
return Objects.hash(username, password);
62+
}
63+
}

sormas-backend/src/main/java/de/symeda/sormas/backend/common/ConfigFacadeEjb.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import javax.ejb.LocalBean;
2727
import javax.ejb.Stateless;
2828

29+
import de.symeda.sormas.api.externaljournal.UserConfig;
2930
import org.apache.commons.lang3.StringUtils;
3031
import org.apache.commons.validator.routines.UrlValidator;
3132
import org.slf4j.Logger;
@@ -95,12 +96,16 @@ public class ConfigFacadeEjb implements ConfigFacade {
9596
public static final String INTERFACE_SYMPTOM_JOURNAL_AUTH_URL = "interface.symptomjournal.authurl";
9697
public static final String INTERFACE_SYMPTOM_JOURNAL_CLIENT_ID = "interface.symptomjournal.clientid";
9798
public static final String INTERFACE_SYMPTOM_JOURNAL_SECRET = "interface.symptomjournal.secret";
99+
public static final String INTERFACE_SYMPTOM_JOURNAL_DEFAULT_USER_USERNAME = "interface.symptomjournal.defaultuser.username";
100+
public static final String INTERFACE_SYMPTOM_JOURNAL_DEFAULT_USER_PASSWORD = "interface.symptomjournal.defaultuser.password";
98101

99102
public static final String INTERFACE_PATIENT_DIARY_URL = "interface.patientdiary.url";
100103
public static final String INTERFACE_PATIENT_DIARY_EXTERNAL_DATA_URL = "interface.patientdiary.externaldataurl";
101104
public static final String INTERFACE_PATIENT_DIARY_AUTH_URL = "interface.patientdiary.authurl";
102105
public static final String INTERFACE_PATIENT_DIARY_EMAIL = "interface.patientdiary.email";
103106
public static final String INTERFACE_PATIENT_DIARY_PASSWORD = "interface.patientdiary.password";
107+
public static final String INTERFACE_PATIENT_DIARY_DEFAULT_USER_USERNAME = "interface.patientdiary.defaultuser.username";
108+
public static final String INTERFACE_PATIENT_DIARY_DEFAULT_USER_PASSWORD = "interface.patientdiary.defaultuser.password";
104109

105110
public static final String DAYS_AFTER_CASE_GETS_ARCHIVED = "daysAfterCaseGetsArchived";
106111
private static final String DAYS_AFTER_EVENT_GETS_ARCHIVED = "daysAfterEventGetsArchived";
@@ -385,6 +390,15 @@ public SymptomJournalConfig getSymptomJournalConfig() {
385390
config.setAuthUrl(getProperty(INTERFACE_SYMPTOM_JOURNAL_AUTH_URL, null));
386391
config.setClientId(getProperty(INTERFACE_SYMPTOM_JOURNAL_CLIENT_ID, null));
387392
config.setSecret(getProperty(INTERFACE_SYMPTOM_JOURNAL_SECRET, null));
393+
394+
UserConfig userConfig = new UserConfig();
395+
userConfig.setUsername(getProperty(INTERFACE_SYMPTOM_JOURNAL_DEFAULT_USER_USERNAME, null));
396+
userConfig.setPassword(getProperty(INTERFACE_SYMPTOM_JOURNAL_DEFAULT_USER_PASSWORD, null));
397+
398+
if(StringUtils.isNoneBlank(userConfig.getUsername(), userConfig.getPassword())) {
399+
config.setDefaultUser(userConfig);
400+
}
401+
388402
return config;
389403
}
390404

@@ -396,6 +410,15 @@ public PatientDiaryConfig getPatientDiaryConfig() {
396410
config.setAuthUrl(getProperty(INTERFACE_PATIENT_DIARY_AUTH_URL, null));
397411
config.setEmail(getProperty(INTERFACE_PATIENT_DIARY_EMAIL, null));
398412
config.setPassword(getProperty(INTERFACE_PATIENT_DIARY_PASSWORD, null));
413+
414+
UserConfig userConfig = new UserConfig();
415+
userConfig.setUsername(getProperty(INTERFACE_PATIENT_DIARY_DEFAULT_USER_USERNAME, null));
416+
userConfig.setPassword(getProperty(INTERFACE_PATIENT_DIARY_DEFAULT_USER_PASSWORD, null));
417+
418+
if(StringUtils.isNoneBlank(userConfig.getUsername(), userConfig.getPassword())) {
419+
config.setDefaultUser(userConfig);
420+
}
421+
399422
return config;
400423
}
401424

sormas-backend/src/main/java/de/symeda/sormas/backend/common/StartupShutdownService.java

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
import java.nio.charset.StandardCharsets;
2424
import java.util.ArrayList;
2525
import java.util.Arrays;
26+
import java.util.Collections;
27+
import java.util.HashSet;
2628
import java.util.List;
2729
import java.util.NoSuchElementException;
2830
import java.util.Optional;
2931
import java.util.Scanner;
32+
import java.util.Set;
3033
import java.util.regex.Matcher;
3134
import java.util.regex.Pattern;
3235
import java.util.stream.Collectors;
@@ -45,10 +48,14 @@
4548
import javax.persistence.EntityManager;
4649
import javax.persistence.PersistenceContext;
4750

51+
import de.symeda.sormas.api.externaljournal.PatientDiaryConfig;
52+
import de.symeda.sormas.api.externaljournal.SymptomJournalConfig;
53+
import de.symeda.sormas.api.externaljournal.UserConfig;
4854
import de.symeda.sormas.backend.user.event.MockPasswordUpdateEvent;
4955
import de.symeda.sormas.backend.user.event.MockUserCreateEvent;
5056
import de.symeda.sormas.backend.user.event.PasswordResetEvent;
5157
import de.symeda.sormas.backend.user.event.UserCreateEvent;
58+
import org.apache.commons.lang3.StringUtils;
5259
import org.slf4j.Logger;
5360
import org.slf4j.LoggerFactory;
5461

@@ -177,6 +184,10 @@ public void startup() {
177184

178185
createOrUpdateSormasToSormasUser();
179186

187+
createOrUpdateSymptomJournalUser();
188+
189+
createOrUpdatePatientDiaryUser();
190+
180191
upgrade();
181192

182193
createImportTemplateFiles();
@@ -435,29 +446,75 @@ private void createDefaultUsers() {
435446
}
436447

437448
private void createOrUpdateSormasToSormasUser() {
438-
final User sormasToSormasUser = userService.getByUserName(SORMAS_TO_SORMAS_USER_NAME);
439-
440449
serverAccessDataService.getServerAccessData().ifPresent((serverAccessData -> {
441450
String sormasToSormasUserPassword = serverAccessData.getRestUserPassword();
451+
createOrUpdateDefaultUser(
452+
Collections.singleton(UserRole.SORMAS_TO_SORMAS_CLIENT),
453+
SORMAS_TO_SORMAS_USER_NAME,
454+
sormasToSormasUserPassword,
455+
"Sormas to Sormas",
456+
"Client");
457+
}));
458+
}
442459

443-
if (sormasToSormasUser == null) {
444-
if (!DataHelper.isNullOrEmpty(sormasToSormasUserPassword)) {
445-
User newUser =
446-
MockDataGenerator.createUser(UserRole.SORMAS_TO_SORMAS_CLIENT, "Sormas to Sormas", "Client", sormasToSormasUserPassword);
447-
newUser.setUserName(SORMAS_TO_SORMAS_USER_NAME);
460+
private void createOrUpdateSymptomJournalUser() {
461+
SymptomJournalConfig symptomJournalConfig = configFacade.getSymptomJournalConfig();
462+
UserConfig userConfig = symptomJournalConfig.getDefaultUser();
463+
if (userConfig == null) {
464+
logger.debug("Symptom journal default user not configured");
465+
return;
466+
}
448467

449-
userService.persist(newUser);
450-
userCreateEvent.fire(new MockUserCreateEvent(newUser, sormasToSormasUserPassword));
451-
}
452-
} else if (!DataHelper
453-
.equal(sormasToSormasUser.getPassword(), PasswordHelper.encodePassword(sormasToSormasUserPassword, sormasToSormasUser.getSeed()))) {
454-
sormasToSormasUser.setSeed(PasswordHelper.createPass(16));
455-
sormasToSormasUser.setPassword(PasswordHelper.encodePassword(sormasToSormasUserPassword, sormasToSormasUser.getSeed()));
468+
createOrUpdateDefaultUser(
469+
Collections.singleton(UserRole.REST_USER),
470+
userConfig.getUsername(),
471+
userConfig.getPassword(),
472+
"Symptom",
473+
"Journal");
474+
}
456475

457-
userService.persist(sormasToSormasUser);
458-
passwordResetEvent.fire(new MockPasswordUpdateEvent(sormasToSormasUser, sormasToSormasUserPassword));
476+
private void createOrUpdatePatientDiaryUser() {
477+
PatientDiaryConfig patientDiaryConfig = configFacade.getPatientDiaryConfig();
478+
UserConfig userConfig = patientDiaryConfig.getDefaultUser();
479+
if (userConfig == null) {
480+
logger.debug("Patient diary default user not configured");
481+
return;
482+
}
483+
484+
createOrUpdateDefaultUser(
485+
new HashSet<>(Arrays.asList(UserRole.REST_USER, UserRole.REST_EXTERNAL_VISITS_USER)),
486+
userConfig.getUsername(),
487+
userConfig.getPassword(),
488+
"Patient",
489+
"Diary");
490+
}
491+
492+
private void createOrUpdateDefaultUser(Set<UserRole> userRoles, String username, String password, String firstName, String lastName) {
493+
494+
if(StringUtils.isAnyBlank(username, password)) {
495+
logger.debug("Invalid user details. Will not create/update default user");
496+
return;
497+
}
498+
499+
User existingUser = userService.getByUserName(username);
500+
501+
if (existingUser == null) {
502+
if (!DataHelper.isNullOrEmpty(password)) {
503+
User newUser = MockDataGenerator.createUser(userRoles, firstName, lastName, password);
504+
newUser.setUserName(username);
505+
506+
userService.persist(newUser);
507+
userCreateEvent.fire(new MockUserCreateEvent(newUser, password));
459508
}
460-
}));
509+
} else if (!DataHelper
510+
.equal(existingUser.getPassword(), PasswordHelper.encodePassword(password, existingUser.getSeed()))) {
511+
existingUser.setSeed(PasswordHelper.createPass(16));
512+
existingUser.setPassword(PasswordHelper.encodePassword(password, existingUser.getSeed()));
513+
514+
userService.persist(existingUser);
515+
passwordResetEvent.fire(new MockPasswordUpdateEvent(existingUser, password));
516+
}
517+
461518
}
462519

463520
/**

sormas-backend/src/main/java/de/symeda/sormas/backend/util/MockDataGenerator.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
package de.symeda.sormas.backend.util;
1919

2020
import java.util.Arrays;
21+
import java.util.Collections;
2122
import java.util.HashSet;
23+
import java.util.List;
24+
import java.util.Set;
2225

2326
import de.symeda.sormas.api.user.UserHelper;
2427
import de.symeda.sormas.api.user.UserRole;
2528
import de.symeda.sormas.backend.user.User;
29+
import org.apache.commons.collections4.CollectionUtils;
2630

2731
public final class MockDataGenerator {
2832

@@ -31,12 +35,17 @@ private MockDataGenerator() {
3135
}
3236

3337
public static User createUser(UserRole userRole, String firstName, String lastName, String password) {
38+
Set<UserRole> userRoles = userRole != null ? Collections.singleton(userRole) : null;
39+
return createUser(userRoles, firstName, lastName, password);
40+
}
41+
42+
public static User createUser(Set<UserRole> userRoles, String firstName, String lastName, String password) {
3443

3544
User user = new User();
3645
user.setFirstName(firstName);
3746
user.setLastName(lastName);
38-
if (userRole != null) {
39-
user.setUserRoles(new HashSet<UserRole>(Arrays.asList(userRole)));
47+
if (CollectionUtils.isNotEmpty(userRoles)) {
48+
user.setUserRoles(new HashSet<>(userRoles));
4049
}
4150
user.setUserName(UserHelper.getSuggestedUsername(user.getFirstName(), user.getLastName()));
4251
user.setSeed(PasswordHelper.createPass(16));

sormas-base/setup/sormas.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ sms.auth.secret=
157157
#interface.symptomjournal.authurl=
158158
#interface.symptomjournal.clientid=
159159
#interface.symptomjournal.secret=
160+
# Default user used by the symptom journal to communicate with the SORMAS API (can be used to automate the setup process of new systems).
161+
#interface.symptomjournal.defaultuser.username=
162+
#interface.symptomjournal.defaultuser.password=
160163

161164
# Website that is displayed in a new tab to show or create a climedo patient eDiary for a contact person; leave this commented
162165
# if you don't want to use this feature
@@ -165,6 +168,9 @@ sms.auth.secret=
165168
#interface.patientdiary.authurl=
166169
#interface.patientdiary.email=
167170
#interface.patientdiary.password=
171+
# Default user used by the symptom journal to communicate with the SORMAS API (can be used to automate the setup process of new systems).
172+
#interface.patientdiary.defaultuser.username=
173+
#interface.patientdiary.defaultuser.password=
168174

169175
# Specify the authentication provider for UI and Rest API
170176
# Supported values: SORMAS, KEYCLOAK

0 commit comments

Comments
 (0)