diff --git a/docs/db/changelog/changesets/powerauth-java-server/1.5.x/20230323-add-column-signature-metadata.xml b/docs/db/changelog/changesets/powerauth-java-server/1.5.x/20230323-add-column-signature-metadata.xml new file mode 100644 index 000000000..421ee377d --- /dev/null +++ b/docs/db/changelog/changesets/powerauth-java-server/1.5.x/20230323-add-column-signature-metadata.xml @@ -0,0 +1,18 @@ + + + + + + + + + + Add signature_metadata column of type Clob + + + + + + diff --git a/docs/db/changelog/changesets/powerauth-java-server/1.5.x/20230323-add-columns-signature-data.xml b/docs/db/changelog/changesets/powerauth-java-server/1.5.x/20230323-add-columns-signature-data.xml deleted file mode 100644 index b99f2b623..000000000 --- a/docs/db/changelog/changesets/powerauth-java-server/1.5.x/20230323-add-columns-signature-data.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - Add signature_data_method column - - - - - - - - - - - - Add signature_data_uri_id column - - - - - - - - - - - - Add signature_data_body column - - - - - - diff --git a/docs/db/changelog/changesets/powerauth-java-server/1.5.x/db.changelog-version.xml b/docs/db/changelog/changesets/powerauth-java-server/1.5.x/db.changelog-version.xml index 20cffd003..cbb1867c5 100644 --- a/docs/db/changelog/changesets/powerauth-java-server/1.5.x/db.changelog-version.xml +++ b/docs/db/changelog/changesets/powerauth-java-server/1.5.x/db.changelog-version.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd"> - + diff --git a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/PowerAuthSignatureMetadata.java b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/PowerAuthSignatureMetadata.java new file mode 100644 index 000000000..37d606503 --- /dev/null +++ b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/PowerAuthSignatureMetadata.java @@ -0,0 +1,62 @@ +/* + * PowerAuth Server and related software components + * Copyright (C) 2023 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.getlime.security.powerauth.app.server.database.model; + +import lombok.AllArgsConstructor; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.util.Objects; + + +/** + * Concrete implementation of the {@link SignatureMetadata} interface for PowerAuth. + * Contains metadata parameters specific to PowerAuth Signature. + * + * @author Jan Dusil + */ +@AllArgsConstructor +@NoArgsConstructor +@Data +public class PowerAuthSignatureMetadata implements SignatureMetadata { + + @Serial + private static final long serialVersionUID = -5167321997819747483L; + + @JsonProperty("signatureDataMethod") + private String signatureDataMethod; + @JsonProperty("signatureDataUriId") + private String signatureDataUriId; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PowerAuthSignatureMetadata that = (PowerAuthSignatureMetadata) o; + return Objects.equals(signatureDataMethod, that.signatureDataMethod) && + Objects.equals(signatureDataUriId, that.signatureDataUriId); + } + + @Override + public int hashCode() { + return Objects.hash(signatureDataMethod, signatureDataUriId); + } +} diff --git a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/SignatureMetadata.java b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/SignatureMetadata.java new file mode 100644 index 000000000..4d40a4001 --- /dev/null +++ b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/SignatureMetadata.java @@ -0,0 +1,45 @@ +/* + * PowerAuth Server and related software components + * Copyright (C) 2023 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.getlime.security.powerauth.app.server.database.model; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.getlime.security.powerauth.app.server.database.model.enumeration.SignatureMetadataType; + +import java.io.Serializable; + +/** + * Represents an interface for metadata related to different types of signatures. + * The interface is designed to work specifically with metadata attributes of type + * String for the first parameter and Object for the second parameter. This allows + * the flexibility to capture various metadata details according to the specific + * requirements of different signature algorithms or methods. + * + * @author Jan Dusil + */ +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(value = PowerAuthSignatureMetadata.class, + name = SignatureMetadataType.POWERAUTH) +}) +public interface SignatureMetadata extends Serializable { + +} + + diff --git a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/converter/SignatureMetadataConverter.java b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/converter/SignatureMetadataConverter.java new file mode 100644 index 000000000..817b927ca --- /dev/null +++ b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/converter/SignatureMetadataConverter.java @@ -0,0 +1,100 @@ +/* + * PowerAuth Server and related software components + * Copyright (C) 2023 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.getlime.security.powerauth.app.server.database.model.converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.getlime.security.powerauth.app.server.database.model.SignatureMetadata; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * A JPA attribute converter for converting SignatureMetadata objects to and from JSON representations. + * This class enables storing SignatureMetadata in the database as a JSON column. + * + * @author Jan Dusil + */ +@Converter +@Component +@Slf4j +public class SignatureMetadataConverter implements AttributeConverter { + + private final ObjectMapper objectMapper; + + /** + * Default constructor that initializes a default ObjectMapper. + */ + public SignatureMetadataConverter() { + this.objectMapper = new ObjectMapper(); + } + + /** + * Constructor that initializes the ObjectMapper. + * + * @param objectMapper The Jackson ObjectMapper. + */ + @Autowired + public SignatureMetadataConverter(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + /** + * Converts a SignatureMetadata object to its JSON string representation. + * + * @param attribute The SignatureMetadata object to convert. + * @return The JSON string representation of the object. + */ + @Override + public String convertToDatabaseColumn(SignatureMetadata attribute) { + if (attribute == null) { + return "{}"; + } + try { + return objectMapper.writeValueAsString(attribute); + } catch (JsonProcessingException ex) { + logger.warn("JSON writing error", ex); + return "{}"; + } + } + + /** + * Converts a JSON string representation to a SignatureMetadata object. + * + * @param s The JSON string to convert. + * @return The converted SignatureMetadata object. + */ + @Override + public SignatureMetadata convertToEntityAttribute(String s) { + if (StringUtils.isBlank(s)) { + return null; + } + try { + return objectMapper.readValue(s, new TypeReference<>() { + }); + } catch (JsonProcessingException ex) { + logger.warn("Conversion failed for SignatureMetadata, error: " + ex.getMessage(), ex); + return null; + } + } +} \ No newline at end of file diff --git a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/entity/SignatureEntity.java b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/entity/SignatureEntity.java index 7b410035c..7ff86b51a 100644 --- a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/entity/SignatureEntity.java +++ b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/entity/SignatureEntity.java @@ -17,7 +17,9 @@ */ package io.getlime.security.powerauth.app.server.database.model.entity; +import io.getlime.security.powerauth.app.server.database.model.PowerAuthSignatureMetadata; import io.getlime.security.powerauth.app.server.database.model.converter.ActivationStatusConverter; +import io.getlime.security.powerauth.app.server.database.model.converter.SignatureMetadataConverter; import io.getlime.security.powerauth.app.server.database.model.enumeration.ActivationStatus; import jakarta.persistence.*; @@ -73,11 +75,9 @@ public class SignatureEntity implements Serializable { @Column(name = "signature", nullable = false, updatable = false) private String signature; - @Column(name = "signature_data_method", updatable = false) - private String signatureDataMethod; - - @Column(name = "signature_data_uri_id", updatable = false) - private String signatureDataUriId; + @Column(name = "signature_metadata") + @Convert(converter = SignatureMetadataConverter.class) + private PowerAuthSignatureMetadata signatureMetadata; @Column(name = "signature_data_body", updatable = false) private String signatureDataBody; @@ -104,7 +104,7 @@ public SignatureEntity() { * Constructor with all properties. * * @param id Signature audit item record ID. - * @param activation Associated activation, or null of no related activation was found. + * @param activation Associated activation, or null if no related activation was found. * @param activationCounter Activation counter at the time of signature computation attempt, or 0 if activation is null. * @param activationCtrDataBase64 Activation counter data at the time of signature computation attempt, or null if only numeric counter is used. * @param activationStatus Activation status at the time of signature computation attempt. @@ -112,13 +112,13 @@ public SignatureEntity() { * @param signatureVersion Requested signature version. * @param signatureType Requested signature type. * @param signature Signature value. - * @param signatureDataMethod Signature data method. - * @param signatureDataUriId Signature data URI identifier. + * @param signatureMetadata Metadata related to the signature. * @param signatureDataBody Signature data body. * @param additionalInfo Additional information related to this signature. * @param note Signature audit log note, with more information about the log reason. * @param valid True if the signature was valid, false otherwise. - * @param timestampCreated Created timestapm. + * @param timestampCreated Created timestamp. + * @param version Version of the signature entity. */ public SignatureEntity( Long id, @@ -130,8 +130,7 @@ public SignatureEntity( String signatureVersion, String signatureType, String signature, - String signatureDataMethod, - String signatureDataUriId, + PowerAuthSignatureMetadata signatureMetadata, String signatureDataBody, String additionalInfo, String note, @@ -148,8 +147,7 @@ public SignatureEntity( this.signatureVersion = signatureVersion; this.signatureType = signatureType; this.signature = signature; - this.signatureDataMethod = signatureDataMethod; - this.signatureDataUriId = signatureDataUriId; + this.signatureMetadata = signatureMetadata; this.signatureDataBody = signatureDataBody; this.additionalInfo = additionalInfo; this.note = note; @@ -337,39 +335,21 @@ public void setSignature(String signature) { } /** - * Get signature data HTTP method. + * Get the signature metadata associated with this signature. * - * @return Signature data HTTP method. + * @return Signature metadata. */ - public String getSignatureDataMethod() { - return signatureDataMethod; + public PowerAuthSignatureMetadata getSignatureMetadata() { + return signatureMetadata; } /** - * Set signature data HTTP method. + * Set the signature metadata associated with this signature. * - * @param signatureDataMethod Signature data HTTP method. + * @param signatureMetadata Metadata related to the signature. */ - public void setSignatureDataMethod(String signatureDataMethod) { - this.signatureDataMethod = signatureDataMethod; - } - - /** - * Get signature data resource URI identifier. - * - * @return Signature data resource URI identifier. - */ - public String getSignatureDataUriId() { - return signatureDataUriId; - } - - /** - * Set signature data resource URI identifier. - * - * @param signatureDataUriId Signature data URI identifier. - */ - public void setSignatureDataUriId(String signatureDataUriId) { - this.signatureDataUriId = signatureDataUriId; + public void setSignatureMetadata(PowerAuthSignatureMetadata signatureMetadata) { + this.signatureMetadata = signatureMetadata; } /** @@ -468,8 +448,7 @@ public int hashCode() { hash = 23 * hash + Objects.hashCode(this.dataBase64); hash = 23 * hash + Objects.hashCode(this.signatureType); hash = 23 * hash + Objects.hashCode(this.signature); - hash = 23 * hash + Objects.hashCode(this.signatureDataMethod); - hash = 23 * hash + Objects.hashCode(this.signatureDataUriId); + hash = 23 * hash + Objects.hashCode(this.signatureMetadata); hash = 23 * hash + Objects.hashCode(this.signatureDataBody); hash = 23 * hash + Objects.hashCode(this.additionalInfo); hash = 23 * hash + Objects.hashCode(this.note); @@ -500,10 +479,7 @@ public boolean equals(Object obj) { if (!Objects.equals(this.signature, other.signature)) { return false; } - if (!Objects.equals(this.signatureDataMethod, other.signatureDataMethod)) { - return false; - } - if (!Objects.equals(this.signatureDataUriId, other.signatureDataUriId)) { + if (!Objects.equals(this.signatureMetadata, other.signatureMetadata)) { return false; } if (!Objects.equals(this.signatureDataBody, other.signatureDataBody)) { diff --git a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/enumeration/SignatureMetadataType.java b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/enumeration/SignatureMetadataType.java new file mode 100644 index 000000000..220ff5f37 --- /dev/null +++ b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/database/model/enumeration/SignatureMetadataType.java @@ -0,0 +1,39 @@ +/* + * PowerAuth Server and related software components + * Copyright (C) 2023 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package io.getlime.security.powerauth.app.server.database.model.enumeration; + +/** + * Enumeration constants representing the types of signature metadata supported in the application. + * These constants are used as names in JSON subtypes and therefore must be kept in sync. + *

