jhipster / generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.
https://www.jhipster.tech
Apache License 2.0
21.5k stars 4.02k forks source link

Angular sends whole entity instead of the reference field to the backend #17129

Closed hokrobert closed 5 months ago

hokrobert commented 2 years ago
Overview of the issue

While we did some test upgrades for our application, I noticed a change in behavior of the Angular UI. Lets assume you have two entities. Customer and Installation. One To Many relation and the customer is a required reference for an installation.

When creating an installation the ui sends the id (or the key field) of the customer including all fields for the installation to the backend.

Now after the update to the most recent jhipster version, the ui sends the whole customer entity to the backend.

angular UI with jhipster 6.8.10 Request payload to backend: image

This is the generated model: image

angular UI with jhipster 7.4.0 Request payload to backedn: image

This is the generated model: image

If the backend is created from the same jdl we used for jhipster 6.8.10 with jhipster 7.4.0 also the InstallationDTO now has customerDTO as reference instead of the key field (the id). image

Motivation for or Use Case

This is imho wrong behavior for two reasons:

Reproduce the error
Related issues
Suggest a Fix

Change the behavior of the UI and backend to work only with the reference of an entity not with the whole entity like it was implemented until jhipster 6.8.10

JHipster Version(s)

JHipster 7.4.0

JHipster configuration

{ "generator-jhipster": { "applicationType": "gateway", "baseName": "testportal", "jhipsterVersion": "7.4.0", "skipUserManagement": true, "skipCheckLengthOfIdentifier": false, "skipFakeData": false, "jhiPrefix": "jhi", "entitySuffix": "", "dtoSuffix": "DTO", "testFrameworks": ["cypress"], "blueprints": [], "otherModules": [], "pages": [], "creationTimestamp": 1637766648009, "serviceDiscoveryType": "eureka", "reactive": true, "authenticationType": "oauth2", "packageName": "com.package.my", "serverPort": "8080", "cacheProvider": "no", "enableHibernateCache": false, "databaseType": "no", "devDatabaseType": "no", "prodDatabaseType": "no", "buildTool": "maven", "serverSideOptions": [], "websocket": false, "searchEngine": false, "messageBroker": false, "enableSwaggerCodegen": false, "clientFramework": "angularX", "withAdminUi": true, "clientTheme": "lumen", "clientThemeVariant": "dark", "enableTranslation": true, "nativeLanguage": "en", "jwtSecretKey": "ZDJkYTAyZTRkZmIyNDBhNmE3MblablaZGNmNmIyOWY3Y2JiMjFkM2VhMDI0ZjY4MmI2ZmM2OTM=", "devServerPort": 4200, "clientPackageManager": "npm", "languages": ["en", "fr", "de", "es"], "enableGradleEnterprise": false, "cypressCoverage": false, "entities": [ "Customer", "Installation" ], "lastLiquibaseTimestamp": 1637825363000 } }

Entity configuration(s) entityName.json files generated in the .jhipster directory

{ "name": "Customer", "fields": [ { "fieldName": "cardCode", "fieldType": "String", "fieldValidateRules": ["maxlength", "required", "unique"], "fieldValidateRulesMaxlength": "30" }, { "fieldName": "customerName", "fieldType": "String", "fieldValidateRules": ["maxlength"], "fieldValidateRulesMaxlength": "100" } ], "relationships": [ { "relationshipType": "one-to-many", "otherEntityName": "installation", "otherEntityRelationshipName": "customer", "relationshipName": "installation" } ], "entityTableName": "customer", "dto": "mapstruct", "pagination": "no", "service": "serviceClass", "jpaMetamodelFiltering": false, "fluentMethods": true, "readOnly": false, "embedded": false, "applications": "*", "microserviceName": "testservice", "clientRootFolder": "testservice", "databaseType": "no", "changelogDate": "20211125071654" }

{ "name": "Installation", "fields": [ { "fieldName": "installationNumber", "fieldType": "String", "fieldValidateRules": ["maxlength", "required"], "fieldValidateRulesMaxlength": "30" } ], "relationships": [ { "relationshipType": "one-to-many", "otherEntityName": "bhSystem", "otherEntityRelationshipName": "installation", "relationshipName": "bhSystem" }, { "relationshipType": "many-to-one", "otherEntityName": "customer", "otherEntityRelationshipName": "installation", "relationshipValidateRules": "required", "relationshipName": "customer" } ], "entityTableName": "installation", "dto": "mapstruct", "pagination": "no", "service": "serviceClass", "jpaMetamodelFiltering": false, "fluentMethods": true, "readOnly": false, "embedded": false, "applications": "*", "microserviceName": "testservice", "clientRootFolder": "testservice", "databaseType": "no", "changelogDate": "20211125071655" }

Browsers and Operating System

Mac OS Monterey Tested with brave browser as well as firefox.

mshima commented 2 years ago

Angular will send back whatever the backend returned. JHipster 6 has flatten relationships, JHipster 7 doesn’t. Non DTO will always return the entire entity. DTO on the other hand is supposed to return the id and the label field only. This should be managed by the entity mapper.

vishal423 commented 2 years ago

I also noticed this while implementing relationship support in the svelte blueprint. If you have a relationship with a User entity, then it opens up a security hole and undoes the effect of the special purpose public get all users endpoint.

github-actions[bot] commented 2 years ago

This issue is stale because it has been open 30 days with no activity. Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted. We are accepting PRs :smiley:. Comment or this will be closed in 7 days

mshima commented 2 years ago

If you have a relationship with a User entity, then it opens up a security hole and undoes the effect of the special purpose public get all users endpoint.

That’s the reason for public and admin user. Public only exposes a few fields and is used for relationships.

hokrobert commented 2 years ago

Is there anything left to discuss? I still think, that sending the complete representation of a related business objects is a security flaw. The creation of a child entity should only have the reference to the parent not the whole representation of the parent.

In my opinion it also violates somehow against OWASP - excessive data exposure. Though it is not the response that exposes too much, for the use case not needed, data but the request.

github-actions[bot] commented 10 months ago

This issue is stale because it has been open for too long without any activity. Due to the moving nature of jhipster generated application, bugs can become invalid. If this issue still applies please comment otherwise it will be closed in 7 days

hokrobert commented 10 months ago

Is there still anything left to discuss?

mshima commented 10 months ago

I suppose a @JsonIncludeProperty({ "<%- relationship.otherEntity.primaryKey.name %>", "<%- relationship.relationshipOtherFieldName %>" }) in dto relationships should fix this issue. @hokrobert can you contribute with a PR?

mshima commented 10 months ago

Entity mappers filter the value by default:

    @Named("mapsIdChildEntityWithDTOId")
    @BeanMapping(ignoreByDefault = true)
    @Mapping(target = "id", source = "id")
    MapsIdChildEntityWithDTO toDtoMapsIdChildEntityWithDTOId(MapsIdChildEntityWithDTOEntity mapsIdChildEntityWithDTOEntity);

But the serialized json includes fields with null values.

csfercoci commented 5 months ago

when will be this fixed?