refactor(account): generalize RemoveEmailIdentity to RemoveIdentity(kind)
Generalize the email-erase store op to any identity kind (with the same last-identity guard and, for email, the pending-confirmation cleanup) so the profile Unlink control can reuse it for Telegram/VK. RemoveEmailIdentity stays as a thin wrapper for the admin console.
This commit is contained in:
@@ -21,25 +21,25 @@ var ErrIdentityTaken = errors.New("account: identity already linked to another a
|
||||
// none, making it unreachable after logout. The admin email-erase refuses it.
|
||||
var ErrLastIdentity = errors.New("account: cannot remove the last identity")
|
||||
|
||||
// RemoveEmailIdentity deletes the account's email identity and any pending confirmations
|
||||
// for it, freeing the address for reuse. It refuses when the email is the account's only
|
||||
// identity (ErrLastIdentity) — that would leave the account unreachable — and returns
|
||||
// ErrNotFound when the account has no email identity. It backs the admin console's
|
||||
// "erase email" action.
|
||||
func (s *Store) RemoveEmailIdentity(ctx context.Context, accountID uuid.UUID) error {
|
||||
// RemoveIdentity deletes the account's identity of the given kind (and, for an email,
|
||||
// any pending confirmations for it), freeing it for reuse. It refuses when that is the
|
||||
// account's only identity (ErrLastIdentity) — which would leave the account
|
||||
// unreachable — and returns ErrNotFound when the account has no identity of that kind.
|
||||
// It backs the profile Unlink control and the admin "erase email" action.
|
||||
func (s *Store) RemoveIdentity(ctx context.Context, accountID uuid.UUID, kind string) error {
|
||||
ids, err := s.Identities(ctx, accountID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hasEmail, others := false, 0
|
||||
hasKind, others := false, 0
|
||||
for _, id := range ids {
|
||||
if id.Kind == KindEmail {
|
||||
hasEmail = true
|
||||
if id.Kind == kind {
|
||||
hasKind = true
|
||||
} else {
|
||||
others++
|
||||
}
|
||||
}
|
||||
if !hasEmail {
|
||||
if !hasKind {
|
||||
return ErrNotFound
|
||||
}
|
||||
if others == 0 {
|
||||
@@ -48,21 +48,29 @@ func (s *Store) RemoveEmailIdentity(ctx context.Context, accountID uuid.UUID) er
|
||||
return withTx(ctx, s.db, func(tx *sql.Tx) error {
|
||||
delID := table.Identities.DELETE().WHERE(
|
||||
table.Identities.AccountID.EQ(postgres.UUID(accountID)).
|
||||
AND(table.Identities.Kind.EQ(postgres.String(KindEmail))),
|
||||
AND(table.Identities.Kind.EQ(postgres.String(kind))),
|
||||
)
|
||||
if _, err := delID.ExecContext(ctx, tx); err != nil {
|
||||
return fmt.Errorf("account: delete email identity %s: %w", accountID, err)
|
||||
return fmt.Errorf("account: delete %s identity %s: %w", kind, accountID, err)
|
||||
}
|
||||
delConf := table.EmailConfirmations.DELETE().WHERE(
|
||||
table.EmailConfirmations.AccountID.EQ(postgres.UUID(accountID)),
|
||||
)
|
||||
if _, err := delConf.ExecContext(ctx, tx); err != nil {
|
||||
return fmt.Errorf("account: delete email confirmations %s: %w", accountID, err)
|
||||
if kind == KindEmail {
|
||||
delConf := table.EmailConfirmations.DELETE().WHERE(
|
||||
table.EmailConfirmations.AccountID.EQ(postgres.UUID(accountID)),
|
||||
)
|
||||
if _, err := delConf.ExecContext(ctx, tx); err != nil {
|
||||
return fmt.Errorf("account: delete email confirmations %s: %w", accountID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// RemoveEmailIdentity erases the account's email identity. It backs the admin console's
|
||||
// "erase email" action; the user-facing profile never unlinks email (it is changed).
|
||||
func (s *Store) RemoveEmailIdentity(ctx context.Context, accountID uuid.UUID) error {
|
||||
return s.RemoveIdentity(ctx, accountID, KindEmail)
|
||||
}
|
||||
|
||||
// RequestLinkCode issues and mails a confirm-code for email to accountID,
|
||||
// replacing any prior pending code. Unlike RequestCode it never refuses up front
|
||||
// (taken or already-confirmed): possession of the address is the authorization for
|
||||
|
||||
Reference in New Issue
Block a user