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

Fix #971: Add column for signature metadata #985

Merged
merged 15 commits into from
Sep 6, 2023

Conversation

jandusil
Copy link
Contributor

  • Add new column signature_metadata, remove merged columns signature_data_method and signature_data_uri_id, document it in liquibase
  • Edit entity class, introduce new converter

- Add new column signature_metadata, remove merged columns signature_data_method and signature_data_uri_id, document it in liquibase
- Edit entity class, introduce new converter
@jandusil jandusil self-assigned this Aug 24, 2023
@jandusil jandusil linked an issue Aug 24, 2023 that may be closed by this pull request
@jandusil jandusil requested a review from romanstrobl August 28, 2023 22:46
@jandusil jandusil marked this pull request as ready for review August 28, 2023 22:46
Copy link
Member

@romanstrobl romanstrobl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job. Let's review the Liquibase script, because it will not work on other databases such as Oracle.

- Make the change retrospective in terms of liquibase
@jandusil jandusil requested a review from romanstrobl August 29, 2023 11:22
Copy link
Member

@petrdvorak petrdvorak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let's introduce abstraction on signature metadata types. We currently need to have only PowerAuth signature metadata with method and URI ID, but the reason we are making this change is that next release, we will also need to have FIDO2 signature metadata with completely different attributes.

As a result, we need to introduce facilities that allow serialization / deserialization of the specific classes.

- Introduce abstraction for SignatureMetadata
- Add a test
- Introduce more generic approach
@jandusil jandusil requested a review from petrdvorak August 30, 2023 22:26
signatureAuditRecord.setActivation(activationRepository.getReferenceById(activation.getActivationId()));
signatureAuditRecord.setActivationCounter(activation.getCounter());
signatureAuditRecord.setActivationCtrDataBase64(activation.getCtrDataBase64());
signatureAuditRecord.setActivationStatus(activation.getActivationStatus());
signatureAuditRecord.setAdditionalInfo(additionalInfo);
signatureAuditRecord.setDataBase64(data);
signatureAuditRecord.setSignature(signatureData.getSignature());
signatureAuditRecord.setSignatureDataMethod(signatureData.getRequestMethod());
signatureAuditRecord.setSignatureDataUriId(signatureData.getRequestUriId());
signatureAuditRecord.setSignatureMetadata(signatureMetadata);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to adjust the AuditDetail as well? Probably yes, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you mean it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we need to store it in the audit record too. 👍

- Add a test
- Introduce more generic approach
- Change type of signature_metadata to clob
- Incorporate code review comments
- Incorporate code review comments
@jandusil jandusil requested a review from banterCZ September 5, 2023 09:44
Copy link
Member

@romanstrobl romanstrobl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should work as expected, however I suggest we improve the types. In my opinion there is no need to use the ? (any type) in generics, or am I missing something? E.g. we know the resulting value in DB is a String.

@Converter
@Component
@Slf4j
public class SignatureMetadataConverter implements AttributeConverter<SignatureMetadata<?, ?>, String> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we use the <?, ?> type specification?

Copy link
Contributor Author

@jandusil jandusil Sep 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My general idea was that this converter could be used for different types of SignatureMetadata implementations not just the SignatureMetadata<String, String>. Since the props of implementations of SignatureMetadata could be different types, I thought the <?, ?> type specification shall be here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these types which are specified instead of <?, ?> used for? I can't find it in the code. Do we really need to make the class SignatureMetadata generic? What happens if you remove <?, ?> type specification from the 3 places where it is used, will the code still work?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can safely say that <String, Object> will work for us. This allows for a fairly generic way of serialization. Apologies for not specifying this clearer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In current code the usage of generics is really strange. See the following message from IntelliJ IDEA:
image

My point is that we specify types for a generified class SignatureMetadata, however these types are never used, so they just make the code more complicated for no good reason. If you remove the <T1, T2> and <?, ?> types everywhere from the code for the SignatureMetadata, the tests are still green, so why do we need this generification in the first place?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that it's just a leftover from the previous version, where there used to be such code

T1 getMetadataParam1();

- Incorporate code review comments
@jandusil jandusil requested a review from romanstrobl September 5, 2023 14:53
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PowerAuthSignatureMetadata implements SignatureMetadata<String, String>, Serializable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for the change, but just in case, let's make this <String, Object> - I can imagine we would like to encode some FIDO2 specific data and this could require structure to be comprehensive and easy to deserialize back...

@Converter
@Component
@Slf4j
public class SignatureMetadataConverter implements AttributeConverter<SignatureMetadata<?, ?>, String> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can safely say that <String, Object> will work for us. This allows for a fairly generic way of serialization. Apologies for not specifying this clearer.

* @return The JSON string representation of the object.
*/
@Override
public String convertToDatabaseColumn(SignatureMetadata<?, ?> attribute) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dtto

* @return The converted SignatureMetadata object.
*/
@Override
public SignatureMetadata<?, ?> convertToEntityAttribute(String s) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dtto

* Represents PowerAuth signature metadata.
* This value is used for identifying the type of metadata in JSON serialization/deserialization.
*/
public static final String POWERAUTH = "PowerAuthSignatureMetadata";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this will get serialized into the JSON payload, we should use just POWERAUTH. Also, are we sure this will get into the serialized JSON? We need to be able to deserialize it back...

signatureAuditRecord.setActivation(activationRepository.getReferenceById(activation.getActivationId()));
signatureAuditRecord.setActivationCounter(activation.getCounter());
signatureAuditRecord.setActivationCtrDataBase64(activation.getCtrDataBase64());
signatureAuditRecord.setActivationStatus(activation.getActivationStatus());
signatureAuditRecord.setAdditionalInfo(additionalInfo);
signatureAuditRecord.setDataBase64(data);
signatureAuditRecord.setSignature(signatureData.getSignature());
signatureAuditRecord.setSignatureDataMethod(signatureData.getRequestMethod());
signatureAuditRecord.setSignatureDataUriId(signatureData.getRequestUriId());
signatureAuditRecord.setSignatureMetadata(signatureMetadata);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we need to store it in the audit record too. 👍

@JsonSubTypes.Type(value = PowerAuthSignatureMetadata.class,
name = SignatureMetadataType.POWERAUTH)
})
public interface SignatureMetadata<T1, T2> extends Serializable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we keep the type property? We need to have it somewhere so that we are able to deserialize the value back...

Copy link
Contributor Author

@jandusil jandusil Sep 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the type is dynamically added by the annotation during serialization
res: https://www.baeldung.com/jackson-inheritance#bd-1-conversion-between-subtypes

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = PowerAuthSignatureMetadata.class,
                name = SignatureMetadataType.POWERAUTH)
})

Works in the tests I wrote

 @Test
    void convertToDatabaseColumnTest() {
        PowerAuthSignatureMetadata metadata = new PowerAuthSignatureMetadata("POST", "123");
        String jsonStr = converter.convertToDatabaseColumn(metadata);

        assertNotNull(jsonStr);
        assertEquals("{\"type\":\"POWERAUTH\",\"signatureDataMethod\":\"POST\",\"signatureDataUriId\":\"123\"}", jsonStr);
    }

- Incorporate code review comments
@jandusil jandusil requested a review from petrdvorak September 6, 2023 10:27
Copy link
Member

@petrdvorak petrdvorak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks OK now

Copy link
Member

@romanstrobl romanstrobl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better now!

@jandusil jandusil merged commit 7596275 into develop Sep 6, 2023
5 checks passed
@jandusil jandusil deleted the issues/971-signature-metadata-col branch September 6, 2023 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add column for signature metadata
4 participants