Skip to content

Commit fcf2177

Browse files
feat(auth): implement deletion of associated credentials during account deletion
1 parent 707bc49 commit fcf2177

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

pkg/account/api/account.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
v2as "github.com/bucketeer-io/bucketeer/v2/pkg/account/storage/v2"
3434
"github.com/bucketeer-io/bucketeer/v2/pkg/api/api"
3535
domainauditlog "github.com/bucketeer-io/bucketeer/v2/pkg/auditlog/domain"
36+
authstorage "github.com/bucketeer-io/bucketeer/v2/pkg/auth/storage"
3637
domainevent "github.com/bucketeer-io/bucketeer/v2/pkg/domainevent/domain"
3738
"github.com/bucketeer-io/bucketeer/v2/pkg/locale"
3839
"github.com/bucketeer-io/bucketeer/v2/pkg/log"
@@ -979,6 +980,13 @@ func (s *AccountService) DeleteAccountV2(
979980
if err = s.publisher.Publish(ctx, deleteAccountV2Event); err != nil {
980981
return err
981982
}
983+
// Delete associated credentials if they exist
984+
if err = s.credentialsStorage.DeleteCredentials(contextWithTx, account.Email); err != nil {
985+
// Ignore error if credentials don't exist (e.g., SSO-only accounts)
986+
if !errors.Is(err, authstorage.ErrCredentialsUnexpectedAffectedRows) {
987+
return err
988+
}
989+
}
982990
return s.accountStorage.DeleteAccountV2(contextWithTx, account)
983991
})
984992
if err != nil {

pkg/account/api/account_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import (
3333
accstoragemock "github.com/bucketeer-io/bucketeer/v2/pkg/account/storage/v2/mock"
3434
"github.com/bucketeer-io/bucketeer/v2/pkg/api/api"
3535
alstoragemock "github.com/bucketeer-io/bucketeer/v2/pkg/auditlog/storage/v2/mock"
36+
authstorage "github.com/bucketeer-io/bucketeer/v2/pkg/auth/storage"
37+
authstoragemock "github.com/bucketeer-io/bucketeer/v2/pkg/auth/storage/mock"
3638
pkgErr "github.com/bucketeer-io/bucketeer/v2/pkg/error"
3739
"github.com/bucketeer-io/bucketeer/v2/pkg/locale"
3840
publishermock "github.com/bucketeer-io/bucketeer/v2/pkg/pubsub/publisher/mock"
@@ -1720,10 +1722,50 @@ func TestDeleteAccountV2MySQL(t *testing.T) {
17201722
err := fn(ctx, nil)
17211723
require.NoError(t, err)
17221724
}).Return(nil)
1725+
s.publisher.(*publishermock.MockPublisher).EXPECT().Publish(gomock.Any(), gomock.Any()).Return(nil)
1726+
s.credentialsStorage.(*authstoragemock.MockCredentialsStorage).EXPECT().DeleteCredentials(
1727+
gomock.Any(), "bucketeer@example.com",
1728+
).Return(nil)
17231729
s.accountStorage.(*accstoragemock.MockAccountStorage).EXPECT().DeleteAccountV2(
17241730
gomock.Any(), gomock.Any(),
17251731
).Return(nil)
1732+
},
1733+
req: &accountproto.DeleteAccountV2Request{
1734+
Email: "bucketeer@example.com",
1735+
OrganizationId: "org0",
1736+
},
1737+
expectedErr: nil,
1738+
},
1739+
{
1740+
desc: "successWithoutCredentials",
1741+
setup: func(s *AccountService) {
1742+
s.accountStorage.(*accstoragemock.MockAccountStorage).EXPECT().GetAccountV2(
1743+
gomock.Any(), gomock.Any(), gomock.Any(),
1744+
).Return(&domain.AccountV2{
1745+
AccountV2: &accountproto.AccountV2{
1746+
Email: "bucketeer@example.com",
1747+
FirstName: "Test",
1748+
LastName: "User",
1749+
OrganizationId: "org0",
1750+
Language: "en",
1751+
OrganizationRole: accountproto.AccountV2_Role_Organization_ADMIN,
1752+
},
1753+
}, nil).Times(2)
1754+
1755+
s.mysqlClient.(*mysqlmock.MockClient).EXPECT().RunInTransactionV2(
1756+
gomock.Any(), gomock.Any(),
1757+
).Do(func(ctx context.Context, fn func(ctx context.Context, tx mysql.Transaction) error) {
1758+
err := fn(ctx, nil)
1759+
require.NoError(t, err)
1760+
}).Return(nil)
17261761
s.publisher.(*publishermock.MockPublisher).EXPECT().Publish(gomock.Any(), gomock.Any()).Return(nil)
1762+
// Simulate account without credentials (e.g., SSO-only account)
1763+
s.credentialsStorage.(*authstoragemock.MockCredentialsStorage).EXPECT().DeleteCredentials(
1764+
gomock.Any(), "bucketeer@example.com",
1765+
).Return(authstorage.ErrCredentialsUnexpectedAffectedRows)
1766+
s.accountStorage.(*accstoragemock.MockAccountStorage).EXPECT().DeleteAccountV2(
1767+
gomock.Any(), gomock.Any(),
1768+
).Return(nil)
17271769
},
17281770
req: &accountproto.DeleteAccountV2Request{
17291771
Email: "bucketeer@example.com",

0 commit comments

Comments
 (0)