Skip to content

Commit 1bab341

Browse files
authored
fix: disconnect Wise when changing hosts (#11605)
1 parent f58282f commit 1bab341

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

server/models/Collective.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ class Collective extends ModelWithPublicId<
11241124

11251125
await ConnectedAccount.destroy({
11261126
where: {
1127-
service: 'stripe',
1127+
service: [Service.STRIPE, Service.TRANSFERWISE],
11281128
CollectiveId: this.id,
11291129
},
11301130
transaction,
@@ -2726,7 +2726,7 @@ class Collective extends ModelWithPublicId<
27262726
if (this.id === this.HostCollectiveId) {
27272727
await ConnectedAccount.destroy({
27282728
where: {
2729-
service: 'stripe',
2729+
service: [Service.STRIPE, Service.TRANSFERWISE],
27302730
CollectiveId: this.id,
27312731
},
27322732
});

test/server/models/Collective.test.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,78 @@ describe('server/models/Collective', () => {
573573
expect(pendingCollective.HostCollectiveId).to.be.null;
574574
});
575575

576+
it('deletes Stripe and Transferwise connected accounts when deactivateMoneyManagement is called', async () => {
577+
const host = await fakeHost({
578+
name: 'Host with connected accounts',
579+
slug: randStr('host-ca-'),
580+
currency: 'USD',
581+
CreatedByUserId: user1.id,
582+
hasHosting: false,
583+
hasMoneyManagement: true,
584+
});
585+
586+
const stripeAccount = await fakeConnectedAccount({ CollectiveId: host.id, service: 'stripe' });
587+
const transferwiseAccount = await fakeConnectedAccount({ CollectiveId: host.id, service: 'transferwise' });
588+
const otherAccount = await fakeConnectedAccount({ CollectiveId: host.id, service: 'github' });
589+
590+
await host.deactivateMoneyManagement();
591+
592+
const remainingAccounts = await models.ConnectedAccount.findAll({
593+
where: { CollectiveId: host.id },
594+
});
595+
596+
const remainingServices = remainingAccounts.map(a => a.service);
597+
expect(remainingServices).to.not.include('stripe');
598+
expect(remainingServices).to.not.include('transferwise');
599+
expect(remainingServices).to.include('github');
600+
601+
// Verify the specific records were destroyed
602+
const deletedStripe = await models.ConnectedAccount.findByPk(stripeAccount.id);
603+
const deletedTransferwise = await models.ConnectedAccount.findByPk(transferwiseAccount.id);
604+
const keptOther = await models.ConnectedAccount.findByPk(otherAccount.id);
605+
expect(deletedStripe).to.be.null;
606+
expect(deletedTransferwise).to.be.null;
607+
expect(keptOther).to.not.be.null;
608+
});
609+
610+
it('deletes Stripe and Transferwise connected accounts when a self-hosted collective changes host', async () => {
611+
const selfHostedCollective = await fakeActiveHost({
612+
name: 'Self Hosted',
613+
slug: randStr('self-hosted-'),
614+
currency: 'USD',
615+
CreatedByUserId: user1.id,
616+
});
617+
// Ensure it is truly self-hosted
618+
expect(selfHostedCollective.id).to.equal(selfHostedCollective.HostCollectiveId);
619+
620+
const stripeAccount = await fakeConnectedAccount({ CollectiveId: selfHostedCollective.id, service: 'stripe' });
621+
const transferwiseAccount = await fakeConnectedAccount({
622+
CollectiveId: selfHostedCollective.id,
623+
service: 'transferwise',
624+
});
625+
const githubAccount = await fakeConnectedAccount({ CollectiveId: selfHostedCollective.id, service: 'github' });
626+
627+
// Remove host (changeHost with null)
628+
await selfHostedCollective.changeHost(null, user1);
629+
630+
const remainingAccounts = await models.ConnectedAccount.findAll({
631+
where: { CollectiveId: selfHostedCollective.id },
632+
});
633+
634+
const remainingServices = remainingAccounts.map(a => a.service);
635+
expect(remainingServices).to.not.include('stripe');
636+
expect(remainingServices).to.not.include('transferwise');
637+
expect(remainingServices).to.include('github');
638+
639+
// Verify the specific records were destroyed
640+
const deletedStripe = await models.ConnectedAccount.findByPk(stripeAccount.id);
641+
const deletedTransferwise = await models.ConnectedAccount.findByPk(transferwiseAccount.id);
642+
const keptGithub = await models.ConnectedAccount.findByPk(githubAccount.id);
643+
expect(deletedStripe).to.be.null;
644+
expect(deletedTransferwise).to.be.null;
645+
expect(keptGithub).to.not.be.null;
646+
});
647+
576648
it('changes host successfully and sends email notification to host', async () => {
577649
const assertCollectiveCurrency = async (collective, currency) => {
578650
const tiers = await models.Tier.findAll({

0 commit comments

Comments
 (0)