From d98f60ab5444128a0c57dba6720bd175c1616c4e Mon Sep 17 00:00:00 2001 From: Torge Hamann <37174525+torge-hmn@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:35:27 +0100 Subject: [PATCH] feat: Add basic certificate models and repositories (#8) * Add basic certificate models and repositories * Review comments * Adjust cert enum --- build.gradle.kts | 1 + .../certassist/models/Certificate.java | 45 ++++++++++++++ .../models/CertificateExtension.java | 19 ++++++ .../models/CertificateSubjectPreset.java | 26 +++++++++ .../certassist/models/CertificateType.java | 8 +++ .../de/mlessmann/certassist/models/User.java | 6 +- .../openssl/CertificateRequest.java | 1 + .../CertificateExtensionRepository.java | 8 +++ .../repositories/CertificateRepository.java | 8 +++ .../CertificateSubjectPresetRepository.java | 8 +++ .../repositories/UserRepository.java | 5 +- .../CertificateExtensionRepositoryTest.java | 26 +++++++++ .../CertificateRepositoryTest.java | 58 +++++++++++++++++++ ...ertificateSubjectPresetRepositoryTest.java | 26 +++++++++ .../repositories/UserRepositoryTest.java | 8 ++- 15 files changed, 244 insertions(+), 9 deletions(-) create mode 100644 src/main/java/de/mlessmann/certassist/models/Certificate.java create mode 100644 src/main/java/de/mlessmann/certassist/models/CertificateExtension.java create mode 100644 src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java create mode 100644 src/main/java/de/mlessmann/certassist/models/CertificateType.java create mode 100644 src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java create mode 100644 src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java create mode 100644 src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java create mode 100644 src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java create mode 100644 src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java create mode 100644 src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 4290980..f6c7c81 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,6 +36,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-jdbc") implementation("org.xerial:sqlite-jdbc") implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.hibernate.orm:hibernate-community-dialects") implementation("org.springframework.boot:spring-boot-starter-security") diff --git a/src/main/java/de/mlessmann/certassist/models/Certificate.java b/src/main/java/de/mlessmann/certassist/models/Certificate.java new file mode 100644 index 0000000..f7a5997 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/Certificate.java @@ -0,0 +1,45 @@ +package de.mlessmann.certassist.models; + +import jakarta.persistence.*; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +@Entity +@Data +public class Certificate { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; + + @NotNull + @Enumerated(EnumType.STRING) + private CertificateType type; + + @NotNull + private String commonName; + + private String trustingAuthority; + + @Min(1) + private int requestedKeyLength; + + @Min(1) + private int requestedValidityDays; + + private String subjectEmailAddress; + private String subjectOrganization; + private String subjectOrganizationalUnit; + private String subjectCountry; + private String subjectState; + private String subjectLocality; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + private List certificateExtension = new ArrayList<>(); +} diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateExtension.java b/src/main/java/de/mlessmann/certassist/models/CertificateExtension.java new file mode 100644 index 0000000..f9e6ca0 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/CertificateExtension.java @@ -0,0 +1,19 @@ +package de.mlessmann.certassist.models; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +@Entity +@Data +public class CertificateExtension { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; + + private String identifier; + private String value; +} diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java b/src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java new file mode 100644 index 0000000..ba8a033 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java @@ -0,0 +1,26 @@ +package de.mlessmann.certassist.models; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +@Entity +@Data +public class CertificateSubjectPreset { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; + + private String emailAddress; + private String organization; + private String organizationalUnit; + private String country; + private String state; + private String locality; +} diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateType.java b/src/main/java/de/mlessmann/certassist/models/CertificateType.java new file mode 100644 index 0000000..3b44140 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/CertificateType.java @@ -0,0 +1,8 @@ +package de.mlessmann.certassist.models; + +public enum CertificateType { + ROOT_CA, + STANDALONE_CERT, + SIGNED_CERT, + CLIENT_CERT, +} diff --git a/src/main/java/de/mlessmann/certassist/models/User.java b/src/main/java/de/mlessmann/certassist/models/User.java index 78f77a4..42a221e 100644 --- a/src/main/java/de/mlessmann/certassist/models/User.java +++ b/src/main/java/de/mlessmann/certassist/models/User.java @@ -4,6 +4,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -12,8 +13,9 @@ import lombok.Setter; public class User { @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE) - private Long id; + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; @Setter private String username; diff --git a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java index 4d6ab9d..54befcd 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java +++ b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java @@ -9,6 +9,7 @@ import lombok.Data; public class CertificateRequest { @Builder.Default + @Deprecated private String oid = UUID.randomUUID().toString(); private RequestType type; diff --git a/src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java b/src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java new file mode 100644 index 0000000..262c999 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java @@ -0,0 +1,8 @@ +package de.mlessmann.certassist.repositories; + +import de.mlessmann.certassist.models.CertificateExtension; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CertificateExtensionRepository extends CrudRepository {} diff --git a/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java b/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java new file mode 100644 index 0000000..fed956f --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java @@ -0,0 +1,8 @@ +package de.mlessmann.certassist.repositories; + +import de.mlessmann.certassist.models.Certificate; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CertificateRepository extends CrudRepository {} diff --git a/src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java b/src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java new file mode 100644 index 0000000..c74e86d --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java @@ -0,0 +1,8 @@ +package de.mlessmann.certassist.repositories; + +import de.mlessmann.certassist.models.CertificateSubjectPreset; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CertificateSubjectPresetRepository extends CrudRepository {} diff --git a/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java b/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java index 4f12c8b..6839491 100644 --- a/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java +++ b/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java @@ -5,7 +5,4 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @Repository -public interface UserRepository extends CrudRepository { - - User findUserById(long id); -} +public interface UserRepository extends CrudRepository {} diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java new file mode 100644 index 0000000..8f40ca4 --- /dev/null +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java @@ -0,0 +1,26 @@ +package de.mlessmann.certassist.repositories; + +import static org.assertj.core.api.Assertions.assertThat; + +import de.mlessmann.certassist.models.CertificateExtension; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CertificateExtensionRepositoryTest { + + @Autowired + private CertificateExtensionRepository repository; + + @Test + @Transactional + void findCertificate() { + CertificateExtension certificateExtension = new CertificateExtension(); + certificateExtension.setValue("test-value"); + repository.save(certificateExtension); + + assertThat(repository.findById(certificateExtension.getId()).orElseThrow().getValue()).isEqualTo("test-value"); + } +} diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java new file mode 100644 index 0000000..f107461 --- /dev/null +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java @@ -0,0 +1,58 @@ +package de.mlessmann.certassist.repositories; + +import static org.assertj.core.api.Assertions.assertThat; + +import de.mlessmann.certassist.models.Certificate; +import de.mlessmann.certassist.models.CertificateExtension; +import de.mlessmann.certassist.models.CertificateType; +import jakarta.transaction.Transactional; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CertificateRepositoryTest { + + @Autowired + private CertificateRepository repository; + + @Autowired + private CertificateExtensionRepository extensionRepository; + + private Certificate getCertificate() { + final Certificate certificate = new Certificate(); + certificate.setCommonName("test-cn"); + certificate.setType(CertificateType.SIGNED_CERT); + certificate.setRequestedKeyLength(1); + certificate.setRequestedValidityDays(1); + + return certificate; + } + + @Test + @Transactional + void findCertificate() { + final Certificate certificate = getCertificate(); + repository.save(certificate); + + Certificate foundCertificate = repository.findById(certificate.getId()).orElseThrow(); + assertThat(foundCertificate.getCommonName()).isEqualTo("test-cn"); + assertThat(foundCertificate.getType()).isEqualTo(CertificateType.SIGNED_CERT); + } + + @Test + @Transactional + void findCertificateWithExtension() { + final Certificate certificate = getCertificate(); + CertificateExtension extension = new CertificateExtension(); + extension.setValue("test-ext-value"); + certificate.setCertificateExtension(List.of(extension)); + repository.save(certificate); + + assertThat(repository.findById(certificate.getId()).orElseThrow().getCertificateExtension()).hasSize(1); + assertThat(extensionRepository.findAll()) + .singleElement() + .satisfies(ce -> assertThat(ce.getValue()).isEqualTo("test-ext-value")); + } +} diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java new file mode 100644 index 0000000..2c73ba6 --- /dev/null +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java @@ -0,0 +1,26 @@ +package de.mlessmann.certassist.repositories; + +import static org.assertj.core.api.Assertions.assertThat; + +import de.mlessmann.certassist.models.CertificateSubjectPreset; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CertificateSubjectPresetRepositoryTest { + + @Autowired + private CertificateSubjectPresetRepository repository; + + @Test + @Transactional + void findCertificateSubjectPreset() { + final CertificateSubjectPreset certificateSubjectPreset = new CertificateSubjectPreset(); + certificateSubjectPreset.setCountry("DE"); + repository.save(certificateSubjectPreset); + + assertThat(repository.findById(certificateSubjectPreset.getId()).orElseThrow().getCountry()).isEqualTo("DE"); + } +} diff --git a/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java index 0e6f342..da2468f 100644 --- a/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java +++ b/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java @@ -1,12 +1,13 @@ package de.mlessmann.certassist.repositories; +import static org.assertj.core.api.Assertions.assertThat; + import de.mlessmann.certassist.models.User; +import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import static org.assertj.core.api.Assertions.assertThat; - @SpringBootTest class UserRepositoryTest { @@ -14,11 +15,12 @@ class UserRepositoryTest { private UserRepository userRepository; @Test + @Transactional void findUserById() { final User user = new User(); user.setUsername("test"); userRepository.save(user); - assertThat(userRepository.findUserById(user.getId()).getUsername()).isEqualTo("test"); + assertThat(userRepository.findById(user.getId()).orElseThrow().getUsername()).isEqualTo("test"); } }