rmagnum2002
rmagnum2002

Reputation: 11421

Creating a Mysql user within a Rails controller action

Working on an app that wil be used by admin only to create multiple instances of another app.

In other words, app A will be used to create clones of app B on server and create all the configurations needed to run that cloned app on a subdomain new_clone.domain.com.

Managed to clone the app, created the apache config file, unicorn server settings file too. Managed to run rake db:create; db:migrate but I did this with the root user of mysql.

At the point where I clone the app, I generate a database.yml file for the new cloned app that has at this moment username and password set as root, but I woould like to have a different user for each cloned app.

The app A has a model called Subdomain, in the subdomains_controller.rb at the create action I do all the things, clone, generate config files, running rake tasks, etc... and also in this create action I need to create a new Mysql user with privileges for a specific database.

What I have tried so far, can't say I did much, I tried to run the mysql command within controller create action:

def create
  if @subdomain.save
    ....
    system "mysql -u root -p root; create database new_database;..."
    ....
  else
    ....
  end
end

but this puts my create action on hold until I type in the password, and even if I'll find a way to go over it I am not sure the rest of mysql commands will work. Probably there is a better way to add a Mysql user with one command line without going into mysql console.

Thank you.

Upvotes: 1

Views: 647

Answers (2)

rmagnum2002
rmagnum2002

Reputation: 11421

Thanks to Yuriy's answer I got it working in a shorter way:

  def create_mysql_user
    @db_name = "#{@subdomain.name}_domain_production"
    @db_user = "#{@subdomain.name}_user"
    @db_password = "#{@subdomain.name}domain_password"

    ActiveRecord::Base.connection.execute("GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER,
        INDEX ON `#{@db_name}`.* TO #{ActiveRecord::Base.sanitize(@db_user)}@localhost
        IDENTIFIED BY #{ActiveRecord::Base.sanitize(@db_password)};")
    # Apply
    ActiveRecord::Base.connection.execute("FLUSH PRIVILEGES")
  end

Upvotes: 1

Yuri Golobokov
Yuri Golobokov

Reputation: 1965

As far as I understood, your create method runs under Rails app with root mysql user. Then you can simply execute mysql commands via AR adapter:

# Create DB
ActiveRecord::Base.connection.execute("CREATE DATABASE IF NOT EXISTS \
`#{ActiveRecord::Base.sanitize(db_name)}` CHARACTER SET = `utf8` \ 
COLLATE = `utf8_general_ci`")    
# Create User
ActiveRecord::Base.connection.execute("REPLACE INTO mysql.user \ 
(Host, User, Password) VALUES(\"localhost\", \ 
\"#{ActiveRecord::Base.sanitize(db_user)}\", \ 
PASSWORD(\"#{ActiveRecord::Base.sanitize(db_password)}\"))")
# Grant access
ActiveRecord::Base.connection.execute("GRANT ALL PRIVILEGES ON \ 
`#{ActiveRecord::Base.sanitize(db_name)}`.* TO \ 
`#{ActiveRecord::Base.sanitize(db_user)}`")
# Apply 
ActiveRecord::Base.connection.execute("FLUSH PRIVILEGES")

Upvotes: 2

Related Questions