From 77c076db15219122c8306197c1a5d793321ea58b Mon Sep 17 00:00:00 2001 From: Andreas Hufler Date: Mon, 2 Sep 2024 14:10:33 +0200 Subject: [PATCH 1/6] add PR snapshots --- .github/workflows/test.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 72ed23d..03be02c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,3 +23,35 @@ jobs: env: GITHUB_USER_NAME: ${{ github.actor }} GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + snapshot: + name: Publish snapshot + runs-on: ubuntu-22.04 + timeout-minutes: 10 + needs: test + if: github.event_name == 'pull_request' + steps: + - name: Set Version + run: sed -i 's|BUILD-SNAPSHOT|${{ github.event.pull_request.number }}-SNAPSHOT|g' pom.xml + - run: >- + ./mvnw + -s $GITHUB_WORKSPACE/.github/workflows/maven-settings.xml + --batch-mode + -DskipTests=true + deploy + env: + GITHUB_USER_NAME: ${{ github.actor }} + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + remove-snapshot: + name: Remove Snapshot + runs-on: ubuntu-22.04 + timeout-minutes: 10 + if: github.event_name == 'pull_request' && github.event.action == 'closed' + steps: + - name: Authenticate with GitHub Packages + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $GITHUB_USER_NAME --password-stdin + - name: Remove snapshot version from repository + run: | + curl -X DELETE -u ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} \ + https://maven.pkg.github.com/OWNER/REPOSITORY/com/example/myartifact/${{ github.event.pull_request.number }}-SNAPSHOT/ From 5be51f0731cc6b2cdafd3c9fbbf855ca13780b98 Mon Sep 17 00:00:00 2001 From: Andreas Hufler Date: Mon, 2 Sep 2024 14:40:33 +0200 Subject: [PATCH 2/6] add basic validators --- .idea/encodings.xml | 6 ++ pom.xml | 39 +++++++++++++ .../validation/enumeration/ValidEnum.java | 28 ++++++++++ .../enumeration/ValidEnumValidator.java | 30 ++++++++++ .../validation/password/ValidPassword.java | 26 +++++++++ .../password/ValidPasswordValidator.java | 56 +++++++++++++++++++ 6 files changed, 185 insertions(+) create mode 100644 .idea/encodings.xml create mode 100644 src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnum.java create mode 100644 src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnumValidator.java create mode 100644 src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPassword.java create mode 100644 src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPasswordValidator.java diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..63e9001 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8159baf..d2e2350 100644 --- a/pom.xml +++ b/pom.xml @@ -3,17 +3,56 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.2 + + + it.aboutbits spring-boot-toolbox BUILD-SNAPSHOT Utility library for Spring Boot projects. + jar 21 + + org.springframework.boot + spring-boot-starter-validation + + + + + org.projectlombok + lombok + true + + + + + + org.passay + passay + 1.6.5 + + + + + org.jetbrains + annotations + 24.1.0 + + + + org.springframework.boot + spring-boot-starter-test + diff --git a/src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnum.java b/src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnum.java new file mode 100644 index 0000000..3f53b46 --- /dev/null +++ b/src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnum.java @@ -0,0 +1,28 @@ +package it.aboutbits.springboot.toolbox.validation.enumeration; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Documented +@Constraint(validatedBy = ValidEnumValidator.class) +@Target({FIELD, ANNOTATION_TYPE}) +@Retention(RUNTIME) +public @interface ValidEnum { + + String message() default "{shared.error.validation.invalidEnum}"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + Class> enumClass(); + +} diff --git a/src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnumValidator.java b/src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnumValidator.java new file mode 100644 index 0000000..d90d53c --- /dev/null +++ b/src/main/java/it/aboutbits/springboot/toolbox/validation/enumeration/ValidEnumValidator.java @@ -0,0 +1,30 @@ +package it.aboutbits.springboot.toolbox.validation.enumeration; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +import java.util.HashSet; +import java.util.Set; + +public class ValidEnumValidator implements ConstraintValidator { + private Set enumValues; + + @Override + public void initialize(ValidEnum validEnum) { + var enumClass = validEnum.enumClass(); + + enumValues = new HashSet<>(); + for (Enum anEnum : enumClass.getEnumConstants()) { + enumValues.add(anEnum.name()); + } + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null) { + return true; + } + + return enumValues.contains(value); + } +} diff --git a/src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPassword.java b/src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPassword.java new file mode 100644 index 0000000..f2097f4 --- /dev/null +++ b/src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPassword.java @@ -0,0 +1,26 @@ +package it.aboutbits.springboot.toolbox.validation.password; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Documented +@Constraint(validatedBy = ValidPasswordValidator.class) +@Target({FIELD, ANNOTATION_TYPE}) +@Retention(RUNTIME) +public @interface ValidPassword { + String message() default "{shared.error.validation.invalidPassword}"; + + String lengthMessage() default "{shared.error.validation.invalidPassword.length}"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPasswordValidator.java b/src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPasswordValidator.java new file mode 100644 index 0000000..1914a72 --- /dev/null +++ b/src/main/java/it/aboutbits/springboot/toolbox/validation/password/ValidPasswordValidator.java @@ -0,0 +1,56 @@ +package it.aboutbits.springboot.toolbox.validation.password; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import org.passay.LengthRule; +import org.passay.PasswordData; +import org.passay.PasswordValidator; +import org.passay.RuleResultDetail; + +import java.util.List; + +public class ValidPasswordValidator implements ConstraintValidator { + private String message; + private String lengthMessage; + + @Override + public void initialize(ValidPassword constraintAnnotation) { + this.message = constraintAnnotation.message(); + this.lengthMessage = constraintAnnotation.lengthMessage(); + } + + @Override + public boolean isValid(String password, ConstraintValidatorContext context) { + if (password == null) { + return true; + } + + var validator = new PasswordValidator(List.of( + // at least 8 characters + new LengthRule(8, 50) + )); + + var result = validator.validate(new PasswordData(password)); + + if (!password.isBlank() && result.isValid()) { + return true; + } + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(getMessageTemplate(result.getDetails())) + .addConstraintViolation(); + + return false; + } + + private String getMessageTemplate(List ruleResultDetails) { + if (ruleResultDetails.isEmpty()) { + return message; + } + + return switch (ruleResultDetails.getFirst().getErrorCode()) { + case "TOO_SHORT" -> lengthMessage; + case "TOO_LONG" -> lengthMessage; + default -> message; + }; + } +} From d56edc298b2a9fe1026c8b2cb7a83fdb21837a43 Mon Sep 17 00:00:00 2001 From: Andreas Hufler Date: Mon, 2 Sep 2024 14:42:43 +0200 Subject: [PATCH 3/6] fix missing steps --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03be02c..fe39c88 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,6 +31,10 @@ jobs: needs: test if: github.event_name == 'pull_request' steps: + - uses: actions/checkout@v4 + - uses: aboutbits/github-actions-java/setup@v3 + with: + java-version: 21 - name: Set Version run: sed -i 's|BUILD-SNAPSHOT|${{ github.event.pull_request.number }}-SNAPSHOT|g' pom.xml - run: >- From abb5259ebaeff9b1670f9612e40759d721d20d48 Mon Sep 17 00:00:00 2001 From: Andreas Hufler Date: Mon, 2 Sep 2024 15:03:44 +0200 Subject: [PATCH 4/6] fix version --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fe39c88..5d1e58f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: with: java-version: 21 - name: Set Version - run: sed -i 's|BUILD-SNAPSHOT|${{ github.event.pull_request.number }}-SNAPSHOT|g' pom.xml + run: sed -i 's|BUILD-SNAPSHOT|PR-${{ github.event.pull_request.number }}|g' pom.xml - run: >- ./mvnw -s $GITHUB_WORKSPACE/.github/workflows/maven-settings.xml @@ -58,4 +58,4 @@ jobs: - name: Remove snapshot version from repository run: | curl -X DELETE -u ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} \ - https://maven.pkg.github.com/OWNER/REPOSITORY/com/example/myartifact/${{ github.event.pull_request.number }}-SNAPSHOT/ + https://maven.pkg.github.com/OWNER/REPOSITORY/com/example/myartifact/PR-${{ github.event.pull_request.number }}/ From 16993239ee714dd9c6f38b870762106dc23a0f39 Mon Sep 17 00:00:00 2001 From: Andreas Hufler Date: Mon, 2 Sep 2024 15:28:58 +0200 Subject: [PATCH 5/6] fix actions --- .github/workflows/test.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5d1e58f..4e361ec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,7 @@ jobs: name: Maven-Java runs-on: ubuntu-22.04 timeout-minutes: 10 + if: github.event_name == 'pull_request' && github.event.action != 'closed' steps: - uses: actions/checkout@v4 - uses: aboutbits/github-actions-java/setup@v3 @@ -25,7 +26,7 @@ jobs: GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} snapshot: - name: Publish snapshot + name: Publish Snapshot runs-on: ubuntu-22.04 timeout-minutes: 10 needs: test @@ -53,9 +54,10 @@ jobs: timeout-minutes: 10 if: github.event_name == 'pull_request' && github.event.action == 'closed' steps: - - name: Authenticate with GitHub Packages - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $GITHUB_USER_NAME --password-stdin - name: Remove snapshot version from repository - run: | - curl -X DELETE -u ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} \ - https://maven.pkg.github.com/OWNER/REPOSITORY/com/example/myartifact/PR-${{ github.event.pull_request.number }}/ + uses: actions/delete-package-versions@v5 + with: + package-type: 'maven' + package-name: 'it.aboutbits.spring-boot-toolbox' + package-version-ids: 'PR-${{ github.event.pull_request.number }}' + token: ${{ secrets.GITHUB_PAT }} From dbee6e51bde16e7c6ebde540e0099e7b524ff4df Mon Sep 17 00:00:00 2001 From: Andreas Hufler Date: Mon, 2 Sep 2024 15:38:07 +0200 Subject: [PATCH 6/6] remove snapshots --- .github/workflows/test.yml | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4e361ec..72ed23d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,6 @@ jobs: name: Maven-Java runs-on: ubuntu-22.04 timeout-minutes: 10 - if: github.event_name == 'pull_request' && github.event.action != 'closed' steps: - uses: actions/checkout@v4 - uses: aboutbits/github-actions-java/setup@v3 @@ -24,40 +23,3 @@ jobs: env: GITHUB_USER_NAME: ${{ github.actor }} GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - snapshot: - name: Publish Snapshot - runs-on: ubuntu-22.04 - timeout-minutes: 10 - needs: test - if: github.event_name == 'pull_request' - steps: - - uses: actions/checkout@v4 - - uses: aboutbits/github-actions-java/setup@v3 - with: - java-version: 21 - - name: Set Version - run: sed -i 's|BUILD-SNAPSHOT|PR-${{ github.event.pull_request.number }}|g' pom.xml - - run: >- - ./mvnw - -s $GITHUB_WORKSPACE/.github/workflows/maven-settings.xml - --batch-mode - -DskipTests=true - deploy - env: - GITHUB_USER_NAME: ${{ github.actor }} - GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - remove-snapshot: - name: Remove Snapshot - runs-on: ubuntu-22.04 - timeout-minutes: 10 - if: github.event_name == 'pull_request' && github.event.action == 'closed' - steps: - - name: Remove snapshot version from repository - uses: actions/delete-package-versions@v5 - with: - package-type: 'maven' - package-name: 'it.aboutbits.spring-boot-toolbox' - package-version-ids: 'PR-${{ github.event.pull_request.number }}' - token: ${{ secrets.GITHUB_PAT }}