1
0

produce client-error for unspecified-properties (#166)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/166
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig
2025-03-20 12:04:57 +01:00
parent 4994bac101
commit e6b32eda88
21 changed files with 148 additions and 47 deletions

View File

@@ -27,7 +27,8 @@ public class JsonObjectMapperConfiguration {
.modules(new JsonNullableModule(), new JavaTimeModule())
.featuresToEnable(
JsonParser.Feature.ALLOW_COMMENTS,
DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS
DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS,
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}

View File

@@ -25,6 +25,12 @@ class HsOfficePartnerEntityPatcher implements EntityPatcher<HsOfficePartnerPatch
@Override
public void apply(final HsOfficePartnerPatchResource resource) {
// HOWTO: allow properties from the GET request to be passed to PATCH, but only if unchanged.
// These properties have to be specified in the OpenAPI PATCH resource specification,
// ídeally with a comment in the description field, that the value mist be unchanged, if given at all.
ignoreUnchangedPropertyValue("uuid", resource.getUuid(), entity.getUuid());
ignoreUnchangedPropertyValue("partnerNumber", resource.getPartnerNumber(), entity.getPartnerNumber().toString());
if (resource.getPartnerRel() != null) {
new HsOfficeRelationPatcher(mapper, em, entity.getPartnerRel()).apply(resource.getPartnerRel());
}

View File

@@ -1,6 +1,19 @@
package net.hostsharing.hsadminng.mapper;
import org.openapitools.jackson.nullable.JsonNullable;
import jakarta.validation.ValidationException;
import java.util.Optional;
public interface EntityPatcher<R> {
void apply(R resource);
default <T> void ignoreUnchangedPropertyValue(final String propertyName, final JsonNullable<T> resourcePropertyValue, final T entityPropertyValue) {
Optional.ofNullable(resourcePropertyValue).ifPresent(value -> {
if (!value.get().equals(entityPropertyValue) ) {
throw new ValidationException(propertyName + " cannot be changed, either leave empty or leave unchanged as " + entityPropertyValue);
}
});
}
}

View File

@@ -48,6 +48,7 @@ components:
nullable: true
resources:
$ref: '#/components/schemas/BookingResources'
additionalProperties: false
HsBookingItemInsert:
type: object

View File

@@ -21,6 +21,7 @@ components:
caption:
type: string
nullable: true
additionalProperties: false
HsBookingProjectInsert:
type: object

View File

@@ -60,6 +60,7 @@ components:
nullable: true
config:
$ref: '#/components/schemas/HsHostingAssetConfiguration'
additionalProperties: false
HsHostingAssetInsert:
type: object

View File

@@ -29,3 +29,4 @@ components:
- holder
- iban
- bic
additionalProperties: false

View File

@@ -31,6 +31,7 @@ components:
$ref: '#/components/schemas/HsOfficeContactPhoneNumbers'
required:
- caption
additionalProperties: false
HsOfficeContactPatch:
type: object
@@ -44,6 +45,7 @@ components:
$ref: '#/components/schemas/HsOfficeContactEmailAddresses'
phoneNumbers:
$ref: '#/components/schemas/HsOfficeContactPhoneNumbers'
additionalProperties: false
HsOfficeContactPostalAddress:
# forces generating a java.lang.Object containing a Map, instead of a class with fixed properties

View File

@@ -67,6 +67,7 @@ components:
type: string
pattern: '^[a-z0-9]{3}$'
nullable: true
additionalProperties: false
HsOfficeDebitorInsert:
type: object
@@ -101,3 +102,4 @@ components:
- debitorNumberSuffix
- defaultPrefix
- billable
additionalProperties: false

View File

@@ -48,6 +48,16 @@ components:
HsOfficePartnerPatch:
type: object
properties:
uuid:
type: string
format: uuid
nullable: true
description: if given (e.g. taken from a GET request), it must be identical to the patched entities uuid
partnerNumber:
type: string
pattern: 'P-[0-9]{5}'
nullable: true
description: if given (e.g. taken from a GET request), it must be identical to the patched entities partnerNumber
partnerRel:
$ref: 'hs-office-relation-schemas.yaml#/components/schemas/HsOfficeRelationPatch'
details:
@@ -78,6 +88,7 @@ components:
type: string
format: date
nullable: true
additionalProperties: false
HsOfficePartnerInsert:
type: object
@@ -93,6 +104,7 @@ components:
- partnerNumber
- partnerRel
- details
additionalProperties: false
HsOfficePartnerRelInsert:
type: object
@@ -111,6 +123,7 @@ components:
- anchor.uuid
- holder.uuid
- relContact.uuid
additionalProperties: false
HsOfficePartnerDetailsInsert:
type: object
@@ -136,3 +149,4 @@ components:
type: string
format: date
nullable: true
additionalProperties: false

View File

@@ -50,12 +50,12 @@ components:
type: string
required:
- personType
additionalProperties: false
HsOfficePersonPatch:
type: object
properties:
personType:
nullable: true
$ref: '#/components/schemas/HsOfficePersonType'
tradeName:
type: string
@@ -72,3 +72,4 @@ components:
familyName:
type: string
nullable: true
additionalProperties: false

View File

@@ -41,6 +41,7 @@ components:
type: string
format: uuid
nullable: true
additionalProperties: false
HsOfficeRelationPatch:
type: object
@@ -95,6 +96,7 @@ components:
description:
Additionally to `type` and `anchor.uuid`, either `anchor.uuid` or `anchor`
and either `contact` or `contact.uuid` need to be given.
additionalProperties: false
# relation created as a sub-element with implicitly known type
HsOfficeRelationSubInsert:
@@ -116,3 +118,4 @@ components:
- anchor.uuid
- holder.uuid
- contact.uuid
additionalProperties: false