Files
nairobi/db/migrate/20200602233844_create_shared_extensions_schema.rb
Javi Martín 96a0aa2a88 Add and apply LineContinuationSpacing rubocop rule
So now we're consistent when separating multiline strings.
2023-08-18 14:56:17 +02:00

138 lines
4.0 KiB
Ruby

class CreateSharedExtensionsSchema < ActiveRecord::Migration[6.0]
def up
unless schema_exists?(extensions_schema)
execute_or_log_create_schema_warning("CREATE SCHEMA #{extensions_schema}")
end
%w[unaccent pg_trgm].each do |extension|
if extension_enabled?(extension)
unless extension_already_in_extensions_schema?(extension)
execute_or_log_extension_warning("ALTER EXTENSION #{extension} SET SCHEMA #{extensions_schema}")
end
else
execute_or_log_extension_warning("CREATE EXTENSION #{extension} SCHEMA #{extensions_schema}")
end
end
unless schema_exists?(extensions_schema) && public_has_usage_privilege_on_extensions_schema?
execute_or_log_grant_usage_warning("GRANT usage ON SCHEMA #{extensions_schema} TO public")
end
show_full_warning_message if warning_messages.any?
end
def down
%w[unaccent pg_trgm].each do |extension|
unless extension_already_in_public_schema?(extension)
execute "ALTER EXTENSION #{extension} SET SCHEMA public;"
end
end
execute "DROP SCHEMA #{extensions_schema};" if schema_exists?(extensions_schema)
end
private
def extensions_schema
"shared_extensions"
end
def extension_already_in_extensions_schema?(extension)
associated_schema_id_for(extension) == extensions_schema_id
end
def extension_already_in_public_schema?(extension)
associated_schema_id_for(extension) == public_schema_id
end
def associated_schema_id_for(extension)
query_value("SELECT extnamespace FROM pg_extension WHERE extname=#{quote(extension)}")
end
def extensions_schema_id
schema_id_for(extensions_schema)
end
def public_schema_id
schema_id_for("public")
end
def schema_id_for(schema)
query_value("SELECT oid FROM pg_namespace WHERE nspname=#{quote(schema)}")
end
def execute_or_log_create_schema_warning(statement)
if create_permission?
execute statement
else
log_warning(
"GRANT CREATE ON DATABASE #{query_value("SELECT CURRENT_DATABASE()")} " \
"TO #{query_value("SELECT CURRENT_USER")}"
)
log_warning(statement)
end
end
def execute_or_log_extension_warning(statement)
if superuser?
execute statement
else
log_warning(statement)
end
end
def execute_or_log_grant_usage_warning(statement)
if schema_exists?(extensions_schema) && grant_usage_permission?
execute statement
else
log_warning(statement)
end
end
def create_permission?
query_value("SELECT has_database_privilege(CURRENT_USER, CURRENT_DATABASE(), 'CREATE');")
end
def superuser?
query_value("SELECT usesuper FROM pg_user WHERE usename = CURRENT_USER")
end
def grant_usage_permission?
query_value("SELECT has_schema_privilege(CURRENT_USER, '#{extensions_schema}', 'CREATE');")
end
def public_has_usage_privilege_on_extensions_schema?
query_value("SELECT has_schema_privilege('public', '#{extensions_schema}', 'USAGE');")
end
def log_warning(statement)
warning_messages.push(statement)
end
def warning_messages
@warning_messages ||= []
end
def show_full_warning_message
message = <<~WARNING
---------------------- Multitenancy Warning ----------------------
Multitenancy is a feature that allows managing multiple
institutions in a completely independent way using just one
CONSUL DEMOCRACY installation.
NOTE: If you aren't going to use multitenancy, you can safely
ignore this warning.
If you'd like to enable this feature, first run:
#{warning_messages.join(";\n ")};
using a user with enough database privileges.
Check the CONSUL DEMOCRACY release notes for more information.
------------------------------------------------------------------
WARNING
puts message
Rails.logger.warn(message)
end
end