Error Handling - Email LDAP - Rails - ruby-on-rails

I'm beginner in Ruby on Rails and I need help
In my project, I need to catch on LDAP the e-mail of user.
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :ldap_authenticatable,:rememberable, :trackable
#validates :username, presence: true, uniqueness: true
validates :email, presence: true
validates_uniqueness_of :email
before_validation :get_ldap_email
before_save :get_ldap_email
def get_ldap_email
self.email = Devise::LDAP::Adapter.get_ldap_param(self.username,"mail").first
end
But If in LDAP doesn't have an e-mail, shows an RailsĀ“ error message and I want to redirect to a page with a message made by me.
So, in SessionController i want make an "if", but i don't have success to call the method.
class Users::SessionsController < Devise::SessionsController
require_relative '../../models/User.rb'
def create
super
if get_ldap_email == nil
# redirect to /errorlogin
end
end
And here show message
undefined local variable or method `get_ldap_email' for #
Users::SessionsController:0x67342e0>
Also I modificed the User for this...
def get_ldap_email
ldapEmail = Devise::LDAP::Adapter.get_ldap_param(self.username,"mail")
if ldapEmail == nil
else
self.email = ldapEmail.first
end
end
But now show this message
Validation failed: Email can't be blank
I don't what I need to do...

The issue is that you're calling super before your get_ldap_email, so the validation in Devise's SessionController is checking for a valid email. This should work:
def create
if get_ldap_email == nil
# redirect to /errorlogin
end
super
end

Related

Devise: Authenticate with Just Username Only Instead of Email

everyone!
So I'm building an application that only needs a username for authentication and not an email.
In my config/initializers/devise.rb, I changed the :email to :username resulting to this
config.authentication_keys = [:username]
config.case_insensitive_keys = [:username]
config.strip_whitespace_keys = [:username]
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :stores
has_many :customers, through: :stores
has_many :visits, through: :stores
has_many :mall_managers
validates :name, presence: true
validates :username, presence: true, uniqueness: true
end
I also edited the views accordingly.
When I try to sign up I get an error:
NoMethodError in Devise::RegistrationsController#create
undefined method `email' for #<User:0x000000011bd61b38>
i guess your user table does not contain email column, but the module validatable of gem devise will validates_presence_of the email, so that error will be raised.
however module validatable allow you ignore email validation by override email_required? method
class User < ApplicationRecord
# ...
def email_required?
false
end
def will_save_change_to_email?
false
end
def email_changed?
false
end
end
update i found more 2 methods need to override (as above), and who know what else (in future versions) ? so i recommend you add email database field (if the root cause i suspect (miss email) correct).

Devise custom after confirmation action

Switching from my own auth solution to Devise, I'm trying to integrate with my mail service, Convertkit.
I'm trying to make devise call my method after confirming a user but I'm not sure how to call the resource.
I tried both these solutions:
https://stackoverflow.com/a/25336930/6848493
https://stackoverflow.com/a/16423638/6848493
Here's my User model:
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :lastseenable, :timeoutable
validates :terms_and_privacy_policy,
acceptance: { accept: true }, on: :create, allow_nil: false
validates :first_name, presence: true
validates :last_name, presence: true
def confirm!
super
subscribe self
self.send_convertkit_failure unless #ck_response_code == 200
end
# Send email to admin in case of ConvertKit API failure
def send_convertkit_failure
UserMailer.convertkit_failure(self).deliver_now
end
Here's my user helper:
module UsersHelper
def subscribe(user)
response = HTTParty.post("https://api.convertkit.com/v3/forms/form/subscribe",
query: {email: user.email, first_name: user.name, course_opted: true, api_secret: 'my secret' })
#ck_response_code = response.code
end
end
There is no error message, it confirms the user okay but it doesn't subscribe them to convertkit. I've tried the same code but with resource
as the object but that throws an error.
As for the second method (writing to after_confirmation), it errors saying the user has already been confirmed.
Would really appreciate your input, thanks in advance.
Finally got this to work, in my User model:
# Override Devise::Confirmable#after_confirmation
def after_confirmation
subscribe self
self.send_convertkit_failure unless #ck_response_code == 200
end

devise invitable do not validate model

