lib/flydata/compatibility_check.rb in flydata-0.3.18 vs lib/flydata/compatibility_check.rb in flydata-0.3.19
- old
+ new
@@ -98,30 +98,47 @@
end
raise "Please correct these errors if you wish to run FlyData Sync"
end
def check_mysql_user_compat
- client = Mysql2::Client.new(@db_opts)
+ databases = ['mysql', @db_opts[:database]]
+ get_grant_regex = /GRANT (?<privs>.*) ON (`)?(?<db_name>[^`]*)(`)?\.\* TO '#{@db_opts[:username]}/
+ necessary_permission_fields = ["SELECT","RELOAD","LOCK TABLES","REPLICATION SLAVE","REPLICATION CLIENT"]
+ all_privileges_field = ["ALL PRIVILEGES"]
+
+ # Do not catch MySQL connection problem because check should stop if no MySQL connection can be made.
grants_sql = "SHOW GRANTS"
- correct_db = ["ON (\\*|(`)?#{@db_opts[:database]}(`)?).","TO '#{@db_opts[:username]}"]
- necessary_permission_fields= ["SELECT","RELOAD","LOCK TABLES","REPLICATION SLAVE","REPLICATION CLIENT"]
- all_privileges_field= ["ALL PRIVILEGES"]
+ client = Mysql2::Client.new(@db_opts)
result = client.query(grants_sql)
- # Do not catch MySQL connection problem because check should stop if no MySQL connection can be made.
client.close
- found_priv = []
+
+ found_priv = Hash[databases.map {|d| [d,[]]}]
+ missing_priv = {}
+
result.each do |res|
# SHOW GRANTS should only return one column
res_value = res.values.first
- if correct_db.all? {|perm| res_value.match(perm)}
- necessary_permission_fields.each do |priv|
- found_priv << priv if res_value.match(priv)
+ matched_values = res_value.match(get_grant_regex)
+ next unless matched_values
+ line_priv = matched_values["privs"].split(", ")
+ if matched_values["db_name"] == "*"
+ return true if (all_privileges_field - line_priv).empty?
+ databases.each {|d| found_priv[d] << line_priv }
+ elsif databases.include? matched_values["db_name"]
+ if (all_privileges_field - line_priv).empty?
+ found_priv[matched_values["db_name"]] = necessary_permission_fields
+ else
+ found_priv[matched_values["db_name"]] << line_priv
end
- return true if (necessary_permission_fields-found_priv).empty? or all_privileges_field.all? {|d| res_value.match(d)}
end
+ missing_priv = get_missing_privileges(found_priv, necessary_permission_fields)
+ return true if missing_priv.empty?
end
- raise MysqlCompatibilityError, "The user '#{@db_opts[:username]}' does not have the correct permissions to run FlyData Sync\n * These privileges are missing: #{(necessary_permission_fields-found_priv).join(", ")}"
+ error_text = "The user '#{@db_opts[:username]}' does not have the correct permissions to run FlyData Sync\n"
+ error_text << " * These privileges are missing...\n"
+ missing_priv.each_key {|db| error_text << " for the database '#{db}': #{missing_priv[db].join(", ")}\n"}
+ raise MysqlCompatibilityError, error_text
end
def check_mysql_protocol_tcp_compat
query = Mysql::MysqlUtil.generate_mysql_show_grants_cmd(@db_opts)
@@ -217,9 +234,18 @@
end
raise MysqlCompatibilityError, "FlyData does not support VIEW and MEMORY ENGINE table. Remove following tables from data entry: #{invalid_tables.join(", ")}" unless invalid_tables.empty?
ensure
client.close
end
+ end
+
+ def get_missing_privileges(found_priv, all_priv)
+ return_hash = {}
+ found_priv.each_key do |key|
+ missing_priv = all_priv - found_priv[key].flatten.uniq
+ return_hash[key] = missing_priv unless missing_priv.empty?
+ end
+ return_hash
end
def run_mysql_retention_check(mysql_client)
expire_logs_days_limit = BINLOG_RETENTION_HOURS / 24
sel_query = SELECT_QUERY_TMPLT % '@@expire_logs_days'