Skip to content

Commit

Permalink
feat: S.InputValidation in frontend and bff (#223)
Browse files Browse the repository at this point in the history
* feat: adds a new utility class and add sanitasion functions for ui inputs

Refs: iris-connect/iris-backlog#145

* feat: Add validation rule against entering attacks

Refs: iris-connect/iris-backlog#145

* feat: Replaces sanitasion functions with ui input controls to give more feedback

Refs: iris-connect/iris-backlog#145

* feat: adds basic function for validation and begins with detail implementation

Refs: iris-connect/iris-backlog#145

* feat: Implement original concept of input validation

Refs: iris-connect/iris-backlog#145

* feat: Adjust input validation to new security guidelines

Refs: iris-connect/iris-backlog#145

* feat: Add validation for database security

Refs: iris-connect/iris-backlog#145

* feat: Rename utility class

Refs: iris-connect/iris-backlog#145

* feat: update Constructor

Refs: iris-connect/iris-backlog#145

* feat: Refactor and fix tests

Refs: iris-connect/iris-backlog#145

* feat: Implement improvements in bff

Refs: iris-connect/iris-backlog#145

* feat: Improvements to validation in frontend and implement CaseDataControllerImpl

Refs: iris-connect/iris-backlog#145

* feat: Implement validation in CaseDataControllerImpl and remove critical information from logs

Refs: iris-connect/iris-backlog#145

* feat: Refactoring of string constants: compact and meaningful names.
Refs: iris-connect/iris-backlog#145

* feat: Implemented obfuscation and alerting logic analogous to backend service.
Refs: iris-connect/iris-backlog#145

* feat: Fix sending alerts. Obfuscation method for tokens.
Refs: iris-connect/iris-backlog#145

* feat: Fix tests, empty contact list and empty event list are allowed.
Refs: iris-connect/iris-backlog#145

Co-authored-by: Timo Boegner <tboegner@googlemail.com>
Closes:  iris-connect/iris-backlog#145
PR: /pull/223
  • Loading branch information
SWlionmint and tboegner authored Aug 4, 2021
1 parent fe4b3fe commit e0f86ac
Show file tree
Hide file tree
Showing 25 changed files with 1,117 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private String generateDwUrl(CaseDataRequest dataRequest) throws IRISDataRequest
new DwUrlParamDto(dataRequest.getId().toString(), dataRequest.getAnnouncementToken(), hdConfig.getZipCode());
String paramsAsJson = new ObjectMapper().writeValueAsString(dwUrlParamDto);
paramsAsJsonBase64 = Base64.getEncoder().encodeToString(paramsAsJson.getBytes());
log.debug("Generated Base64 encoded params: {}", dwUrlParamDto);
log.debug("Generated Base64 encoded params: {}", dwUrlParamDto.toStringWithObfuscation());
} catch (Exception e) {
log.error("Generating DW URL failed", e);
throw new IRISDataRequestException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,23 @@ public String validateAndSaveData(UUID dataAuthorizationToken, Contacts contacts
}

public void save(CaseDataRequest dataRequest, Contacts contacts, Events events, CaseDataProvider dataProvider) {
var contactsForDb = contacts.getContactPersons().stream().map(it -> {
var mapped = mapper.map(it, Contact.class);

Optional.ofNullable(it.getContactInformation()).ifPresent(contactInformation -> {
mapped.setBasicConditions(contactInformation.getBasicConditions());
if (contactInformation.getContactCategory() != null) {
mapped.setContactCategory(Contact.ContactCategory.valueOf(contactInformation.getContactCategory().name()));
}
mapped.setFirstContactDate(contactInformation.getFirstContactDate());
mapped.setLastContactDate(contactInformation.getLastContactDate());
});

return mapped;
}).collect(Collectors.toSet());
Set<Contact> contactsForDb = new HashSet<>();
if(contacts.getContactPersons() != null) {
contactsForDb = contacts.getContactPersons().stream().map(it -> {
var mapped = mapper.map(it, Contact.class);

Optional.ofNullable(it.getContactInformation()).ifPresent(contactInformation -> {
mapped.setBasicConditions(contactInformation.getBasicConditions());
if (contactInformation.getContactCategory() != null) {
mapped.setContactCategory(Contact.ContactCategory.valueOf(contactInformation.getContactCategory().name()));
}
mapped.setFirstContactDate(contactInformation.getFirstContactDate());
mapped.setLastContactDate(contactInformation.getLastContactDate());
});

return mapped;
}).collect(Collectors.toSet());
}

Set<CaseEvent> eventsForDb = new HashSet<>();
if (events.getEvents() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import lombok.AllArgsConstructor;
import lombok.Data;

import static iris.client_bff.core.log.LogHelper.obfuscateAtStart8;

@Data
@AllArgsConstructor
public class DwUrlParamDto {
Expand All @@ -16,6 +18,11 @@ public class DwUrlParamDto {
private String p;

public String toString() {
return "dataAuthorizationToken=" + d + "; connectionAuthorizationToken=" + c + "; HD zip code=" + p;
return String.format("dataAuthorizationToken=%s; connectionAuthorizationToken=%s; HD zip code=%s", d, c, p);
}

public String toStringWithObfuscation() {
return String.format("dataAuthorizationToken=%s; connectionAuthorizationToken=%s; HD zip code=%s",
obfuscateAtStart8(d), obfuscateAtStart8(c), p);
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,212 @@
package iris.client_bff.cases.eps;

import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl;
import iris.client_bff.cases.CaseDataSubmissionService;
import iris.client_bff.cases.eps.dto.Contacts;
import iris.client_bff.cases.eps.dto.CaseDataProvider;
import iris.client_bff.cases.eps.dto.ContactInformation;
import iris.client_bff.cases.eps.dto.ContactPerson;
import iris.client_bff.cases.eps.dto.Contacts;
import iris.client_bff.cases.eps.dto.Event;
import iris.client_bff.cases.eps.dto.Events;
import iris.client_bff.cases.eps.dto.WorkPlace;
import iris.client_bff.core.utils.ValidationHelper;
import iris.client_bff.core.web.dto.Address;
import iris.client_bff.ui.messages.ErrorMessages;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.UUID;

import javax.validation.Valid;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl;

@Slf4j
@Service
@AutoJsonRpcServiceImpl
@RequiredArgsConstructor
public class CaseDataControllerImpl implements CaseDataController {

private static final String FIELD_DATA_AUTHORIZATION_TOKEN = "dataAuthorizationToken";
private static final String FIELD_FIRSTNAME = "firstName";
private static final String FIELD_LASTNAME = "lastName";
private static final String FIELD_EMAIL = "email";
private static final String FIELD_PHONE = "phone";
private static final String FIELD_MOBILE_PHONE = "mobilePhone";
private static final String FIELD_NAME = "name";
private static final String FIELD_STREET = "street";
private static final String FIELD_ZIP_CODE = "zipCode";
private static final String FIELD_HOUSE_NUMBER = "houseNumber";
private static final String FIELD_CITY = "city";
private static final String FIELD_ADDITIONAL_INFORMATION = "additionalInformation";
private static final String FIELD_POINT_OF_CONTACT = "pointOfContact";

private final ValidationHelper validHelper;
private final CaseDataSubmissionService submissionService;

@Override
public String submitContactAndEventData(UUID dataAuthorizationToken, @Valid Contacts contacts, @Valid Events events,
@Valid CaseDataProvider dataProvider) {
public String submitContactAndEventData(
UUID dataAuthorizationToken,
@Valid Contacts contacts,
@Valid Events events,
@Valid CaseDataProvider dataProvider) {

if (ValidationHelper
.isUUIDInputValid(dataAuthorizationToken.toString(), FIELD_DATA_AUTHORIZATION_TOKEN)
&& validateEvents(events)
&& validateContacts(contacts)
&& validateCaseDataProvider(dataProvider)) {
log.trace("Start submission {}", dataAuthorizationToken);

return submissionService.validateAndSaveData(dataAuthorizationToken, contacts, events, dataProvider);

} else {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, ErrorMessages.INVALID_INPUT);
}
}

private boolean validateEvents(Events events) {

if (events == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, ErrorMessages.INVALID_INPUT);
}

if (events.getEvents() != null) {
for (Event event : events.getEvents()) {

if (validHelper.isPossibleAttack(event.getName(), FIELD_NAME, true)) {
event.setName(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(event.getPhone(), FIELD_PHONE, true)) {
event.setPhone(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(event.getAdditionalInformation(), FIELD_ADDITIONAL_INFORMATION, true)) {
event.setAdditionalInformation(ErrorMessages.INVALID_INPUT_STRING);
}

event.setAddress(validateAddress(event.getAddress()));
}
}

return true;
}

private boolean validateContacts(Contacts contacts) {

if (contacts == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, ErrorMessages.INVALID_INPUT);
}

if (contacts.getContactPersons() != null) {
for (ContactPerson contactPerson : contacts.getContactPersons()) {

if (validHelper.isPossibleAttack(contactPerson.getLastName(), FIELD_LASTNAME, true)) {
contactPerson.setLastName(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(contactPerson.getFirstName(), FIELD_FIRSTNAME,true)) {
contactPerson.setFirstName(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(contactPerson.getEmail(), FIELD_EMAIL,true)) {
contactPerson.setEmail(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(contactPerson.getPhone(), FIELD_PHONE, true)) {
contactPerson.setPhone(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(contactPerson.getMobilePhone(), FIELD_MOBILE_PHONE,true)) {
contactPerson.setMobilePhone(ErrorMessages.INVALID_INPUT_STRING);
}

contactPerson.setWorkPlace(validateWorkPlace(contactPerson.getWorkPlace()));

contactPerson.setContactInformation(contactPerson.getContactInformation());
}
}

return true;
}

private ContactInformation validateContactInformation(ContactInformation contactInformation) {

if (contactInformation != null) {

// TODO validate ContactInformation

return contactInformation;
}

return null;
}

private Address validateAddress(Address address) {
if (address != null) {

if (validHelper.isPossibleAttack(address.getCity(), FIELD_CITY, true)) {
address.setCity(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(address.getHouseNumber(), FIELD_HOUSE_NUMBER, true)) {
address.setHouseNumber(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(address.getStreet(), FIELD_STREET, true)) {
address.setStreet(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(address.getZipCode(), FIELD_ZIP_CODE, true)) {
address.setZipCode(ErrorMessages.INVALID_INPUT_STRING);
}

return address;
}

return null;
}

private WorkPlace validateWorkPlace(WorkPlace workPlace) {
if (workPlace != null) {

if (validHelper.isPossibleAttack(workPlace.getName(), FIELD_NAME, true)) {
workPlace.setName(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(workPlace.getPhone(), FIELD_PHONE, true)) {
workPlace.setPhone(ErrorMessages.INVALID_INPUT_STRING);
}

if (validHelper.isPossibleAttack(workPlace.getPointOfContact(), FIELD_POINT_OF_CONTACT, true)) {
workPlace.setPointOfContact(ErrorMessages.INVALID_INPUT_STRING);
}

workPlace.setAddress(validateAddress(workPlace.getAddress()));

return workPlace;
}
return null;
}

private boolean validateCaseDataProvider(CaseDataProvider dataProvider) {

if (dataProvider == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, ErrorMessages.INVALID_INPUT);
}

if (validHelper.isPossibleAttack(dataProvider.getFirstName(), FIELD_FIRSTNAME, true)) {
dataProvider.setFirstName(ErrorMessages.INVALID_INPUT_STRING);
}

log.trace("Start submission {}: contacts = {}; events = {}; dataProvider = {}", dataAuthorizationToken, contacts, events, dataProvider);
if (validHelper.isPossibleAttack(dataProvider.getLastName(), FIELD_LASTNAME, true)) {
dataProvider.setLastName(ErrorMessages.INVALID_INPUT_STRING);
}

return submissionService.validateAndSaveData(dataAuthorizationToken, contacts, events, dataProvider);
return true;
}
}
Loading

0 comments on commit e0f86ac

Please sign in to comment.