OmniAuth triggering validations - ruby

I am using OmniAuth in an application that requires authentication.
I have 3 ways for users to authenticate:
Create an account on my site
Facebook via OmniAuth
Twitter via OmniAuth
For option 1 I have validations in the form of:
validates_presence_of :email, :role
validates_presence_of :password, :if => :password_required
validates_presence_of :password_confirmation, :if => :password_required
validates_length_of :password, :within => 4..40, :if => :password_required
validates_confirmation_of :password, :if => :password_required
validates_length_of :email, :within => 3..100
validates_uniqueness_of :email, :case_sensitive => false
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
validates_format_of :role, :with => /[A-Za-z]/
The problem is that when I allow a user to login via twitter/facebook for the first time an Account is created, the validations are triggered, and fail.
For example:
ActiveRecord::RecordInvalid - Validation failed: Password can't be blank, Password is too short (minimum is 4 characters), Password confirmation can't be blank:
This makes sense as OmniAuth created accounts will not be submitting a password but i'm not sure exactly how i should make my model aware of this and skip (specific?) validations.
If it's of any use, the full account.rb model is here: http://pastie.org/private/wzpftprrzfg42uifetfhpa
Thanks a lot!!

try to extract the condition into the encrypt_password method from here, this line seems incorrect:
# Callbacks
before_save :encrypt_password, :if => :password_required
can you also copy-paste stack trace please?

Related

DEPRECATION WARNING: The `Validator#setup` instance method is deprecated and will be removed on Rails 4.2

I don't know what this warning is ? Please suggest something.
Given below is part of my application code.
It gives me error on statement with validates_date line.
Rails suggest me the do something like:
class MyValidator < ActiveModel::Validator
def initialize(options={})
super
options[:class].send :attr_accessor, :custom_attribute
end
end
This is the code of application below:
class Patient < ActiveRecord::Base
searchkick index_name: "patients",text_start: [:first_name,:last_name]
after_update :reindex
has_secure_password
has_many :addresses
has_many :vitals
has_attached_file :avatar, :styles => { :medium => "150x150>", :thumb => "50x50>" }, :default_url => "app/assets/images/missing.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
validates :email, email_format: {message: "Invalid email format" }
validates_uniqueness_of :email
validates :password_digest, presence: true, confirmation: true, length: {minimum: 8,message:"Must be of atleast 8 characters"}
validates :first_name, presence: true, format: { with: /\A[a-zA-Z]+\z/, message: "First Name should contain only alphabets"}
validates :last_name, presence: true, format: { with: /\A[a-zA-Z]+\z/, message: "Last Name should contain only alphabets" }
validates_date :dob,:before => lambda { Date.current }, presence: true
validates :password_digest, presence: true, confirmation: true, length: {minimum: 8,message:"Must be of atleast 8 characters"}
validates :primary_phone_no, presence: true,numericality: {only_integer: true}
end
You don't need to worry right now. I see from validates_date you are using the validates_timeliness gem - it's that gem that is currently throwing the deprecation warning.
It is an open issue on that gem and it's being worked on - this is the current open issue: https://github.com/adzap/validates_timeliness/pull/114
I suggest you just wait until they fix it and then update the gem. It's just a warning and won't stop anything working right now.

Rails 4 Device 3.2 registration with custom attributes, UnknownAttributeError

Issue looks simple, drives me up the walls and has cost me weeks of production time so far and i dont see this issue go away anytime soon since it pops up absolutely everywhere where nested attributes come in.
Started POST "/users" for 127.0.0.1 at 2013-11-12 04:56:03 +0100
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"afucNMlRRQkgBeKVVwOQxvjtMtvCDPiQLilr7TXXnUg=", "user"=>{"email"=>"test7#test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "first_name"=>"test7", "last_name"=>"test7", "preferred_language"=>"en", **"master_data_contact_information"=>**{"contact_email"=>"test7#test.com", "primary_phone_number"=>"23452352345234", "secondary_phone_number"=>"324523453245", "fax_number"=>"23452345234"}, "group_token"=>""}, "commit"=>"Register"}
Completed 500 Internal Server Error in 96ms
ActiveRecord::UnknownAttributeError (unknown attribute: master_data_contact_information):
How can it be unknown? it is RIGHT THERE.
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password,
:password_confirmation, :first_name,
:last_name, :preferred_language,
:group_token,
:master_data_contact_information =>
[:contact_email, :primary_phone_number, :secondary_phone_number, :fax_number ]
) }
end
if i change it to this:
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password,
:password_confirmation, :first_name,
:last_name, :preferred_language,
:group_token
) }
end
I get
Unpermitted parameters: master_data_contact_information
so what is the deal with nested resources and strong parameters?
When run in the RubyMine console, it works fine.
params = ActionController::Parameters.new user: {"email"=>"test5#test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]",
"first_name"=>"testqr", "last_name"=>"nsdfjkhasdfjk", "preferred_language"=>"en", "group_token"=>"",
"master_data_contact_information"=>
{"contact_email"=>"test10#test.com", "primary_phone_number"=>"786789678678",
"secondary_phone_number"=>"56675675876567", "fax_number"=>"2456246"}}
p = params.require(:user).permit(:email, :password, :password_confirmation, :first_name,
:last_name, :preferred_language, :group_token,
:master_data_contact_information => [:contact_email, :primary_phone_number, :secondary_phone_number, :fax_number ]
)
all is shiny.
I get that the Rails core people wanted to make rails more secure, but this has taken up a lot of my time.
It works really well on simple models, yes.
when things start to get a tiny bit complicated, all hell breaks lose.
Try changing :master_data_contact_information to :master_data_contact_information_attributes
So you have something like this:
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password,
:password_confirmation, :first_name,
:last_name, :preferred_language,
:group_token,
:master_data_contact_information_attributes =>
[:contact_email, :primary_phone_number, :secondary_phone_number, :fax_number ]
) }
end

