Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vaccination report): Apps connected to EPS can submit a vaccinatio… #651

Merged
merged 4 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions iris-client-bff/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,11 @@
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>8.12.44</version>
</dependency>

<!-- Security -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
package iris.client_bff.cases;

import io.vavr.control.Try;
import iris.client_bff.core.EmailAddress;
import iris.client_bff.core.mail.EmailProvider;
import iris.client_bff.core.mail.EmailSender;
import iris.client_bff.core.mail.EmailSender.TemplatedEmail.ConfiguredRecipient;
import iris.client_bff.core.model.EmailAddress;
import iris.client_bff.core.mail.EmailTemplates;
import lombok.AccessLevel;
import lombok.Setter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public CompositeJsonServiceExporter jsonRpcServiceImplExporterWithSlash() {
private CompositeJsonServiceExporter createCompositeJsonServiceExporter() {

CompositeJsonServiceExporter compositeJsonServiceExporter = new CompositeJsonServiceExporter();
compositeJsonServiceExporter.setServiceInterfaces(new Class[] { CaseDataController.class, EventDataController.class,
IrisMessageDataController.class, VaccinationInfoController.class });
compositeJsonServiceExporter.setServices(new Object[] { caseDataController, eventDataController,
irisMessageDataController, vaccinationProofController });
compositeJsonServiceExporter.setAllowExtraParams(true); // Used to allow the EPS to add common parameters (e.g. a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,50 @@

import iris.client_bff.ui.messages.ErrorMessages;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

import java.util.Arrays;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

@Configuration
@RequiredArgsConstructor
public class JsonRpcDataValidator {

private final Validator validator;
private final Validator validator;

public void validateData(Object... data) {

Arrays.stream(data)
.map(validator::validate)
.flatMap(Set::stream)
.map(this::createViolationPair)
.reduce(this::joinViolations)
.ifPresent(this::throwException);
}

public void validateData(Object data) {

validator.validate(data).stream()
.map(this::createViolationPair)
.reduce(this::joinViolations)
.ifPresent(this::throwException);
}

private String createViolationPair(ConstraintViolation<Object> violation) {
return String.format("%s: %s", violation.getPropertyPath(), violation.getMessage());
}

public void validateData(Object data) {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(data);
if (!constraintViolations.isEmpty())
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
ErrorMessages.INVALID_INPUT + ": " + constraintViolations.stream().map(violation -> String.format("%s: %s", violation.getPropertyPath(), violation.getMessage())).collect(Collectors.joining(", "))
);
}
private String joinViolations(String a, String b) {
return String.join(", ", a, b);
}

private void throwException(String it) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, ErrorMessages.INVALID_INPUT + ": " + it);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package iris.client_bff.core.mail;

import io.vavr.control.Try;
import iris.client_bff.core.EmailAddress;
import iris.client_bff.core.mail.EmailTemplates.EmailType;
import iris.client_bff.core.mail.EmailTemplates.Key;
import iris.client_bff.core.model.EmailAddress;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package iris.client_bff.core;
package iris.client_bff.core.model;

import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package iris.client_bff.core.model;

import static org.apache.commons.lang3.StringUtils.*;

/**
* @author Jens Kutzsche
*/
public interface FlexibleEnum {

static String cleanStringForEnum(String string) {

var cleanString = replaceChars(string, '-', '_');
cleanString = camelToSnake(cleanString);

return cleanString.toUpperCase();
}

static String camelToSnake(String str) {
return str.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package iris.client_bff.core.model;

import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;

import java.util.regex.Pattern;

import javax.persistence.Column;
import javax.persistence.Embeddable;

import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
* @author Oliver Drotbohm
*/
@Embeddable
@EqualsAndHashCode
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
public class PhoneNumber {

private static final String REMOVABLE_CHARACTERS_REGEX = "\\(\\)\\s\\-";
private static final String REMOVABLE_CHARACTERS_SET = "[" + REMOVABLE_CHARACTERS_REGEX + "]";
public static final String PATTERN = "^[\\+\\(\\)\\s\\-0-9]*?$";
private static final Pattern REGEX = Pattern.compile(PATTERN);

private final @Column(name = "phoneNumber") String value;

public static PhoneNumber of(String number) {

Assert.hasText(number, "Phone number must not be null or empty!");

if (!isValid(number)) {
throw new IllegalArgumentException(String.format("%s is not a valid phone number!", number));
}

return new PhoneNumber(number.replaceAll("\\s", "")
.replace("(0)", "")
.replaceAll(REMOVABLE_CHARACTERS_SET, "")
.replace("+", "00")
.replaceAll("^0049", "0"));
}

@Nullable
@SuppressWarnings("null")
public static PhoneNumber ofNullable(@Nullable String number) {
return StringUtils.hasText(number) ? of(number) : null;
}

public static boolean isValid(@Nullable String candidate) {
return StringUtils.hasText(candidate) && REGEX.matcher(candidate).matches();
}

/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,43 @@

import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = NoSignOfAttackValidator.class)
@Documented
public @interface NoSignOfAttack {

String message() default "{iris.validation.constraints.NoSignOfAttack.message}";
String message()

default "{iris.validation.constraints.NoSignOfAttack.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

public interface Phone extends Payload {}

public static class NoSignOfAttackValidator implements ConstraintValidator<NoSignOfAttack, String> {

@Autowired
private ValidationHelper validationHelper;

private Class<? extends Payload> type;

@Override
public void initialize(NoSignOfAttack constraintAnnotation) {

var payloads = constraintAnnotation.payload();

Assert.isTrue(payloads.length <= 1, "Only one type can be defined!");

if (payloads.length == 1) {
this.type = payloads[0];
}
}

@Override
public boolean isValid(final String text, final ConstraintValidatorContext context) {

Expand All @@ -43,6 +62,10 @@ public boolean isValid(final String text, final ConstraintValidatorContext conte
path = impl.getConstraintViolationCreationContexts().get(0).getPath().asString();
}

if (type == Phone.class) {
return !validationHelper.isPossibleAttackForPhone(text, path, true);
}

return !validationHelper.isPossibleAttack(text, path, true);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package iris.client_bff.core.validation;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;

import iris.client_bff.core.validation.PhoneNumber.PhoneNumberValidator;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;

import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;

@Target({ METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = PhoneNumberValidator.class)
@Documented
public @interface PhoneNumber {

String message() default "{iris.validation.constraints.PhoneNumber.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

public static class PhoneNumberValidator implements ConstraintValidator<PhoneNumber, String> {

private PhoneNumberUtil util = PhoneNumberUtil.getInstance();

@Override
public boolean isValid(final String text, final ConstraintValidatorContext context) {

if (text == null) {
return true;
}

try {

var number = util.parse(text, "ZZ");
return util.isValidNumber(number);

} catch (NumberParseException e) {
return false;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static lombok.AccessLevel.*;

import iris.client_bff.core.validation.NoSignOfAttack;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand All @@ -17,8 +18,8 @@
@AllArgsConstructor(access = PRIVATE)
public class Address {

private @NotBlank String street;
private @NotBlank String houseNumber;
private @NotBlank String zipCode;
private @NotBlank String city;
private @NotBlank @NoSignOfAttack String street;
private @NotBlank @NoSignOfAttack String houseNumber;
private @NotBlank @NoSignOfAttack String zipCode;
private @NotBlank @NoSignOfAttack String city;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
package iris.client_bff.events;

import io.vavr.control.Try;
import iris.client_bff.core.EmailAddress;
import iris.client_bff.core.mail.EmailProvider;
import iris.client_bff.core.mail.EmailSender;
import iris.client_bff.core.mail.EmailSender.TemplatedEmail.ConfiguredRecipient;
import iris.client_bff.core.model.EmailAddress;
import iris.client_bff.core.mail.EmailTemplates;
import lombok.AccessLevel;
import lombok.Setter;
Expand Down
Loading