Skip to content

Feature/sab#653

Merged
oharsta merged 16 commits intomainfrom
feature/sab
Feb 24, 2026
Merged

Feature/sab#653
oharsta merged 16 commits intomainfrom
feature/sab

Conversation

@oharsta
Copy link
Copy Markdown
Member

@oharsta oharsta commented Feb 23, 2026

See #650

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements CRM (Customer Relationship Management) integration to support SAB (SURFconext Autorisatie Beheer) phaseout by allowing Invite to receive CRM messages about contact persons, organizations, and roles, and to provide SAB authorization attributes to service providers.

Changes:

  • Adds a new CRM API endpoint (/api/internal/v1/crm) for receiving POST (provision/invite users) and DELETE (remove users) requests from CRM
  • Implements SAB attribute generation in the Attribute Aggregator to return organization codes, GUIDs, and role URNs for CRM-managed users
  • Adds database schema changes to track CRM-specific information (contact IDs, organization IDs, role IDs) in users, roles, and invitations tables

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
server/src/main/resources/db/mysql/migration/V55_0__crm_roles_users.sql Adds CRM-related columns to roles, users, and invitations tables with appropriate indexes
server/src/main/resources/crm/crm_config.json Configuration mapping SAB codes to role names and associated applications
server/src/main/resources/application.yml Adds CRM configuration properties (API key, collab person prefix, config resource path)
server/src/main/java/invite/security/SecurityConfig.java Adds security filter chain for CRM API with API-KEY header authentication
server/src/main/java/invite/repository/UserRepository.java Adds query method to find users by CRM contact ID
server/src/main/java/invite/repository/RoleRepository.java Adds query method to find roles by CRM role ID
server/src/main/java/invite/provision/scim/GroupURN.java Updates URN generation to support SAB role URN format for CRM roles
server/src/main/java/invite/provision/ProvisioningServiceDefault.java Removes unused roleRepository field
server/src/main/java/invite/model/User.java Adds crmContactId field and reorders constructor
server/src/main/java/invite/model/Role.java Adds CRM-related fields (organisation ID/code, role ID/name)
server/src/main/java/invite/model/Invitation.java Adds crmContactId field
server/src/main/java/invite/mail/MailBox.java Minor indentation fix
server/src/main/java/invite/exception/InvitationUniqueCrmOrganisationException.java New exception for enforcing single-organization constraint per SAB requirements
server/src/main/java/invite/crm/CrmManageIdentifier.java Record class for CRM manage identifier configuration
server/src/main/java/invite/crm/CrmConfigEntry.java Record class for CRM configuration entries
server/src/main/java/invite/crm/CRMRole.java DTO for CRM role data
server/src/main/java/invite/crm/CRMOrganisation.java DTO for CRM organization data
server/src/main/java/invite/crm/CRMController.java Main controller implementing CRM POST/DELETE endpoints for user provisioning and invitation
server/src/main/java/invite/crm/CRMContact.java DTO for CRM contact data
server/src/main/java/invite/api/InvitationOperations.java Refactors identityProviderName to static method for reuse
server/src/main/java/invite/api/InvitationController.java Adds validation to enforce single-organization constraint for CRM invitations; expands imports
server/src/main/java/invite/aggregation/AttributeAggregatorController.java Adds SAB organization codes/GUIDs to attribute aggregation response for CRM users
server/src/test/java/invite/crm/CRMControllerTest.java Test cases for CRM contact provisioning and invitation flows
server/src/test/java/invite/AbstractMailTest.java Adds myconext.uri to test configuration
server/src/test/resources/crm/put.json Test data for CRM PUT requests
server/src/test/resources/crm/post.json Test data for CRM POST requests
server/src/test/resources/crm/delete.json Test data for CRM DELETE requests

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

null,
Language.en,
null,
null,//Defauly expiryDate
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

There is a typo in the comment: "Defauly" should be "Default".

Suggested change
null,//Defauly expiryDate
null,//Default expiryDate

Copilot uses AI. Check for mistakes.
null,//Defauly expiryDate
null,
invitationRoles,
null
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The crmContactId is not being set on the created invitation. This means the checkCrmUniqueOrganisation validation in InvitationController will not work correctly for CRM invitations. The invitation should have its crmContactId set from crmContact.getContactId().

Suggested change
null
crmContact.getContactId()

Copilot uses AI. Check for mistakes.
Comment on lines +122 to +135
@DeleteMapping("")
public ResponseEntity<String> delete(@RequestBody CRMContact crmContact) {
LOG.debug("DELETE /api/external/v1/crm: " + crmContact);

List<User> users = userRepository.findByCrmContactId(crmContact.getContactId());
users.forEach(user -> {
LOG.info("Deleting CRM user: " + user.getEmail());

this.provisioningService.deleteUserRequest(user);
this.userRepository.delete(user);
});

return ResponseEntity.ok().body("deleted");
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

The DELETE endpoint deletes all users with the given contactId, which may be incorrect behavior. According to the issue description, a DELETE should remove roles, not delete the entire user. The delete.json test data includes organization information, suggesting that DELETE should remove roles for a specific contact-organization combination rather than deleting all users with that contactId. Additionally, there may be legitimate non-CRM roles that should be preserved.

Copilot uses AI. Check for mistakes.
Comment on lines +137 to +152
private boolean provisionUser(CRMContact crmContact) {
String sub = constructSub(crmContact);
Optional<User> optionalUser = userRepository.findBySubIgnoreCase(sub);
User user = optionalUser.orElseGet(() -> createUser(crmContact, sub));
List<CRMRole> newCrmRoles = syncCrmRoles(crmContact, user);

List<Role> roles = convertCrmRolesToInviteRoles(crmContact, newCrmRoles);
roles
.forEach(role -> {
UserRole userRole = new UserRole(Authority.GUEST, role);
user.addUserRole(userRole);
this.provisioningService.updateGroupRequest(userRole, OperationType.add);
});
userRepository.save(user);
return optionalUser.isEmpty();
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

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

Missing audit logging for CRM operations. The userRoleAuditService is injected but never used. When user roles are added or removed through CRM operations, the changes should be logged using userRoleAuditService.logAction, as done in other controllers (InvitationController, UserRoleController, TeamsController).

Copilot uses AI. Check for mistakes.
oharsta and others added 10 commits February 23, 2026 20:33
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@oharsta oharsta merged commit bf00458 into main Feb 24, 2026
3 checks passed
@github-project-automation github-project-automation bot moved this from New to Delivered in Openconext-Invite Feb 24, 2026
@oharsta oharsta deleted the feature/sab branch February 24, 2026 18:00
@phavekes phavekes added this to the 1.1.0 milestone Mar 19, 2026
@phavekes phavekes moved this from Delivered to Ready for release in Openconext-Invite Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready for release

Development

Successfully merging this pull request may close these issues.

4 participants