First, excuse my poor english, I'm french... it's tricky to explain my problem !
I have a model User model in a Rails application:
class User < ActiveRecord::Base
attr_accessible :email, :gender, :lastname, :firstname
end
And a BackUser model that inherit from User:
class BackUser < User
# Class for Backoffice User
devise :database_authenticatable,
:rememberable,
:trackable,
:lockable,
:invitable,
:confirmable,
:validatable,
:validate_on_invite => true
attr_accessible :password, :password_confirmation, :remember_me, :active, :role
validates :role, presence: true,
inclusion: ["admin", "normal"]
validates :gender, presence: true
validates :firstname, presence: true
validates :lastname, presence: true
def admin?
self.role == 'admin'
end
end
This second class should validate the record before invite!
BUT, when I use the console to do the following:
u = BackUser.new
u.invite!
"u" is saved in database and an invitation is send to a blank email...
Do you know what I have to do?
Thans a lot!
I'm sure you've found a solution or workaround to your problem by now, but for any future SO users who encounter the same problem I found a pretty simple fix.
Devise Invitable's model configuration docs don't fully explain how to implement :validate_on_invite, but you have to set the configuration option to true - :validate_on_invite => true.
Here's what my devise method looks like in my User model for this to work correctly.
models/user.rb
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :validate_on_invite => true
Now when I attempt to submit an invitation it is fully validating the record with what the validations I've set up in my User model before allowing the invitation to be sent and the user record to be created. Looking at the docs, I'm guessing you can also enable this setting in the devise initializer, but I haven't tried going that route.
*Second possible option to enable validation if needed
config/initializers/devise.rb
config.validate_on_invite = true
I've never been able to get the validation to work correctly for devise invitable. You can't use RobHeaton's suggestion either because you will receive a validation error on the password. I use this little hack to get validation to work:
def create
#user = User.new(user_params)
#user.valid?
#user.errors.messages.except!(:password) #remove password from errors
if (#user.errors.any?)
render 'new'
else
#user.invite!(current_user)
redirect_to user_path(#user)
end
end
It doesn't solve the mystery of why your behaviour is occurring, but:
if u.save
u.invite!
end
will give the end result you are after.

Anonymous user in devise - rails

I'm new to rails and I tried to make simple authentication with anonymous user. I followed this tutorial and I have this error:
undefined method `find_or_initialize_by_token'
This is my AnonymousUser model:
class AnonymousUser < User
ACCESSIBLE_ATTRS = [:name, :email]
attr_accessible *ACCESSIBLE_ATTRS, :type, :token, as: :registrant
def register(params)
params = params.merge(type: 'User', token: nil)
self.update_attributes(params, as: :registrant)
end
end
This is my User model:
class User < ActiveRecord::Base
devise :database_authenticatable, :confirmable, :lockable, :recoverable,
:rememberable, :registerable, :trackable, :timeoutable, :validatable,
:token_authenticatable
attr_accessible :email, :password, :password_confirmation, :remember_me
end
And the last one important is my ApplicationController which has this error:
class ApplicationController < ActionController::Base
protect_from_forgery
def authenticate_user!(*args)
current_user.present? || super(*args)
end
def current_user
super || AnonymousUser.find_or_initialize_by_token(anonymous_user_token).tap do |user|
user.save(validate: false) if user.new_record?
end
end
private
def anonymous_user_token
session[:user_token] ||= SecureRandom.hex(8)
end
end
Someone told me that if AnonymousUser user inherits from User then AnonymousUser have method called find_or_initialize_by_token, but i don't know how to fix it.
Provided you have latest rails installed, try to refactor:
# in ApplicationController#current_user
AnonymousUser.find_or_initialize_by_token(anonymous_user_token).tap do |user|
user.save(validate: false) if user.new_record?
end
to something like this:
AnonymousUser.safely_find(anonymous_user_token)
and push the find_or_initialize_by_token and save(validate: false) into the model.
I wrote the blog post you referenced, but today, I would use
AnonymousUser.where(anonymous_user_token: anonymous_user_token).first_or_initialize
Dynamic finders have been deprecated AFAIK.
However, #Saurabh Jain is absolutely correct in his suggestion to refactor that block into a nice little push-button class method on the AnonymousUser.

Trying to create a new AdminUser in Rails: active_admin but cannot get email sent out

Hi I have added active_admin to my rails app. I would like to create a new AdminUser.
Based on this documentation I tried to create a user and have the app send out an email. The user was created fine in the app, but no email was sent out. I was wondering if anyone can give me suggestions as to why this is not working. Ive double checked my code and its exactly how the documentation says it should be.
What am I missing to make the email be sent out?
Here are the relevant classes
admin/admin_users.rb
ActiveAdmin.register AdminUser do
index do
column :email
column :current_sign_in_at
column :last_sign_in_at
column :sign_in_count
default_actions
end
form do |f|
f.inputs "Admin Details" do
f.input :email
end
f.buttons
end
end
models/admin_user.rb
class AdminUser < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
after_create { |admin| admin.send_reset_password_instructions }
def password_required?
new_record? ? false : super
end
before_destroy :raise_if_last
def raise_if_last
if AdminUser.count < 2
raise "Can't delete last admin user"
end
end
end
config/environments/development.rb
..........
#Added per active admin install instructions
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
sending email from localhost don't work directly if you haven't configured sendmail like utility.
you can either use SMTP for sending emails
check question below
send email from localhost
or you can write emails to a file
Rails Mailer: sending emails to a local file

Resources