Occasionally, things go wrong with software. When things go wrong, one of the worst things that can happen is that the system leaves some data in an inconsistent or invalid state. Of course we try to reduce these cases, but they do happen.
When they happen, we often must take corrective action in the form of some data cleanup. (In addition to hardening the code that allowed the inconsistency.) Some of the techniques I've seen for that cleanup include
rails console
to edit the production data through codeThe script and migration versions have a couple of advantages over the direct-access versions:
Unfortunately, if checked in, these scripts also have a significant security disadvantage: they leak PII or other sensitive data from the database into source control. For example,
# 2013-07-05: delete all of Susan Yee's OAuth tokens because she's locked out
User.find_by_email('[email protected]').oauth_tokens.delete_all!
I can think of a couple solutions to this risk:
Does anyone have a proven technique?
I'll start by saying that the corrective actions I had to do during my work have never been so frequent or complex to require the writing of dedicated scripts; so I've always stopped to the points 1. and 2. that you said (editing database directly or using rails console
).
Anyway, here are a couple of solutions that come to mind:
Make the script general, so it covers the case you want to fix without specifying "ad personam" data. In this case, your example (I report it here for completeness):
# Delete all of Susan Yee's OAuth tokens because she's locked out
User.find_by_email('[email protected]').oauth_tokens.delete_all!
becomes something like:
# Delete locked out people OAuth tokens
User.locked_out.each{ |u| u.oauth_tokens.delete_all! }
The advantages are that the script is based on a logic and covers general cases; the (big) disadvantage is that not always you have a state that you can use to find the data you want to edit, and for these cases (the "ad personam" cases) this solution is not applicable.
Pass sensible data via arguments / environment variables / git-ignored files
This is what I use when I have to store per-app informations, like f.e. the Rails secret key: I put it into a file config/.secret_key
, something like this) which is git-ignored, and I put the app secret key there.
But the git-ignored file is for persistent data; since you're dealing with one-off scripts I think arguments are a good solution:
# Delete all OAuth tokens of the specified user
User.find_by_email(ARGV[0]).oauth_tokens.delete_all!
and then run history -c
so you're safe even if someone manages to leak your history (although you probably have bigger problems in that case :P )
This solution doesn't suite well if you have also to store the informations of the edits you did; but I don't think this is your case, and anyway the log files should contain the informations about what you did. If you have this need probably is better using some database versioning logic (here some resources about this, if you are interested about it)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With