Search code examples
ruby-on-railsdeviseomniauthform-forstrong-parameters

New user registration submits null IDs to Postgres database?


I'm having an issue with new user registrations, and I've spent the last week searching for an answer. I noticed the issue when I was attempting to add Omniauth to my Rails app, starting off with just Github. After a user signs in with Github, they go to the regular devise signup page to answer a couple more questions before signing in. I am able to successfully create a new user, however when I look at the db, it shows both university_id and program_id as null. When I looked at the server logs, I noticed a Unpermitted parameters: code, university_id, program_id error. I don't believe Omniauth has anything to do with this error per se since it's happening whether or not they choose to sign in with Github first. My suspicion is that it has something to do with the strong params. Any suggestions out there?

Registrations Controller:

class Users::RegistrationsController < Devise::RegistrationsController
  # GET /resource/sign_up
  def new
    @universities = University.all
    @programs = Program.all
    super
  end

  # POST /resource
  def create

    if params["user"]["code"] == ENV["CODE_TO_SIGN_UP"]
      User.create(user_params)
    else
      respond_to do |format|
        format.html { return redirect_to new_user_registration_path, notice: 'The code you entered was wrong. Please contact ' + ENV["ADMIN_EMAIL"] }
      end
    end

    super
  end
end

protected

    def user_params
      params.require(:user).permit(:name, :email, :github, :time_zone, :university, :program, :password)
    end
end

User Model:

class User < ActiveRecord::Base
   belongs_to :university
   belongs_to :program
end

University Model:

class University < ActiveRecord::Base
    has_many :programs
    has_many :users, through: :programs
end

Program Model:

class Program < ActiveRecord::Base
    belongs_to :university
    has_many :users, through: :university
end

new.html.erb:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
(...other fields)
 <div class="field">
    <%= f.label :university_id, 'University' %><br />
    <%= f.collection_select(:university_id, University.all, 'id', 'name') %>
  </div>

  <div class="field">
    <%= f.label :program_id, 'Program' %><br>
    <%= f.collection_select(:program_id, Program.all, 'id', 'name') %>
  </div>
  (...other fields)
<% end %>

Github Login User Model:

devise :database_authenticatable, :registerable,
                 :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:github]

def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
            user.email = auth.info.email
            user.password = Devise.friendly_token[0,20]
            user.full_name = auth.info.name   # assuming the user model has a name
            # If you are using confirmable and the provider(s) you use validate emails, 
            # uncomment the line below to skip the confirmation emails.
            # user.skip_confirmation!
        end
    end

    def self.new_with_session(params, session)
        super.tap do |user|
            if data = session["devise.github_data"] && session["devise.github_data"]["extra"]["raw_info"]
                user.email = data["email"] if user.email.blank?
            end
        end
    end

Application Controller

protected

def configure_permitted_parameters
   devise_parameter_sanitizer.permit(:sign_up, keys: [:github, :github_confirmation, :university_id, :program_id, :full_name, :time_zone])
end

Devise Initializer:

Devise.setup do |config|

  config.omniauth :github, "xxx", "xxx",
                  callback_url: "localhost:3000/users/auth/github/callback"
end

Gemfile:

gem 'devise', '~> 4.2'
gem 'omniauth'
gem 'omniauth-github'

If there's a bit of code I forgot to throw up, please let me know!


Solution

  • In your user_params method, you're allowing university and program but in the form you're passing university_id and program_id. Allow these in addition to code in your user_params and it should work.

    Rails will only permit the whitelisted parameters and disregard any others to prevent mass assignment. That's why university_id and other unpermitted params are nil in the database.