Add sign up condition to devise - ruby-on-rails

My goal is simple. I want to allow a user to sign up only if he possesses a unique secret code. I would like to check if this code is valid (being in my secret codes database) and then delete it once the user signed up.
I have a secret_code model with:
:secret_code column
I have a input for the secret code in my sign up form
<%= f.input :secret_code, required: true, autofocus: true %>
Should I personalize the class RegistrationsController < Devise::RegistrationsController?
How ? Thanks !

You can do that by overriding registrationcontroller. Uncomment create method like this.
def create
super
end
and add a filter like:
before_action :check_secret_code, only: [:create]
and you must modify your routes to tell devise use your controller instead of its default:
devise_for :users, controllers: { registrations: "users/registrations" }
you can specify what you want in that check_secret_code method and make render 'new' if code is wrong. Hope it helps.

You can achieve this with a simple before filter. This way you don't have to mess with devise code.
class RegistrationsController < Devise::RegistrationsController
before_filter :check_conditions, only: :create
def create
super
end
private
def check_conditions
#your conditions
end
end

Solved! Along to #Mehmet answer I had to cutomize application_helper.rb
module ApplicationHelper
def resource_name
:user
end
def resource
#user ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
end
And put include ApplicationHelper after the class name in registrations_controller.rb

Related

how to override devise security extension PasswordExpiredController

