Skip to content

fix: respect keepUserData on app uninstall#64

Open
Ghaith (Gaitholabi) wants to merge 2 commits into
mainfrom
feat/respect-keep-user-data
Open

fix: respect keepUserData on app uninstall#64
Ghaith (Gaitholabi) wants to merge 2 commits into
mainfrom
feat/respect-keep-user-data

Conversation

@Gaitholabi

Copy link
Copy Markdown
Contributor

Why

Shopware's AppDeletedEvent carries a keepUserData flag in the app.deleted webhook payload (['keepUserData' => bool]). When a merchant uninstalls an app and opts to keep its data, Shopware retains the app data on its side — but the SDK ignored the flag and unconditionally deleted the shop from the repository, dropping the credentials a later re-install would restore from.

What

AppLifecycle::delete() now reads data.payload.keepUserData from the webhook body (defaulting to false) and:

  • keeps the shop in the repository when true, deletes it otherwise;
  • forwards the flag to BeforeShopDeletionEvent and ShopDeletedEvent through a new keepUserData() accessor (mirrors AppDeletedEvent::keepUserData() in core);
  • records it on the structured Shop uninstalled log line.

Keeping the record is safe for re-install: RegistrationService::register() already handles an existing shop via its updateShop branch.

This is the SDK-side mirror of shopware/shopware#17466, which makes Shopware retain the app secret iff keepUserData — keeping both sides symmetric (retain credentials exactly when the data is kept).

Compatibility

Additive only — an optional bool $keepUserData = false constructor argument plus one method on each of the two deletion events. Existing new ShopDeletedEvent($request, $shop) callers are unaffected.

Tests

Full phpunit suite green; phpstan and php-cs-fixer clean. Adds testUninstallKeepsShopWhenKeepUserDataIsTrue and testUninstallDeletesShopWhenKeepUserDataIsFalse, and updates the existing uninstall-log assertion.

Note: this is the first of a series. A follow-up addresses the secret-desync re-registration deadlock (SDK previous-secret tolerance on re-registration); tracked separately.

🤖 Generated with Claude Code

Shopware's app.deleted webhook carries a keepUserData flag. Honor it: keep the shop in the repository when true and delete it otherwise, forward the flag to BeforeShopDeletionEvent/ShopDeletedEvent via a keepUserData() accessor, and record it on the uninstall log line. Mirrors shopware/shopware#17466 (retain the app secret iff keepUserData).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Gaitholabi Ghaith (Gaitholabi) changed the title feat: respect keepUserData on app uninstall fix: respect keepUserData on app uninstall Jun 16, 2026

Copilot AI left a comment

Copy link
Copy Markdown

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 updates the SDK’s app.deleted lifecycle handling to respect Shopware’s keepUserData uninstall flag, preserving the shop record (and thus credentials) when merchants choose to keep app data for a future re-install.

Changes:

  • Parse data.payload.keepUserData from the app.deleted webhook body and conditionally skip shop deletion when true.
  • Extend BeforeShopDeletionEvent and ShopDeletedEvent with a keepUserData() accessor (and constructor argument) to propagate the flag to listeners.
  • Add/adjust PHPUnit coverage for both keep/delete paths and include the flag in the structured uninstall log context.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/AppLifecycle.php Reads keepUserData from webhook payload, conditionally deletes the shop, forwards the flag to events, and logs it.
src/Event/BeforeShopDeletionEvent.php Adds keepUserData state + accessor to the “before deletion” lifecycle event.
src/Event/ShopDeletedEvent.php Adds keepUserData state + accessor to the “deleted” lifecycle event.
tests/AppLifecycleTest.php Adds tests for keeping vs deleting based on the flag and updates uninstall logging expectations.

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

Comment thread src/AppLifecycle.php
Comment on lines +103 to +109
private function shouldKeepUserData(RequestInterface $request): bool
{
$body = \json_decode($request->getBody()->getContents(), true);
$request->getBody()->rewind();

return \is_array($body) && ($body['data']['payload']['keepUserData'] ?? false) === true;
}
shouldKeepUserData() decoded without JSON_THROW_ON_ERROR, so an invalid/empty payload became null, fell through to keepUserData=false, and deleted the shop. A JSON parse failure means the webhook body is corrupt: decode with JSON_THROW_ON_ERROR and rethrow as MalformedWebhookBodyException (the SDK's malformed-webhook error, as used throughout ContextResolver) instead of dropping the shop. A valid payload missing the key still defaults to false.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Gaitholabi Ghaith (Gaitholabi) force-pushed the feat/respect-keep-user-data branch from f40ff1d to 50b9a22 Compare June 16, 2026 08:28
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.

3 participants