Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses duplicate user_registration rows being created for the same EPerson during import/usage in CLARIN-DSpace (DSpace 7 REST backend), by enforcing uniqueness at both the application and database layers and adding integration tests to validate the behavior.
Changes:
- Prevent duplicate registrations by updating an existing registration when
eperson_idmatches (service-layer guard). - Ensure the EPerson import endpoint does not leave behind an automatically created “Unknown” registration.
- Add DB migrations introducing a unique index on
user_registration.eperson_idand expand DAO email lookup to support semicolon-separated email values.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
dspace-api/src/main/java/org/dspace/content/clarin/ClarinUserRegistrationServiceImpl.java |
Updates create() to update an existing registration when eperson_id already exists. |
dspace-api/src/main/java/org/dspace/content/dao/impl/clarin/ClarinUserRegistrationDAOImpl.java |
Expands findByEmail matching to handle semicolon-separated email strings. |
dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClarinEPersonImportController.java |
Removes auto-created registrations during EPerson import so registrations are managed by the dedicated endpoint. |
dspace-api/src/main/resources/.../postgres/V7.6_2026.03.10__user_registration_unique_eperson_id.sql |
Adds a (partial) unique index on eperson_id in PostgreSQL. |
dspace-api/src/main/resources/.../h2/V7.6_2026.03.10__user_registration_unique_eperson_id.sql |
Adds a unique index on eperson_id in H2 for tests/dev. |
dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinUserRegistrationServiceImplIT.java |
Adds integration tests covering dedup/update behavior and null-eperson cases. |
dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinEPersonImportControllerIT.java |
Adds an integration test asserting EPerson import does not create a user registration. |
...storage/rdbms/sqlmigration/postgres/V7.6_2026.03.10__user_registration_unique_eperson_id.sql
Show resolved
Hide resolved
…er_registration, updated tests, upadted import for user_registration
There was a problem hiding this comment.
Pull request overview
This PR addresses duplicate CLARIN user_registration rows per EPerson by making registrations uniquely keyed by eperson_id and removing the now-redundant email field across the REST layer, service layer, and database schema.
Changes:
- Enforce uniqueness of
user_registration.eperson_id(and add service-level dedup/update behavior). - Remove
emailfromClarinUserRegistrationentity + REST model/converter and adjust related callers. - Update/extend integration tests to cover deduplication and import behavior.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| dspace-server-webapp/src/test/java/org/dspace/app/rest/EPersonRestRepositoryIT.java | Updates assertions to reflect removal of registration email in REST responses. |
| dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinUserRegistrationServiceImplIT.java | Adds IT coverage for “create() does not duplicate eperson_id” and null-eperson behavior. |
| dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinEPersonImportControllerIT.java | Adjusts import tests for ePersonID-based matching and adds test ensuring import doesn’t auto-create registration. |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/EPersonRestRepository.java | Stops setting ClarinUserRegistration.email when auto-creating registration for new EPersons. |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClarinUserRegistrationRestRepository.java | Introduces a leading blank line before header comment (formatting only). |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClarinUserMetadataRestController.java | Switches anonymous registration lookup from findByEmail to findByOrganization. |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClarinEPersonImportController.java | Deletes auto-created “Unknown” registration during eperson import; imports registrations by ePersonID only. |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/model/ClarinUserRegistrationRest.java | Removes email from REST representation. |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/ClarinUserRegistrationConverter.java | Removes mapping of entity email to REST DTO. |
| dspace-api/src/test/java/org/dspace/builder/ClarinUserRegistrationBuilder.java | Removes builder support for setting email. |
| dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/postgres/V7.6_2026.03.10__user_registration_unique_eperson_id.sql | Adds unique index on eperson_id (partial) and drops email column. |
| dspace-api/src/main/resources/org/dspace/storage/rdbms/sqlmigration/h2/V7.6_2026.03.10__user_registration_unique_eperson_id.sql | Adds unique index on eperson_id and drops email column for H2. |
| dspace-api/src/main/java/org/dspace/eperson/EPersonCLITool.java | Stops setting registration email when creating CLARIN registration from CLI. |
| dspace-api/src/main/java/org/dspace/content/service/clarin/ClarinUserRegistrationService.java | Replaces findByEmail with findByOrganization. |
| dspace-api/src/main/java/org/dspace/content/packager/RoleIngester.java | Creates registration only for newly created EPersons (not colliders). |
| dspace-api/src/main/java/org/dspace/content/dao/impl/clarin/ClarinUserRegistrationDAOImpl.java | Implements findByOrganization query instead of findByEmail. |
| dspace-api/src/main/java/org/dspace/content/dao/clarin/ClarinUserRegistrationDAO.java | Updates DAO interface to findByOrganization. |
| dspace-api/src/main/java/org/dspace/content/crosswalk/AIPTechMDCrosswalk.java | Creates registration for newly created submitter eperson (no email field). |
| dspace-api/src/main/java/org/dspace/content/clarin/ClarinUserRegistrationServiceImpl.java | Adds dedup logic: create() updates existing registration for same eperson_id. |
| dspace-api/src/main/java/org/dspace/content/clarin/ClarinUserRegistration.java | Removes email column/field; marks eperson_id column as unique in JPA mapping. |
| dspace-api/src/main/java/org/dspace/authenticate/clarin/ClarinShibAuthentication.java | Removes registration email usage; syncs organization on update. |
| dspace-api/src/main/java/org/dspace/authenticate/X509Authentication.java | Creates registration without email for self-registered users. |
| dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java | Removes registration email usage; syncs organization on update. |
| dspace-api/src/main/java/org/dspace/authenticate/OrcidAuthenticationBean.java | Creates registration without email for newly registered users. |
| dspace-api/src/main/java/org/dspace/authenticate/OidcAuthenticationBean.java | Creates registration without email for newly registered users. |
| dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java | Creates registration without email for newly registered users. |
| dspace-api/src/main/java/org/dspace/administer/CreateAdministrator.java | Stops setting registration email when creating admin CLARIN registration. |
...storage/rdbms/sqlmigration/postgres/V7.6_2026.03.10__user_registration_unique_eperson_id.sql
Show resolved
Hide resolved
...space/storage/rdbms/sqlmigration/h2/V7.6_2026.03.10__user_registration_unique_eperson_id.sql
Show resolved
Hide resolved
dspace-api/src/main/java/org/dspace/content/clarin/ClarinUserRegistration.java
Outdated
Show resolved
Hide resolved
...erver-webapp/src/main/java/org/dspace/app/rest/repository/ClarinEPersonImportController.java
Outdated
Show resolved
Hide resolved
dspace-api/src/main/java/org/dspace/content/clarin/ClarinUserRegistrationServiceImpl.java
Show resolved
Hide resolved
...ebapp/src/main/java/org/dspace/app/rest/repository/ClarinUserRegistrationRestRepository.java
Outdated
Show resolved
Hide resolved
dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinEPersonImportControllerIT.java
Outdated
Show resolved
Hide resolved
dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinUserRegistrationServiceImplIT.java
Outdated
Show resolved
Hide resolved
dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinUserRegistrationServiceImplIT.java
Outdated
Show resolved
Hide resolved
dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinUserRegistrationServiceImplIT.java
Outdated
Show resolved
Hide resolved
dspace-api/src/main/java/org/dspace/content/clarin/ClarinUserRegistrationServiceImpl.java
Show resolved
Hide resolved
...storage/rdbms/sqlmigration/postgres/V7.6_2026.03.10__user_registration_unique_eperson_id.sql
Show resolved
Hide resolved
...space/storage/rdbms/sqlmigration/h2/V7.6_2026.03.10__user_registration_unique_eperson_id.sql
Show resolved
Hide resolved
| throw new UnprocessableEntityException("Error parsing request body", e1); | ||
| } |
There was a problem hiding this comment.
The request body parsing currently relies on a freshly constructed Jackson ObjectMapper (earlier in this method). Now that email was removed from ClarinUserRegistrationRest, older import clients that still send an email field may fail deserialization with an unknown-property error and land in this catch block. Consider using the REST-configured ObjectMapper (or configuring/annotating the model to ignore unknown properties) to keep the import endpoint backward compatible where possible.
There was a problem hiding this comment.
@milanmajchrak can you check this on frontend, what is sending from there? I have no more copilot....
|
@milanmajchrak the failed tests, I have no more copilot for fix |
Problem description
After the import and during DSpace usage, multiple user registrations were created for a single EPerson.
Problem: If an EPerson already existed and was not newly created during the process, a new user registration was still created.
Manual Testing (if applicable)
Copilot review