+ * Note: Although it is represented as a class with static final String fields, it serves + * the purpose of an enum type for specific use cases that require constant String values. + *

+ * + * @author Jan Dusil + */ +public class SignatureMetadataType { + + /** + * Represents PowerAuth signature metadata. + * This value is used for identifying the type of metadata in JSON serialization/deserialization. + */ + public static final String POWERAUTH = "POWERAUTH"; +} + diff --git a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/service/behavior/tasks/AuditingServiceBehavior.java b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/service/behavior/tasks/AuditingServiceBehavior.java index e0c8f29b9..515f493bc 100644 --- a/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/service/behavior/tasks/AuditingServiceBehavior.java +++ b/powerauth-java-server/src/main/java/io/getlime/security/powerauth/app/server/service/behavior/tasks/AuditingServiceBehavior.java @@ -26,6 +26,8 @@ import io.getlime.security.powerauth.app.server.converter.ActivationStatusConverter; import io.getlime.security.powerauth.app.server.converter.KeyValueMapConverter; import io.getlime.security.powerauth.app.server.converter.SignatureTypeConverter; +import io.getlime.security.powerauth.app.server.database.model.PowerAuthSignatureMetadata; +import io.getlime.security.powerauth.app.server.database.model.converter.SignatureMetadataConverter; import io.getlime.security.powerauth.app.server.database.model.entity.ActivationRecordEntity; import io.getlime.security.powerauth.app.server.database.model.entity.SignatureEntity; import io.getlime.security.powerauth.app.server.database.model.enumeration.ActivationStatus; @@ -57,6 +59,8 @@ public class AuditingServiceBehavior { // Prepare converters private final ActivationStatusConverter activationStatusConverter = new ActivationStatusConverter(); private final SignatureTypeConverter signatureTypeConverter = new SignatureTypeConverter(); + + private final SignatureMetadataConverter signatureMetadataConverter = new SignatureMetadataConverter(); private final KeyValueMapConverter keyValueMapConverter; // Generic auditing capability @@ -157,6 +161,7 @@ public void logSignatureAuditRecord(ActivationRecordDto activation, SignatureDat // Audit the signature final SignatureEntity signatureAuditRecord = new SignatureEntity(); + final PowerAuthSignatureMetadata signatureMetadata = new PowerAuthSignatureMetadata(signatureData.getRequestMethod(), signatureData.getRequestUriId()); signatureAuditRecord.setActivation(activationRepository.getReferenceById(activation.getActivationId())); signatureAuditRecord.setActivationCounter(activation.getCounter()); signatureAuditRecord.setActivationCtrDataBase64(activation.getCtrDataBase64()); @@ -164,8 +169,7 @@ public void logSignatureAuditRecord(ActivationRecordDto activation, SignatureDat signatureAuditRecord.setAdditionalInfo(additionalInfo); signatureAuditRecord.setDataBase64(data); signatureAuditRecord.setSignature(signatureData.getSignature()); - signatureAuditRecord.setSignatureDataMethod(signatureData.getRequestMethod()); - signatureAuditRecord.setSignatureDataUriId(signatureData.getRequestUriId()); + signatureAuditRecord.setSignatureMetadata(signatureMetadata); signatureAuditRecord.setSignatureDataBody(signatureData.getRequestBody()); signatureAuditRecord.setSignatureType(signatureType.name()); signatureAuditRecord.setSignatureVersion(signatureData.getSignatureVersion()); @@ -187,8 +191,7 @@ public void logSignatureAuditRecord(ActivationRecordDto activation, SignatureDat .param("additionalInfo", additionalInfo) .param("data", data) .param("signature", signatureData.getSignature()) - .param("signatureDataMethod", signatureData.getRequestMethod()) - .param("signatureDataUriId", signatureData.getRequestUriId()) + .param("signatureMetadata", signatureMetadataConverter.convertToDatabaseColumn(signatureMetadata)) .param("signatureDataBody", signatureData.getRequestBody()) .param("signatureType", signatureType.name()) .param("signatureVersion", signatureData.getSignatureVersion()) diff --git a/powerauth-java-server/src/test/java/io/getlime/security/powerauth/app/server/service/model/signature/SignatureMetadataConverterTest.java b/powerauth-java-server/src/test/java/io/getlime/security/powerauth/app/server/service/model/signature/SignatureMetadataConverterTest.java new file mode 100644 index 000000000..0b72eec44 --- /dev/null +++ b/powerauth-java-server/src/test/java/io/getlime/security/powerauth/app/server/service/model/signature/SignatureMetadataConverterTest.java @@ -0,0 +1,99 @@ +/* + * PowerAuth Server and related software components + * Copyright (C) 2023 Wultra s.r.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package io.getlime.security.powerauth.app.server.service.model.signature; + +import io.getlime.security.powerauth.app.server.database.model.PowerAuthSignatureMetadata; +import io.getlime.security.powerauth.app.server.database.model.SignatureMetadata; +import io.getlime.security.powerauth.app.server.database.model.converter.SignatureMetadataConverter; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * Test class for SignatureMetadataConverter. + * This class tests various aspects of converting SignatureMetadata to and from its serialized JSON form. + * + * @author Jan Dusil + */ +public class SignatureMetadataConverterTest { + + /** + * Converter object to be used for tests. + */ + private SignatureMetadataConverter converter; + + /** + * Initializes the SignatureMetadataConverter object and any other necessary objects. + */ + @BeforeEach + void setUp() { + converter = new SignatureMetadataConverter(); + } + + /** + * Tests the conversion of a PowerAuthSignatureMetadata object to its serialized JSON form. + */ + @Test + void convertToDatabaseColumnTest() { + PowerAuthSignatureMetadata metadata = new PowerAuthSignatureMetadata("POST", "123"); + String jsonStr = converter.convertToDatabaseColumn(metadata); + + assertNotNull(jsonStr); + assertEquals("{\"type\":\"POWERAUTH\",\"signatureDataMethod\":\"POST\",\"signatureDataUriId\":\"123\"}", jsonStr); + } + + /** + * Tests the conversion of a serialized JSON string back to a SignatureMetadata object. + */ + @Test + void convertToEntityAttributeTest() { + String jsonStr = "{\"type\":\"POWERAUTH\",\"signatureDataMethod\":\"POST\",\"signatureDataUriId\":\"123\"}"; + PowerAuthSignatureMetadata metadata = (PowerAuthSignatureMetadata) converter.convertToEntityAttribute(jsonStr); + + assertNotNull(metadata); + assertEquals("POST", metadata.getSignatureDataMethod()); + assertEquals("123", metadata.getSignatureDataUriId()); + } + + /** + * Tests a round-trip conversion, from object to JSON string and back to object, to ensure consistency. + */ + @Test + void testRoundTripConversion() { + PowerAuthSignatureMetadata originalMetadata = new PowerAuthSignatureMetadata("POST", "123"); + String jsonStr = converter.convertToDatabaseColumn(originalMetadata); + PowerAuthSignatureMetadata convertedMetadata = (PowerAuthSignatureMetadata) converter.convertToEntityAttribute(jsonStr); + + assertNotNull(convertedMetadata); + assertEquals(originalMetadata.getSignatureDataMethod(), convertedMetadata.getSignatureDataMethod()); + assertEquals(originalMetadata.getSignatureDataUriId(), convertedMetadata.getSignatureDataUriId()); + } + + /** + * Tests the converter's behavior when provided with an invalid JSON string. + */ + @Test + void testInvalidJsonInput() { + String invalidJson = "{\"invalidField\":\"someValue\"}"; + SignatureMetadata metadata = converter.convertToEntityAttribute(invalidJson); + assertNull(metadata); + } +}