Ruby 2.0 + Rails 4 + Devise 3.1.1 logout issue

if I click on the logout button i get this error: inspected result must be ASCII only or use the same encoding with default external
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
before_action :authenticate_user!
before_action :configure_permitted_parameters, if: :devise_controller?
protect_from_forgery with: :exception
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :email, :password, :password_confirmation, :current_password) }
end
end
Link:
<%= link_to "Logout", logout_path, title: "Logout", method: :delete %>
Routes:
devise_scope :user do
get 'register', to: 'devise/registrations#new', as: 'register'
get 'login', to: 'devise/sessions#new', as: 'login'
delete 'logout', to: 'devise/sessions#destroy', as: 'logout'
end
I have no idea where the problem is.
If I remove this 3 lines then it works but i can't register a new user:
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :email, :password, :password_confirmation, :current_password) }
Thank you!
Try using the following
devise_parameter_sanitizer.for(:sign_up) << :username
And if you need yet another field, add a line like the one above
Im not sure if this is the cause but I noticed that you don't allow a password to be whitelisted upon sign in. I assume that you would want that because you a password in the sign up and account update. It should look like this
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password) }

User specific Redirect after successful login in ruby on rails

Currently I am working on a sms application .I used devise gem for authentication and carrier wave for uploading. My question is after a successful login a user has to redirect to his own page and different users will be having redirecting to different pages.
User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body
has_many :sms
end
Sm model
class Sm < ActiveRecord::Base
attr_accessible :Messages, :Mobile_no, :Nickname, :Templates
validates_presence_of :Mobile_no
validates_length_of :Mobile_no, :minimum => 10, :maximum => 10, :allow_blank => true
validates :Mobile_no, :numericality => {:only_integer => true}
attr_accessible :sm_id, :name, :image
belongs_to :sm
mount_uploader :image, ImageUploader
validate :image_size_validation, :if => "image?"
def image_size_validation
errors[:image] << "should be less than 1MB" if image.size > 1.megabytes
end
validates :image, allow_blank: true, format: {
with: %r{\.(xls|xlsx|csv|txt)\z}i,
message: 'must be a TXT, CSV, XLS, or XLSX'
}, if: :filename_has_extension?
def filename_has_extension?
!(image.to_s =~ /\.[a-z]{1,4}\z/).nil?
end
belongs_to :user
end
You should define after_sign_in_path_for method in ApplicationController
def after_sign_in_path_for(resource)
# resource is commonly a User class object
if resource.admin?
# redirect somewhere
else
# redirect somewhere else
end
end

Two-page sign-up process in rails?

I'm attempting to create a rails app where a user will sign up, then immediately be directed to fill out a profile with more detailed information.
I'm currently attempting this by having both a users and a profile model, with a has_one/belongs_to relationship between the two models.
I'm having trouble with createing the profile for the user. Tests fail with undefined methodprofiles' for #when testing the creation, and using an automated profile builder calledsample_data.rake`:
namespace :db do
desc "Fill database with sample data"
task :populate => :environment do
Rake::Task['db:reset'].invoke
admin = User.create!(:name => "name name",
:email => "fakename#fake.com",
:password => "password",
:password_confirmation => "password")
admin.toggle!(:admin)
99.times do |n|
name = Faker::Name.name
email = Faker::Internet.email
password = "password"
User.create!(:name => name,
:email => email,
:password => password,
:password_confirmation => password)
end
User.all.each do |user|
User.profiles.create(:city => Faker::Address.city,
:state => Faker::Address.us_state_abbr,
...
)
end
end
end
Also fails on
I'm having trouble with createing the profile for the user. Tests fail with undefined method 'profiles'
profiles_controller.rb is:
class ProfilesController < ApplicationController
before_filter :authenticate, :only => [:create, :edit]
def create
#profile = current_user.profiles.build(params[:profile])
if #profile.save
flash[:success] = "Profile Created!"
redirect_to root_path
else
render 'pages/home'
end
end
def edit
end
end
profile.rb is
class Profile < ActiveRecord::Base
attr_accessible :city, :state, ...
belongs_to :user
validates :city, :presence => true
validates :state, :presence => true
...
end
Can anyone see what I'm doing wrong? Is there a way to merge all the items I need under "users", validate the presence of all the required information, and have the signup process be two pages?
Other suggestions for this?
Why do you do this?
1.times do...end
You dont need that.
The failure comes up because you need to create ONE profile, not profiles, for one certain user.
So try this:
User.all.each do |user|
user.create_profile(:city => "bla", ...)
end
In you controller the same. You have just one profile, using singular will help out.

Resources