кнопка удаления, которая ничего не удаляет

7 сентября 2026 г. gdprgoprivacy

У блога теперь есть учётные записи пользователей, а значит есть и пользовательские данные, а значит закон ЕС и моя собственная совесть сходятся в одном: людям нужны две кнопки. Одна, чтобы скачать всё, что у меня есть о них, и вторая, чтобы всё это исчезло. Это история о том, как я сделал обе, и о том, почему кнопка удаления на самом деле ничего не удаляет.

Кнопка скачивания была лёгкой половиной. Один эндпоинт собирает всё, что привязано к твоему аккаунту, из обоих сервисов (данные аккаунта из auth, твои комментарии, лайки и жалобы из blog), и отдаёт это одним JSON файлом. Готово, так я думал. Код-ревью показало, что я спрятал его за логином, но забыл про лимитер, так что любой с аккаунтом мог долбить довольно дорогой эндпоинт. После одной обёртки миддлвером это стало действительно готово.

Кнопка удаления оказалась интереснее. Первым делом хотелось сделать очевидное: удалить аккаунт, удалить комментарии, и всё. Но это ломает переписки. Если ты написал комментарий, и три человека на него ответили, удаление твоего комментария оставляет их ответы висеть в воздухе, отвечающими никому. Ветка обсуждения перестаёт иметь смысл для всех, кроме тебя.

Вкладка данных в настройках профиля, с кнопками скачивания и удаления

Поэтому вместо этого блог при первом запуске создаёт общий аккаунт anonymous, и удаление твоего аккаунта передаёт всё написанное ему. Твоё имя пропадает, слова остаются. Ветка комментариев всё ещё читается нормально, просто там, где раньше было твоё имя пользователя, теперь написано anonymous:

-- name: AnonymizeComments :execrows
-- Reattributes a deleted user's comments to the shared anonymous account.
UPDATE comments
SET author_id = sqlc.arg(anonymous_id)::uuid, author_username = 'anonymous'
WHERE author_id = sqlc.arg(user_id)::uuid;

Эта часть сработала с первого раза. С лайками так не вышло. Лайк это строка, говорящая «этот пользователь лайкнул этот комментарий», и такая пара должна быть уникальной. Если ты лайкнул комментарий, который раньше лайкнул какой-то уже удалённый пользователь, оба лайка теперь хотят стать «anonymous лайкнул этот комментарий», и база данных справедливо отказывается от дубликата. Решение: сначала удалить конфликтующие лайки (счётчик на комментарии остаётся честным, anonymous уже его лайкнул), а потом перепривязать остальные.

Порядок тоже имел значение. Сервис blog сначала анонимизирует, а сервис auth уже потом удаляет аккаунт. Если всё упадёт посередине, ты остаёшься пользователем, чей контент уже анонимизирован, а это безопасное состояние, которое можно просто повторить. Обратный порядок мог бы удалить твой аккаунт и оставить комментарии осиротевшими под id пользователя, которого больше не существует.

В конце добавил две защиты: аккаунт anonymous не может удалить сам себя (это была бы забавная ошибка), и последний админ тоже не может удалить себя, потому что блог, в который никто не может зайти через админку, это очень тихий блог.

Я протестировал всё это на одноразовом аккаунте: зарегистрировался, написал комментарий, скачал свои данные, нажал удалить. Комментарий всё ещё там, подписан как anonymous, а вход перестал работать. Именно то, что обещает кнопка, даже если это не совсем то, что она пишет.

0 комментариев

Войдите , чтобы оставить комментарий.

Войти

Забыли пароль?

Нет аккаунта?