GDPR script get_user_data.rb doesn't include some changes from the Devise upgrade


When the sign-in system was moved to Devise, there were five fields added to the users table that are updated whenever the user signs in:

  • sign_in_count

  • current_sign_in_at

  • last_sign_in_at

  • current_sign_in_ip

  • last_sign_in_ip

The IP addresses recorded in the audits table whenever one of those five values is updated (as well as the IPs in two of those fields) are not included in the script used to export the user's data.

There are a few more changes resulting from the Devise upgrade that aren't accounted for in the script/get_user_data.rb script:

  1. The field failed_login_count was renamed to failed_attempts. (But it may not be necessary to check failed_attempts, because Devise almost exclusively uses increment_counter to change failed_attempts, which doesn't call the before_update hook that the audited gem uses. Still, it might be good to double-check what gets added to the audits table when a failed login attempt occurs, when an account is locked, and when it's unlocked.)

  2. The field recently_reset is no longer used. Instead, Devise changes reset_password_token, reset_password_sent_at, and encrypted_password over the course of a password reset. (It may be necessary to leave in the code relating to recently_reset to account for older entries in the audits table, but I believe there needs to be new code for the new Devise fields regardless.)

The Devise upgrade also renamed various fields related to account activation (which is another activity that probably has the user's IP address associated with it).

After reviewing the above information, here are the changes needed:

  • Add encrypted_password case to handle IPs recorded when someone changes their password.

  • Add failed_attempts case to handle recorded IPs from failed login attempts, which are currently only logged in certain cases due to the way Devise updates the count of failed attempts.

  • Add locked_at case to handle recorded IPs from the last failed login attempt before an account is locked due to too many login attempts.

  • Clarify that the recently_reset case is from before the Devise change, and add a reset_password_sent_at case to handle IPs recorded for password reset requests now that we're using Devise.

  • Add sign_in_count case to handle IPs recorded when someone successfully signs in to an account.

Ideally, to test this, someone would do each of the following with different IP addresses, and then we’d ensure each of those IP address appeared when a database admin ran the script:

  • log in and change their account password

  • log out and request a password reset

  • attempt to log in to their account so many times they get locked out (50 tries, quickly)

  • wait five minutes after being locked out and then log in successfully

Failing that, we should make sure the script works.


February 4, 2020, 4:33 PM


For the GDPR script thing, logging the IP when sign_in_count is in audited_changes should cover all the new fields, I think? They're all logged as one item, e.g.

and we'll already have the current/last IPs from the current/previous sign_in_count update

February 9, 2020, 4:44 PM

Testing with different IP addresses doesn't work on staging. I think recent audits recorded private IPs.

The script works, this should be fine.

February 9, 2020, 4:52 PM

Oooh, you’re right, we found that out with the whole “only one guest kudos can be left on a given work” issue. Whee. We can try the relevant bits individually on production if we really want to be sure they work.






ticking instant





Affects versions

Fix versions





Required Access Level



Internal 0.9