I want to override show logic in order to permit change password not only if it is expired, but some days earlier. I need to modify or replace this before_filter logic
def skip_password_change
return if !resource.nil? && resource.need_change_password?
redirect_to :root
end
I want to make my controller like this:
class PasswordsController < Devise::PasswordExpiredController
# ...
def skip_password_change
return if !resource.nil? && (resource.need_change_password? || ... )
redirect_to :root
end
end
How to achieve my goal?
UPD:
all answers below are kind of right, I missed one thing - my custom controller was placed inside controllers/admin directory, so I should name it Admin::CustomPasswordExpiredController, but I missed Namespace prefix Admin and rails fell into circular dependency.
Just extend devise controller with your custom controller:
# config/routes.rb
devise_for :users, controllers: { passwords: 'custom_passwords' }
# app/controllers/custom_passwords_controller.rb
class CustomPasswordsController < Devise::PasswordsController
def edit
resource = resource_class.new
return unless resource.need_change_password? # your middleware logic here
super
end
end
More facilities can be found in devise PasswordsController documentation (by clicking "View source")
You can try this workaround, first skip the default before_action for skip_password_change method, then add a custom method to wrap it in a condition. Try this
class PasswordsController < Devise::PasswordExpiredController
skip_before_action :skip_password_change, only: :show
before_action :skip_password_change_show, only: :show
def skip_password_change_show
return if !resource.nil? && (resource.need_change_password? || #yourcondition )
redirect_to :root
end
end
Hope that helps!
Go to your routes file and overwrite the controller methods there.
Something like devise_for :users, controllers: {x: 'y'} where x is the name of the controller from devise that you want to overwrite and y is the name of your custom controller you want to overwrite with

how to make devise admin see everything?

I normally have everything scoped with current_user
eg:
#integrations = current_user.integrations.all
For trouble shooting, I want the admin to see everything for all users. I currently have a boolean on the user model that is admin: true
To get around the admin seeing everything, I keep doing this:
def index
if current_user.admin?
#integrations = Integration.all.includes(:user)
#reports = Report.all
else
#integrations = current_user.integrations
#reports = current_user.reports
end
end
I feel like there is an easier way... suggestions?
Thanks!
You could maybe abstract the admin check to a protected/private method in your User controller:
def is_admin
current_user.admin?
end
And then at the top of the controller, place a before action to catch whatever methods you want:
class UsersController < ApplicationController
before_action :is_admin, only: [:index, :show]
# rest of your code
end
OR
class UsersController < ApplicationController
before_action :is_admin, except: [:destroy]
# rest of your code
end
You could make a protected method in the application_controller.rb file. As stated above it will check to see if the current_user is and admin. Then you can use conditional statements to set privileges.
assuming that admin is a boolean value
def is_admin?
current_user.admin == true
end
In a view you can then say
if current_user.is_admin?
........
end

Need to redirect to another form after devise sign up form

i am new to ror..i have created a form using devise..the registeration form is working..the values are saved in db too but after saving it redirects to users page...Is there any way to change it...i want another form to be link once user submits form...
Controller
class UserRequestsController < ApplicationController
def new
#user_request = UserRequest.new
end
end
Application Helper
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
Model
class UserRequest < ActiveRecord::Base
belongs_to :user
validates :user_id, :email, :name, :invitation_type, presence: true
validates :email, uniqueness: true
validates :email, email: true
validate :email_not_in_use_already
validate :invitation_type_is_valid
def email_not_in_use_already
if new_record? && User.where(email: self.email).any?
errors.add(:email, "is already in use")
end
end
def invitation_type_is_valid
unless INVITATION_TYPES.include?(self.invitation_type)
errors.add(:invitation_type, "is not a valid type of invitation")
end
end
end
Application Controller
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name, :email, :password, :password_confirmation, :time_zone, :terms_of_service)
end
devise_parameter_sanitizer.for(:account_update) do |u|
u.permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password, :time_zone, :terms_of_service)
end
end
def after_sign_in_path_for(resource)
previous_url = session[:previous_url]
# if user has an invite code and isn't set up yet, direct them to the appropriate creation page
if invited_user_needs_profile?(session[:hash_code])
return path_for_invite(session[:hash_code])
end
user = resource # not checking resource type since right now only one is User; add later if needed
# require acceptance of terms of service
unless user.terms_of_service == true
flash[:alert] = "You have not yet accepted the Terms of Service. Please verify your account information and review the Terms of Service."
return edit_user_registration_path
end
# redirect to previous URLs in case user followed a link or bookmark but they were redirected due to needing to log in
unless Rails.env == "test"
# don't redirect to previous url if it's going to the root or users_path, because in those cases we'd rather take the user to their home page
return previous_url if previous_url.present? && previous_url != root_path && previous_url != new_user_registration_path && !(previous_url =~ /\/users\/password/)
end
if user.planner.present?
planner_path(user.planner.id)
elsif user.vendor.present?
vendor_path(user.vendor.id)
else
root_path
end
end
def after_sign_up_path_for(resource)
root to: "vendors#invited_new", as: :manager_root
end
end
Need to redirect to another controller action...can u please give any idea to get it fixed.
You need to specify only the path name there. Change:
def after_sign_up_path_for(resource)
root to: "vendors#invited_new", as: :manager_root
end
to:
def after_sign_up_path_for(resource)
manager_root_path
end
Read the docs:
def stored_location_for(resource)
nil
end
def after_sign_in_path_for(resource)
# path_to_redirect_to For eg. root_path
end
Yon can override your devise registration controller
class RegistrationsController < Devise::RegistrationsController
##this method calls when signup is success
def after_sign_up_path_for(resource)
if put your condition here
your_redirect_path (replace your different controller path here)
else
root_path
end
end
end
In this method you just write your logic
Or you can do one thing in your registrations controller create method after your resource will be saved
if resource.save
if resource.active_for_authentication?
if your condition
respond_with resource, location: your_redirect_path
else
end
end
end
1. Make a new controller "registrations_controller.rb" and customize the appropriate method:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path' # Or :prefix_to_your_route
end
end
If the account that is registered is confirmable and not active yet, you have to override after_inactive_sign_up_path_for method.
class RegistrationsController < Devise::RegistrationsController
protected
def after_inactive_sign_up_path_for(resource)
'/an/example/path' # Or :prefix_to_your_route
end
end
2. Modify config/routes.rb to use the new controller
Modify your devise_for line in routes.rb to look like this.
devise_for :users, controllers: { registrations: "registrations" }
Optionally Copy Views
Note: In rails 3.2.5 running Ruby 1.9.2-p290 the steps below don't seem to be necessary. You just need to create your RegistrationsController and alter your routes. Then, by virtue of inheriting from Devise::RegistrationsController, you pick up the existing Devise registrations views. This holds regardless of whether you've created those views already with
rails g devise:views
or not.
Note: After changing the controller in the config/routes.rb file, you will want to copy over the devise registration views over to the new app/views/registrations path.
Copy the files using "rails generate devise:views". After doing this, you need to copy views/devise/registrations/new.html.erb to views/registrations/new.html.erb Otherwise you will get a "Missing Template" error when you go to users/sign_up
3. Modify config/application.rb
You might need this line in case you encounter "MissingTemplate" error
in "/users/sign_up" page.
config.paths['app/views'] << "app/views/devise"

