59 lines
1.4 KiB
Ruby
59 lines
1.4 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
class AddHashedApiKey < ActiveRecord::Migration[6.0]
|
||
|
def up
|
||
|
add_column(:api_keys, :key_hash, :string)
|
||
|
add_column(:api_keys, :truncated_key, :string)
|
||
|
|
||
|
execute(
|
||
|
<<~SQL
|
||
|
UPDATE api_keys
|
||
|
SET truncated_key = LEFT(key, 4)
|
||
|
SQL
|
||
|
)
|
||
|
|
||
|
batch_size = 500
|
||
|
begin
|
||
|
batch = DB.query <<-SQL
|
||
|
SELECT id, key
|
||
|
FROM api_keys
|
||
|
WHERE key_hash IS NULL
|
||
|
LIMIT #{batch_size}
|
||
|
SQL
|
||
|
|
||
|
to_update = []
|
||
|
for row in batch
|
||
|
hashed = Digest::SHA256.hexdigest row.key
|
||
|
to_update << { id: row.id, key_hash: hashed }
|
||
|
end
|
||
|
|
||
|
if to_update.size > 0
|
||
|
data_string = to_update.map { |r| "(#{r[:id]}, '#{r[:key_hash]}')" }.join(",")
|
||
|
|
||
|
DB.exec <<~SQL
|
||
|
UPDATE api_keys
|
||
|
SET key_hash = data.key_hash
|
||
|
FROM (values
|
||
|
#{data_string}
|
||
|
) as data(id, key_hash)
|
||
|
WHERE api_keys.id = data.id
|
||
|
SQL
|
||
|
end
|
||
|
end until batch.length < batch_size
|
||
|
|
||
|
change_column_null :api_keys, :key_hash, false
|
||
|
change_column_null :api_keys, :truncated_key, false
|
||
|
|
||
|
add_index :api_keys, :key_hash
|
||
|
|
||
|
# The key column will be dropped in a post_deploy migration
|
||
|
# But allow it to be null in the meantime
|
||
|
Migration::SafeMigrate.disable!
|
||
|
change_column_null :api_keys, :key, true
|
||
|
Migration::SafeMigrate.enable!
|
||
|
end
|
||
|
|
||
|
def down
|
||
|
raise ActiveRecord::IrreversibleMigration
|
||
|
end
|
||
|
end
|