Add a constraint to ensure application_settings.rate_limits is a hash
What does this MR do and why?
Add a constraint to ensure application_settings.rate_limits is a hash
In f89cc164, we introduced a JSONB
column rate_limits
to store the application rate limits. We want to
ensure that we always store a hash in this column otherwise, the rails
application will break. This can happen if a bad update query is
executed like in the following case if we redefine the
application_settings class:
class MyMigration
class TmpSetting < ApplicationRecord
self.table_name = :application_settings
end
def up
TmpSetting.update(rate_limits: [1])
end
end
MR acceptance checklist
Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Migration output
up
bin/rails db:migrate
main: == [advisory_lock_connection] object_id: 183100, pg_backend_pid: 45389
main: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: migrating =
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute("ALTER TABLE application_settings\nADD CONSTRAINT check_application_settings_rate_limits_is_hash\nCHECK ( (jsonb_typeof(rate_limits) = 'object') )\nNOT VALID;\n")
main: -> 0.0036s
main: -- execute("SET statement_timeout TO 0")
main: -> 0.0002s
main: -- execute("ALTER TABLE application_settings VALIDATE CONSTRAINT check_application_settings_rate_limits_is_hash;")
main: -> 0.0006s
main: -- execute("RESET statement_timeout")
main: -> 0.0002s
main: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: migrated (0.0264s)
main: == [advisory_lock_connection] object_id: 183100, pg_backend_pid: 45389
ci: == [advisory_lock_connection] object_id: 183340, pg_backend_pid: 45391
ci: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: migrating =
ci: -- transaction_open?(nil)
ci: -> 0.0000s
ci: -- transaction_open?(nil)
ci: -> 0.0000s
ci: -- execute("ALTER TABLE application_settings\nADD CONSTRAINT check_application_settings_rate_limits_is_hash\nCHECK ( (jsonb_typeof(rate_limits) = 'object') )\nNOT VALID;\n")
ci: -> 0.0036s
ci: -- execute("SET statement_timeout TO 0")
ci: -> 0.0002s
ci: -- execute("ALTER TABLE application_settings VALIDATE CONSTRAINT check_application_settings_rate_limits_is_hash;")
ci: -> 0.0011s
ci: -- execute("RESET statement_timeout")
ci: -> 0.0002s
ci: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: migrated (0.0213s)
ci: == [advisory_lock_connection] object_id: 183340, pg_backend_pid: 45391
down
VERSION=20240115115029 bin/rails db:rollback:main && bin/rails db:rollback:ci
main: == [advisory_lock_connection] object_id: 182700, pg_backend_pid: 52189
main: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: reverting =
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- transaction_open?(nil)
main: -> 0.0000s
main: -- execute(" ALTER TABLE application_settings\n DROP CONSTRAINT IF EXISTS check_application_settings_rate_limits_is_hash\n")
main: -> 0.0017s
main: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: reverted (0.0140s)
main: == [advisory_lock_connection] object_id: 182700, pg_backend_pid: 52189
ci: == [advisory_lock_connection] object_id: 182640, pg_backend_pid: 52597
ci: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: reverting =
ci: -- transaction_open?(nil)
ci: -> 0.0000s
ci: -- transaction_open?(nil)
ci: -> 0.0000s
ci: -- execute(" ALTER TABLE application_settings\n DROP CONSTRAINT IF EXISTS check_application_settings_rate_limits_is_hash\n")
ci: -> 0.0015s
ci: == 20240115115029 AddRateLimitsHashConstraintToApplicationSettings: reverted (0.0237s)
ci: == [advisory_lock_connection] object_id: 182640, pg_backend_pid: 52597
How to set up and validate locally
Update the rate_limits
column using the below queries on the master branch and all of them will succeed. On this branch, only {}
will be allowed.
update application_settings set rate_limits = '"a"';
update application_settings set rate_limits = '1';
update application_settings set rate_limits = '[]';
update application_settings set rate_limits = '{}';
select jsonb_typeof(rate_limits) from application_settings;
Related to #420321 (closed)
Edited by Abdul Wadood