implement a user_controller for devise with a model user?

I have some methods now under "profile" like user blocking, banning, moderation.
It feels these should belong under "user" and inside the user controller.
Is there a way to have a user_controller.rb when using devise with a user model?
Reason for this is to scope all user related methods under the user_controller instead of the profile_controller as it is now.
Yes. There is no problem with that. You can simply create users_controller.rb and interact with User model like:
class UsersController < ApplicationController
# do any stuff you need here
def block
#user = User.find(params[:id])
#user.block
end
def ban
#user = User.find(params[:id])
#user.ban
end
end
For sure, you have to create routes for this controller:
resources :users, only: [] do
member do
get :ban
get :block
end
end
Like that.

Devise: How to create a new user being already logged in?

I'm going to create a multi user app, so, I will have a admin user that will have permission to create new ones.
I've created the UsersControllerbut when trying to create a new user, being already signed in, I'm getting redirect to root_path with an error message that says "You are already signed in".
So, what should I do to make this possible?
Found.
I have just to removed the registerable module from devise and it works.
In a controller method can't you just go:
def create_user
#user = User.new(:email => params[:email], :password => params[:password])
#user.save
...
end
This is how I am doing it in 2015
# in your terminal
rails g controller Registrations
Registrations controller should look like this,
# registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
skip_before_filter :require_no_authentication, only: [:new]
def new
super
end
end
The important line is the skip_before_filter...
That will disable the requirement that there be no user logged in.
The routes for the controller looks like this,
# routes.rb
devise_for :users,
controllers: {:registrations => "registrations"}
That will tell devise to use your custom registrations controller
Finally, setting up a custom route to that action:
# routes.rb
as :user do
get "/register", to: "registrations#new", as: "register"
end
There is another solution.
You must override registration controller and remove action (or actions) from prepend_before_filter.
DeviseRegistrationController source is here.
You can see:
prepend_before_filter :require_no_authentication, only: [:new, :create, :cancel]
It jumps into require_no_authentication before create method. If you want create new user while you are logged in, just remove :create from array.
I added in the Registrations Controller:
class RegistrationsController < Devise::RegistrationsController
...
skip_before_action :require_no_authentication, only: [:new, :create]
...
end
And it worked for me. I can now go and create a new user.
You could either override the default devise controller and add in your custom logic, or, It would probably be easier however to make a new (Admin) controller and simply create a user using one of it's actions.
#user = User.create!(:name => params[:foo], :email => params[:bar])
redirect_to #user
Devise has loads of guides on how to customise it's behaviour here: https://github.com/plataformatec/devise/wiki/_pages
This one in particular may be of interest to you: https://github.com/plataformatec/devise/wiki/How-To:-Manage-Users-with-an-Admin-Role-(CanCan-method) But make sure to have a look over the rest of the articles, there's a lot of them.
in case someone still looking for help, because it tooks a while for this to work , no clear answers
in your controller
class UsersController < ApplicationController
def new
#user = User.new
end
def add_user
#user = User.new(user_params)
if #user.save!
redirect_to root_path
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
in your routes :
get 'employees', to: 'users#new'
post 'employees', to: 'users#add_user'
and finally a form like this:
<%= form_for User.new , :url => {:action => "add_user"} do |user| %>
<%=user.email_field :email%>
<%=user.password_field :password%>
<%=user.password_field :password_confirmation%>
<%=user.submit 'add'%>
<%end%>
#Mourkeer +1
For simple_form 4.2.0 take #Mourkeer code and replace route.rb by:
# route.rb
devise_for :users, path_names: { registration: "registrations" }

Resources