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

Commit 89ae399

Browse files
committed
Merge branch 'development' into 3578-prevent-blind-sql-injection
2 parents db2f29f + 666067e commit 89ae399

323 files changed

Lines changed: 5159 additions & 660 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

DEVELOPMENT_ENVIRONMENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
- Clone the SORMAS-Project repository and open the project in IntelliJ
5252
- make sure the under "File -> Project Structure -> Modules" all the modules (except the android app - this should not be added) are recognized, if not add the modules with +
5353
- Make sure under "File -> Settings -> Plugins" Glassfish & Ant integrations are enabled (look into the "Installed" tab)
54-
- Install the Vaadin Designer plugin
54+
- Install the Vaadin plugin (not the Vaadin Designer plugin!)
5555
- Make a copy of "build.properties.example" contained in "sormas-base", rename it to "build.properties" and set "glassfish.domain.root" to the location of the sormas domain located in the "glassfish/domains" folder inside your payara installation
5656
- Run "Maven install" on the sormas-base project
5757
- Add a Payara server to IntelliJ:

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ SORMAS officially supports and is tested on **Chromium-based browsers** (like Go
2727

2828
#### Is there a ReST API documentation?
2929
Yes! Please download the [latest release](https://github.com/hzi-braunschweig/SORMAS-Project/releases/latest) and copy the content of /deploy/openapi/sormas-rest.yaml to an editor that generates a visual API documentation (e.g. https://editor.swagger.io/).
30+
<br/>
31+
Runtime Swagger documentation of the External Visits Resource (used by external symptom journals such as CLIMEDO or PIA) is also available at ``<<host>>/sormas-rest/visits-external/openapi.json`` or ``<<host>>/sormas-rest/visits-external/openapi.yaml``
3032

3133
<p align="center"><img src="https://user-images.githubusercontent.com/23701005/74659600-ebb8fc00-5194-11ea-836b-a7ca9d682301.png"/></p>
3234

sormas-api/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@
6767
<artifactId>simmetrics-core</artifactId>
6868
</dependency>
6969

70+
<dependency>
71+
<groupId>org.jsoup</groupId>
72+
<artifactId>jsoup</artifactId>
73+
</dependency>
74+
7075
</dependencies>
7176

7277
</project>

sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseDataDto.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ public class CaseDataDto extends PseudonymizableDto {
167167
public static final String END_OF_ISOLATION_REASON = "endOfIsolationReason";
168168
public static final String END_OF_ISOLATION_REASON_DETAILS = "endOfIsolationReasonDetails";
169169

170+
public static final String PROHIBITION_TO_WORK = "prohibitionToWork";
171+
public static final String PROHIBITION_TO_WORK_FROM = "prohibitionToWorkFrom";
172+
public static final String PROHIBITION_TO_WORK_UNTIL = "prohibitionToWorkUntil";
173+
170174
// Fields are declared in the order they should appear in the import template
171175

172176
@Outbreaks
@@ -450,6 +454,13 @@ public class CaseDataDto extends PseudonymizableDto {
450454
@SensitiveData
451455
private String endOfIsolationReasonDetails;
452456

457+
@HideForCountriesExcept
458+
private YesNoUnknown prohibitionToWork;
459+
@HideForCountriesExcept
460+
private Date prohibitionToWorkFrom;
461+
@HideForCountriesExcept
462+
private Date prohibitionToWorkUntil;
463+
453464
public static CaseDataDto build(PersonReferenceDto person, Disease disease) {
454465
return build(person, disease, null);
455466
}
@@ -1318,6 +1329,30 @@ public void setSormasToSormasOriginInfo(SormasToSormasOriginInfoDto sormasToSorm
13181329
this.sormasToSormasOriginInfo = sormasToSormasOriginInfo;
13191330
}
13201331

1332+
public YesNoUnknown getProhibitionToWork() {
1333+
return prohibitionToWork;
1334+
}
1335+
1336+
public void setProhibitionToWork(YesNoUnknown prohibitionToWork) {
1337+
this.prohibitionToWork = prohibitionToWork;
1338+
}
1339+
1340+
public Date getProhibitionToWorkFrom() {
1341+
return prohibitionToWorkFrom;
1342+
}
1343+
1344+
public void setProhibitionToWorkFrom(Date prohibitionToWorkFrom) {
1345+
this.prohibitionToWorkFrom = prohibitionToWorkFrom;
1346+
}
1347+
1348+
public Date getProhibitionToWorkUntil() {
1349+
return prohibitionToWorkUntil;
1350+
}
1351+
1352+
public void setProhibitionToWorkUntil(Date prohibitionToWorkUntil) {
1353+
this.prohibitionToWorkUntil = prohibitionToWorkUntil;
1354+
}
1355+
13211356
public boolean isOwnershipHandedOver() {
13221357
return ownershipHandedOver;
13231358
}

sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseExportDto.java

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import de.symeda.sormas.api.location.LocationDto;
4343
import de.symeda.sormas.api.person.ApproximateAgeType;
4444
import de.symeda.sormas.api.person.ApproximateAgeType.ApproximateAgeHelper;
45-
import de.symeda.sormas.api.person.ArmedForcesRelationType;
4645
import de.symeda.sormas.api.person.BurialConductor;
4746
import de.symeda.sormas.api.person.EducationType;
4847
import de.symeda.sormas.api.person.OccupationType;
@@ -186,7 +185,6 @@ public class CaseExportDto implements Serializable {
186185
@SensitiveData
187186
private String emailAddress;
188187
private String occupationType;
189-
private ArmedForcesRelationType armedForcesRelationType;
190188
private String educationType;
191189
private String travelHistory;
192190
private boolean traveled;
@@ -266,7 +264,7 @@ public CaseExportDto(long id, long personId, long personAddressId, long epiDataI
266264
String addressRegion, String addressDistrict, String addressCommunity, String city, String street, String houseNumber, String additionalInformation, String postalCode,
267265
String facility, String facilityUuid, String facilityDetails,
268266
String phone, String phoneOwner, String emailAddress, EducationType educationType, String educationDetails,
269-
OccupationType occupationType, String occupationDetails, ArmedForcesRelationType ArmedForcesRelationType, YesNoUnknown contactWithSourceCaseKnown,
267+
OccupationType occupationType, String occupationDetails, YesNoUnknown contactWithSourceCaseKnown,
270268
//Date onsetDate,
271269
Vaccination vaccination, String vaccinationDoses, Date vaccinationDate,
272270
VaccinationInfoSource vaccinationInfoSource, YesNoUnknown postpartum, Trimester trimester,
@@ -283,7 +281,6 @@ public CaseExportDto(long id, long personId, long personAddressId, long epiDataI
283281
this.healthConditionsId = healthConditionsId;
284282
this.uuid = uuid;
285283
this.epidNumber = epidNumber;
286-
this.armedForcesRelationType = ArmedForcesRelationType;
287284
this.diseaseFormatted = DiseaseHelper.toString(disease, diseaseDetails);
288285
this.disease = disease;
289286
this.firstName = firstName;
@@ -336,7 +333,6 @@ public CaseExportDto(long id, long personId, long personAddressId, long epiDataI
336333
this.emailAddress = emailAddress;
337334
this.educationType = PersonHelper.buildEducationString(educationType, educationDetails);
338335
this.occupationType = PersonHelper.buildOccupationString(occupationType, occupationDetails);
339-
this.armedForcesRelationType = armedForcesRelationType;
340336
this.contactWithSourceCaseKnown = contactWithSourceCaseKnown;
341337
// this.onsetDate = onsetDate;
342338
this.vaccination = vaccination;
@@ -1003,8 +999,8 @@ public String getPhone() {
1003999

10041000
@Order(75)
10051001
@ExportTarget(caseExportTypes = {
1006-
CaseExportType.CASE_SURVEILLANCE,
1007-
CaseExportType.CASE_MANAGEMENT })
1002+
CaseExportType.CASE_SURVEILLANCE,
1003+
CaseExportType.CASE_MANAGEMENT })
10081004
@ExportProperty(PersonDto.EMAIL_ADDRESS)
10091005
@ExportGroup(ExportGroupType.SENSITIVE)
10101006
public String getEmailAddress() {
@@ -1036,16 +1032,6 @@ public String getOccupationType() {
10361032
}
10371033

10381034
@Order(78)
1039-
@ExportTarget(caseExportTypes = {
1040-
CaseExportType.CASE_SURVEILLANCE,
1041-
CaseExportType.CASE_MANAGEMENT })
1042-
@ExportProperty(PersonDto.ARMED_FORCES_RELATION_TYPE)
1043-
@ExportGroup(ExportGroupType.PERSON)
1044-
public ArmedForcesRelationType getArmedForcesRelationType() {
1045-
return armedForcesRelationType;
1046-
}
1047-
1048-
@Order(79)
10491035
@ExportTarget(caseExportTypes = {
10501036
CaseExportType.CASE_SURVEILLANCE })
10511037
@ExportProperty(TRAVELED)
@@ -1058,7 +1044,7 @@ public void setTraveled(boolean traveled) {
10581044
this.traveled = traveled;
10591045
}
10601046

1061-
@Order(80)
1047+
@Order(79)
10621048
@ExportTarget(caseExportTypes = {
10631049
CaseExportType.CASE_SURVEILLANCE })
10641050
@ExportProperty(TRAVEL_HISTORY)
@@ -1067,7 +1053,7 @@ public String getTravelHistory() {
10671053
return travelHistory;
10681054
}
10691055

1070-
@Order(81)
1056+
@Order(80)
10711057
@ExportTarget(caseExportTypes = {
10721058
CaseExportType.CASE_SURVEILLANCE })
10731059
@ExportProperty(BURIAL_ATTENDED)
@@ -1080,7 +1066,7 @@ public void setBurialAttended(boolean burialAttended) {
10801066
this.burialAttended = burialAttended;
10811067
}
10821068

1083-
@Order(82)
1069+
@Order(81)
10841070
@ExportTarget(caseExportTypes = {
10851071
CaseExportType.CASE_SURVEILLANCE })
10861072
@ExportProperty(EpiDataDto.CONTACT_WITH_SOURCE_CASE_KNOWN)
@@ -1532,10 +1518,6 @@ public void setOccupationType(String occupationType) {
15321518
this.occupationType = occupationType;
15331519
}
15341520

1535-
public void setArmedForcesRelationType(ArmedForcesRelationType armedForcesRelationType) {
1536-
this.armedForcesRelationType = armedForcesRelationType;
1537-
}
1538-
15391521
public void setTravelHistory(String travelHistory) {
15401522
this.travelHistory = travelHistory;
15411523
}

sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseFacade.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import de.symeda.sormas.api.CaseMeasure;
2828
import de.symeda.sormas.api.Disease;
2929
import de.symeda.sormas.api.Language;
30+
import de.symeda.sormas.api.messaging.ManualMessageLogDto;
31+
import de.symeda.sormas.api.messaging.MessageType;
3032
import de.symeda.sormas.api.contact.ContactReferenceDto;
3133
import de.symeda.sormas.api.contact.DashboardQuarantineDataDto;
3234
import de.symeda.sormas.api.event.EventParticipantReferenceDto;
@@ -175,4 +177,10 @@ List<DashboardQuarantineDataDto> getQuarantineDataForDashBoard(
175177
Date to);
176178

177179
long countCasesConvertedFromContacts(CaseCriteria caseCriteria);
180+
181+
void sendMessage(List<String> caseUuids, String subject, String messageContent, MessageType... messageTypes);
182+
183+
long countCasesWithMissingContactInformation(List<String> caseUuids, MessageType messageType);
184+
185+
List<ManualMessageLogDto> getMessageLog(String caseUuid, MessageType messageType);
178186
}

sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDetailedDto.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public class CaseIndexDetailedDto extends CaseIndexDto {
3030
public static final String LATEST_EVENT_ID = "latestEventId";
3131
public static final String LATEST_EVENT_STATUS = "latestEventStatus";
3232
public static final String LATEST_EVENT_TITLE = "latestEventTitle";
33+
public static final String LATEST_SAMPLE_DATE_TIME = "latestSampleDateTime";
34+
public static final String SAMPLE_COUNT = "sampleCount";
35+
public static final String SYMPTOM_ONSET_DATE = "symptomOnsetDate";
3336

3437
@PersonalData
3538
@SensitiveData
@@ -53,6 +56,9 @@ public class CaseIndexDetailedDto extends CaseIndexDto {
5356
private String latestEventId;
5457
private String latestEventTitle;
5558
private EventStatus latestEventStatus;
59+
private Date latestSampleDateTime;
60+
private Long sampleCount;
61+
private Date symptomOnsetDate;
5662

5763
private UserReferenceDto reportingUser;
5864

@@ -66,7 +72,8 @@ public CaseIndexDetailedDto(long id, String uuid, String epidNumber, String exte
6672
Integer age, ApproximateAgeType ageType, Integer birthdateDD, Integer birthdateMM, Integer birthdateYYYY, Sex sex,
6773
Date quarantineTo, Float completeness, FollowUpStatus followUpStatus, Date followUpUntil, Date changeDate, Long facilityId,
6874
String city, String street, String houseNumber, String additionalInformation, String postalCode, String phone,
69-
String reportingUserFirstName, String reportingUserLastName, int visitCount, long eventCount) {
75+
String reportingUserFirstName, String reportingUserLastName, Date symptomOnsetDate,
76+
int visitCount, long eventCount, Date latestSampleDateTime, long sampleCount) {
7077

7178
super(id, uuid, epidNumber, externalID, personFirstName, personLastName, disease, diseaseDetails, caseClassification, investigationStatus,
7279
presentCondition, reportDate, reportingUserUuid, creationDate, regionUuid, districtUuid, districtName, communityUuid,
@@ -83,6 +90,9 @@ public CaseIndexDetailedDto(long id, String uuid, String epidNumber, String exte
8390
this.phone = phone;
8491
this.reportingUser = new UserReferenceDto(reportingUserUuid, reportingUserFirstName, reportingUserLastName, null);
8592
this.eventCount = eventCount;
93+
this.latestSampleDateTime = latestSampleDateTime;
94+
this.sampleCount = sampleCount;
95+
this.symptomOnsetDate = symptomOnsetDate;
8696
}
8797

8898
public String getCity() {
@@ -144,4 +154,16 @@ public EventStatus getLatestEventStatus() {
144154
public void setLatestEventStatus(EventStatus latestEventStatus) {
145155
this.latestEventStatus = latestEventStatus;
146156
}
157+
158+
public Date getLatestSampleDateTime() {
159+
return latestSampleDateTime;
160+
}
161+
162+
public Long getSampleCount() {
163+
return sampleCount;
164+
}
165+
166+
public Date getSymptomOnsetDate() {
167+
return symptomOnsetDate;
168+
}
147169
}

sormas-api/src/main/java/de/symeda/sormas/api/caze/classification/ClassificationHtmlRenderer.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,11 @@
1717
*******************************************************************************/
1818
package de.symeda.sormas.api.caze.classification;
1919

20-
import static de.symeda.sormas.api.utils.HtmlHelper.escapeAndUnescapeBasicTags;
21-
import static de.symeda.sormas.api.utils.HtmlHelper.unescapeBasicTags;
22-
2320
import java.util.Date;
2421
import java.util.List;
2522

2623
import org.apache.commons.lang3.StringUtils;
27-
import org.apache.commons.text.StringEscapeUtils;
24+
import org.jsoup.safety.Whitelist;
2825

2926
import de.symeda.sormas.api.Disease;
3027
import de.symeda.sormas.api.FacadeProvider;
@@ -34,6 +31,7 @@
3431
import de.symeda.sormas.api.i18n.Strings;
3532
import de.symeda.sormas.api.utils.DataHelper;
3633
import de.symeda.sormas.api.utils.DateHelper;
34+
import de.symeda.sormas.api.utils.HtmlHelper;
3735
import de.symeda.sormas.api.utils.InfoProvider;
3836

3937
/**
@@ -176,7 +174,7 @@ public static String createHtmlForDownload(String sormasServerUrl, List<Disease>
176174
html.append("<h1 style=\"text-align: center; color: #005A9C;\">").append(I18nProperties.getString(Strings.classificationClassificationRules)).append("</h1>");
177175
html.append("<h4 style=\"text-align: center;\">")
178176
.append(I18nProperties.getString(Strings.classificationGeneratedFor))
179-
.append(" ").append(StringEscapeUtils.escapeHtml4(InfoProvider.get().getVersion()))
177+
.append(" ").append(HtmlHelper.cleanHtml(InfoProvider.get().getVersion()))
180178
.append(StringUtils.wrap(I18nProperties.getString(Strings.on), " "))
181179
.append(sormasServerUrl).append(StringUtils.wrap(I18nProperties.getString(Strings.at), " "))
182180
.append(DateHelper.formatLocalDateTime(new Date(), language)).append("</h4>");
@@ -241,7 +239,7 @@ private static String buildSubCriteriaDiv(
241239
for (ClassificationCriteriaDto subCriteria : ((ClassificationCollectiveCriteria) criteria).getSubCriteria()) {
242240
if (!(subCriteria instanceof ClassificationCollectiveCriteria) || subCriteria instanceof ClassificationCompactCriteria) {
243241
// For non-collective or compact collective criteria, add the description as a list item
244-
subCriteriaSb.append("- " + escapeAndUnescapeBasicTags(subCriteria.buildDescription() + "</br>"));
242+
subCriteriaSb.append("- " + HtmlHelper.cleanHtml(subCriteria.buildDescription(), Whitelist.basic()) + "</br>");
245243
} else if (subCriteria instanceof ClassificationCollectiveCriteria
246244
&& !(subCriteria instanceof ClassificationAllOfCriteriaDto)
247245
&& !(subCriteria.getClass() == ClassificationXOfCriteriaDto.class)) {
@@ -273,7 +271,7 @@ private static String createSurroundingDiv(ClassificationCriteriaType criteriaTy
273271
//@formatter:off
274272
return "<div class='classification-rules'>"
275273
+ "<div class='main-criteria main-criteria-"
276-
+ StringEscapeUtils.escapeHtml4(criteriaType.toString())
274+
+ HtmlHelper.cleanHtml(criteriaType.toString())
277275
+ "'>"
278276
+ content
279277
+ "</div></div>";
@@ -287,7 +285,7 @@ private static String createHeadlineDiv(String headline) {
287285

288286
//@formatter:off
289287
return "<div class='headline'>"
290-
+ StringEscapeUtils.escapeHtml4(headline)
288+
+ HtmlHelper.cleanHtml(headline, Whitelist.basic())
291289
+ "</div>";
292290
//@formatter:on
293291
}
@@ -296,13 +294,12 @@ private static String createHeadlineDiv(String headline) {
296294
* Creates a div containing an info text.
297295
*/
298296
private static String createInfoDiv() {
299-
return unescapeBasicTags(StringEscapeUtils.escapeHtml4(I18nProperties.getString(Strings.classificationInfoText)));
297+
return HtmlHelper.cleanI18nString(I18nProperties.getString(Strings.classificationInfoText));
300298
}
301299

302300
private static String createInfoDiv(int requirementsNumber) {
303-
return unescapeBasicTags(
304-
StringEscapeUtils.escapeHtml4(
305-
String.format(I18nProperties.getString(Strings.classificationInfoNumberText), DataHelper.parseNumberToString(requirementsNumber))));
301+
return HtmlHelper.cleanI18nString(
302+
String.format(I18nProperties.getString(Strings.classificationInfoNumberText), DataHelper.parseNumberToString(requirementsNumber)));
306303
}
307304

308305
/**
@@ -334,7 +331,7 @@ private static String createSubCriteriaSurroundingDiv(String content) {
334331
* Specific tags are allowed to be contained in i18n strings and are thus unescaped
335332
*/
336333
private static String createCriteriaItemDiv(String text) {
337-
return unescapeBasicTags(StringEscapeUtils.escapeHtml4(text) + "<br>");
334+
return (HtmlHelper.cleanHtml(text, Whitelist.basic()) + "<br>");
338335
}
339336

340337
private enum ClassificationCriteriaType {

0 commit comments

Comments
 (0)