Change staff email address from console

We recently introduced a security change: When a staff user changes their email address, for enhanced security they must confirm both new email address AND old email address.

However, this creates a problem when a staff member loses access to their old email address and wants to update their email address.

In this guide we’ll change the email address of a user (not necessarily staff) via console without the need to access old email address. Let’s get started!

:information_source:These commands can also be used to force a change in a user’s email address and override the need for them to confirm by clicking on the validation email

Access Console

Connect to your Droplet via SSH, or use Putty on Windows:

ssh root@192.168.1.1

Replace 192.168.1.1 with the IP address of your Droplet.

Switch to your Discourse folder:

cd /var/discourse

Enter the container:

./launcher enter app
# or
./launcher ssh app

Access Rails Console:

rails c

Change Email Address

To personalise these for your user, input your stuff here:

Run these commands (each on a separate line)

u = User.find_by_username("=USERNAME=")
u.email = "=EMAIL="
u.email_tokens.create(email: u.email)
u.activate
u.save!

That’s it, your email address is updated, and you should be able to login with your new email.

24 Likes

Thanks a lot for help

Guys does it still work in Discourse instace from March 2019?

It should. Do you have reason to believe otherwise?

It works! I’ve just ask before checking (mea culpa) thinking that maybe from security reasons it was turned off or database schema has been change or something.

2 Likes

This no longer will work due to Discourse changes.

NoMethodError: undefined method `email=' for #<User::ActiveRecord_Relation:0x000055f706dc8fb8>

This is untested (I’m solving a different related problem) but I think something like this might point in the right direction:

u = User.find_by_username("YOUR_USERNAME")
UserEmail.where(user_id: u.id).each() do |e|
    e.email = "YOUR_NEW_EMAIL_ADDRESS"
    u.email_tokens.create(email: e.email)
    e.save!
end
u.activate
u.save!

I welcome correction.

2 Likes

When using the rails commands in the OP, I get this error instead when I u.activate:

ActiveRecord::RecordInvalid: Validation failed: Primary email has already been taken
from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.3.2/lib/active_record/validations.rb:80:in `raise_validation_error’

However, it still works. And I need to do that step for it to work. u.save! seems unnecessary.

@techAPJ - would you consider making the OP a wiki?

This is the change I'd make

To personalise this code for your user, input your stuff here:

u = User.find_by_username("=USERNAME=")
u.email = "=EMAIL="
u.email_tokens.create(email: u.email)
u.activate
u.save!
3 Likes

The OP is a wiki now!

4 Likes