Есть ли способ массово изменить имена пользователей (примечание: не имена учётных записей)

На нашем форуме есть несколько сотен пользователей, чьи имена (не имена пользователей, а именно имена) по ошибке были установлены как их адрес электронной почты из-за того, как был настроен внешний провайдер SSO (через WordPress) при создании их учетных записей.

Есть ли относительно простой способ массово изменить эти имена с the_name@example.com на the_name (то есть обрезать всё, начиная с символа ‘@’), не заходя вручную в каждый профиль и не меняя их по одному?

Это можно сделать через консоль Rails. Это сложнее, чем можно объяснить здесь, особенно потому что адреса электронной почты больше не хранятся в записи пользователя. Если у вас есть бюджет, вы можете написать в канал Marketplace или связаться со мной напрямую.

Или, если вам не важен сам адрес электронной почты…

Что-то вроде

users = User.where('username like', '%@%')

Затем вы пройдете по списку и используете gsub, чтобы удалить всё от символа @ до конца. Это лучшее, что я могу сделать с телефона.

Спасибо за ответ, @pfaffman. Я могу написать SQL-запрос, но работа в консоли Rails — это немного не моя сфера. Как попасть в консоль Python Discourse? :blush:

Было бы здорово — хотя я понимаю, что это потенциально опасно, — если бы существовал инструмент, похожий на Data Explorer, который также позволял бы выполнять запросы UPDATE.

Кто-нибудь знает, можно ли подключить сторонний SQL-инструмент (например, Sequel Pro или аналогичный) к работающей базе данных в самохостинговом Docker-контейнере Discourse?

Да, но выполнение этого в Rails значительно снижает риск повреждения базы данных. Например, если вы используете Rails, вы будете уверены, что не создадите недопустимые имена пользователей (а если при изменении одной таблицы нужно обновить другую, Rails сделает это автоматически, а SQL — нет).

cd /var/discourse
./launcher enter app
rails c

Теперь вы в Rails.

users = User.where("username like '%@%'")
users.each do |user|
  user.name.gsub!(/@(.*)/, "")
  puts "Новое имя: #{user.name}"
  # user.save
end

Думаю, это решит вашу задачу. Если всё выглядит правильно, можете раскомментировать user.save и попробовать.

Сначала сделайте резервную копию, хорошо? (Или, что ещё лучше, выполните это на тестовом сервере.)

Ого, спасибо за код!

У меня нет тестового сервера для этого экземпляра Discourse, но я могу сделать резервную копию, а затем запустить код очень рано завтра утром, когда, скорее всего, не будет (или будет совсем немного) трафика, чтобы я мог сразу восстановить систему в случае возникновения проблемы.

Огромное спасибо, @pfaffman.

Всё должно быть в порядке, если puts выглядят нормально. Удачи!

Обрезка текста после символа @ всё ещё оставляет личную информацию (адрес электронной почты) в значительной степени видимой для «Большого Злого Интернета» (учитывая, что у большинства людей домен @gmail.com или несколько других крупных провайдеров). Вероятно, вам будет лучше установить их в одно и то же значение, что и имя пользователя.

Спасибо, @lionel-rowe, это верное замечание. Однако имена пользователей уже содержат это же значение (имя пользователя создавалось путём взятия всего, что находится до символа ‘@’, из адреса электронной почты пользователя).

Ужас.

Мне пришлось внести небольшое изменение в код и добавить небольшую процедуру, чтобы всё заработало. Вот изменённый код:

users = User.where("name like '%@%'")

Затем консоль Rails начала выводить данные о пользователях через утилиту more, поэтому мне пришлось нажать q, чтобы выйти. Затем:

users.each do |user|
  user.name.gsub!(/@(.*)/,"")
  puts "Новое имя: #{user.name}"
  # user.save
end

После этого консоль Rails показала список новых имён (правильно!), а затем снова вывела список пользователей через more. Снова q.

Затем:

users.each do |user|
  user.name.gsub!(/@(.*)/,"")
  puts "Новое имя: #{user.name}"
  user.save
end

…и больше нет имён пользователей в виде адресов электронной почты, и на фронтенде форума всё выглядит отлично.

Ещё раз спасибо @pfaffman за вашу щедрую помощь.