Skip to content

Conversation

@larskemper
Copy link
Member

@larskemper larskemper commented Nov 26, 2025

resolves shopware/shopware#13670

SwagMigrationConnector pr: shopware/SwagMigrationConnector#5

This pull request introduces a fingerprinting mechanism for migration connections to prevent duplicate source system connections.

Changes:

  • Added a new sourceSystemFingerprint column to the swag_migration_connection table.
  • Introduced MigrationFingerprintProviders to extract data & generate fingerprints for specific migration profiles
  • Introduced MigrationFingerprintService to generate fingerprints for connections utilizing the MigrationFingerprintProviders
  • Updated RunService::updateConnectionCredentials to generate and store the fingerprint, and throw a MigrationException if a duplicate source system connection is detected.
  • Added a new DUPLICATE_SOURCE_CONNECTION error code and exception to handle duplicate source system connections.

Strategy

Shopware 6

For Shopware 6 connections, we use the shopIdV2 property from system_config as the connection fingerprint. This ID uniquely identifies every Shopware 6 shop.

Shopware 5

Since Shopware 5 doesn't have a shopId and the SBP identifies shops by domain, we extract esdKey and installationDate from s_core_config_elements, hash them together, and use the resulting hash as the connection fingerprint:

  • esdKey: An automatically generated identifier for Shopware 5 shops, present after initial installation. In Shopware 5, it's used to generate serial numbers for digital products. (Note: Theoretically editable by the shop owner, but this is highly unlikely in practice.)
  • installationDate: The datetime set during the Shopware 5 installation process.

=> we can of course use other fields and hash them if you have a idea for more appropriate ones

@larskemper larskemper self-assigned this Nov 26, 2025
@larskemper larskemper changed the title feat: prevent multiple connections to the same shop feat: prevent multiple connections to the same system Nov 26, 2025
@larskemper larskemper marked this pull request as ready for review November 26, 2025 14:13
@larskemper larskemper marked this pull request as draft December 1, 2025 07:46
@larskemper larskemper marked this pull request as ready for review December 2, 2025 15:01
@larskemper larskemper requested a review from MalteJanz December 2, 2025 15:07
);

if ($hasDuplicate) {
throw MigrationException::duplicateSourceConnection();
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't doing all of this in updateConnectionCredentials only prevent the already created duplicate connection from receiving a fingerprint?

I tested this locally (SW6 → SW6) and creating a duplicate connection currently behaves like this:

  • While entering the details for the second connection, an empty connection is already created in swag_migration_connection

  • After submitting the duplicate details, I do see the new "A connection to the same source system already exists." warning, but the connection is updated nonetheless, and the swag_migration_connection row now contains the credentials, only the fingerprint is missing:

    image
  • After dismissing the modal with "Close", the duplicate connection is not only created, but also active

Image

Copy link
Member Author

@larskemper larskemper Dec 10, 2025

Choose a reason for hiding this comment

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

That's a general migration design issue we didn't refactor until now. I suspect it was done this way because the wizard is url based: each step lives on its "own page", so state isn't shared and nothing gets stored in vuex. That said, this shouldn't prevent existing duplicate connections from receiving a fingerprint, the service only checks for existing fingerprints and exits early when none are present. So the first connection should get a fingerprint and is valid, the second not...

but in this case it seems different, I will look into that, probably need to add a filter for null in the service 👍

Copy link
Member

Choose a reason for hiding this comment

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

What I don't get is what this PR achieves then, because the only difference to me as a user of this is that I see the warning modal, but nothing "prevent[s] multiple connections to the same system" - what am I missing here? 😅

Copy link
Member Author

@larskemper larskemper Dec 10, 2025

Choose a reason for hiding this comment

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

i get what you mean now, it validates newly created connections: "prevent creating multiple connections to the same system". Existing connections do not have a fingerprint, that's true, so their are not validated

Copy link
Member Author

Choose a reason for hiding this comment

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

found the issue: we update the connection first and then did a connection check, so creds where written before checking. I refactored it and now we first check the connection with given creds and then update the entity & generate the fingerprint

Copy link
Member

Choose a reason for hiding this comment

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

Better 👍 but I still think there's something strange about it 🤔


  1. UI briefly shows connection success before the warning:
Kapture.2025-12-10.at.18.16.43.mp4

  1. As a user, I am still left with an empty connection when this happens (now without credentials), which is a confusing state to me. While creating an exact duplicate of my existing one was prevented, it would be nicer if this empty connection would either be cleaned up or not created at all, so I am back to my initial (working) connection when I exit this modal, instead of seeing this:
image

Feel free to move this to follow-up issues due to how all of this works, but I think this feature does not make much sense with the behavior described in 2.

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.

7 participants