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" }
Related
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
I'm using Devise with Ruby on Rails.
What is the recommended way to redirect unauthenticated users to the sessions#new page if they attempt to access a page that requires authentication?
Right now I get an error that says no route matches the one they attempt to access (leading to a 404 error in production).
Just simple add this method to application_controller.rb
protected
def authenticate_user!
if user_signed_in?
super
else
redirect_to login_path, :notice => 'if you want to add a notice'
## if you want render 404 page
## render :file => File.join(Rails.root, 'public/404'), :formats => [:html], :status => 404, :layout => false
end
end
And you can call this method on before_filter another controllers you want.
e.g :
class HomesController < ApplicationController
before_filter :authenticate_user!
## if you want spesific action for require authentication
## before_filter :authenticate_user!, :only => [:action1, :action2]
end
Don't forget add login_path into routes.rb
devise_scope :user do
match '/sign-in' => "devise/sessions#new", :as => :login
end
note : I always use this way when play with devise for my apps authentication.. (rails 3.2 and rails 4.0.1)
You can do just like GeekTol wrote, or just put
before_action :authenticate_user!
in your controller.
In this case, devise uses the default authenticate_user! method, that will redirect to the "user_session_path" and use the default flash message.
It's not necessary to rewrite authenticate_user! method, unless you want to customize it.
I thought you could just add:
before_action :authenticate_user!
to each controller that required the user to be logged in.
I'm a Rails beginner but I found this in my own searches and it works well in my application.
You should refer to Devise's own How To: How To: Redirect to a specific page when the user can not be authenticated.
Another alternative I can think of is creating a routing Constraint wrapping your protected routes. You'd better stick to Devise's way, but here is an example:
#On your routes.rb
constraints(Constraints::LoginRequired) do
get '/example'
end
#Somewhere like lib/constraints/login_required.rb
module Constraints
class LoginRequired
def self.matches?(request)
#some devise code that checks if the user is logged in
end
end
end
Add this code in your config/routes.rb devise_for :users and resources :users and you can generate devise in views.
How do I tell Devise to route the user to a one-time welcome screen when he has just registered?
Make a new controller "RegistrationsController" and customize the appropriate method:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
some_special_page
end
end
If the account that is registered is 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)
some_special_page
end
end
Modify config/routes.rb to use the new controller
devise_for :users, :controllers => { :registrations => "registrations" }
Source: https://github.com/plataformatec/devise/wiki/How-To:-Redirect-after-registration-(sign-up)
In the Application controller, add this:
def after_sign_up_path_for(resource)
some_special_page
end
For most of Devise-related questions, hit up their Github wiki
by default Devise will forward user to: user_root (if your model name is user)
so you can define named route
get "/welcome" => "welcomes#index", :as => "user_root"
Using devise, how do i make my Sign Up as my landing/welcome page and then after sign up they go inside the site to the Profile/signed in area?
I am trying to figure out how to make it like where Facebook their is two sides of the website; the Outside (sign up, about,contact,etc) and The Inside (Profile,sign out,etc) for Users only after sign up or sign in.
Thank you.
P.S. I am new at Ruby on Rails and creating applications but i did do the authentication system with the Rails 3 Tutorial, i understand most things to start using Devise, i jst dont know where to start with this situation.
I was going to use 2 application layouts, 1 before sign up which is layouts/welcome.html.erb with PagesController (about,terms,etc) and the other for signed in users which will be layouts/application.html.erb with ApplicationController (profile,news,add,etc), is this the best steps?
in your routes.rb:
root :to => 'welcome#index'
Where welcome is the controller and index is the action.
In your application controller:
def after_sign_in_path_for(user)
"/url_you_want_to_redirect_to/"
end
This my new and updated way using Rails 3.1.0 and Devise 1.5.0:
routes.rb
root :to => "pages#redirect_to_sign_up"
devise_for :users do
get "welcome" => "devise/registrations#new", :as => :new_user_registration
get "account_settings" => "devise/registrations#edit"
get "sign_in" => "devise/sessions#new"
get "sign_out" => "devise/sessions#destroy"
get "new_password", :to => "devise/passwords#new"
end
match 'home', :to => "user_pages#home"
namespace :user do
root :to => "user_pages#home"
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
protected
def after_sign_in_path_for(resource)
stored_location_for(:user) || root_path
end
private
def after_sign_out_path_for(resource)
stored_location_for(:user) || root_path
end
end
pages_controller.rb
class PagesController < ApplicationController
def redirect_to_sign_up
if signed_in?.blank?
redirect_to new_user_registration_path
else
redirect_to home_path
end
end
end
user_pages_controller.rb
class UserPagesController < ApplicationController
before_filter :authenticate_user!
def home
end
def profile
end
end
I find it easiest to root to the desired authenticated landing page and just use a before_filter to force the user to sign in/sign up first via a before_filter.
In this case, let's say your "signed in area" is a controller/action called profile/index.
In your routes.rb, set the root to profile/index.
root :to => 'profile#index'
Then in your profile_controller, set the following before_filter.
before_filter :authenticate_user!
This will automatically push a logged in user (or one that logged in earlier and set a Remember Me cookie) straight to the profile page. Any unauthenticated users will automatically end up on Sign In. You'll want a link (or separate tab) on that page to Sign Up as well.
On the root page check to see if the user is signed in, and redirect based on that.
redirect_to sign_up_path if current_user.nil?
Alternatively, you could render different templates instead of a redirect, but I think it's cleaner to have a 1:1 mapping between urls and pages.
Another approach is to modify devise. Edit devise_gem_path/lib/devise/failure_app.rb and replace the two occurrences in the redirect_url method of:
:"new_#{scope}_session_path"
with:
:"new_#{scope}_registration_path"
A less destructive solution would make redirect_url's response more configurable.
I am using Devise in my rails app. My Users model is registerable, which means that anyone can go to /users/sign_up and create a new account.
Is it possible to protect this route, so that only signed_in users can create new accounts?
Create a Controller with class Devise::RegistrationsController heriting. After you can add your filter. You just need define this controller like registration controller
class RegistrationsController < Devise::RegistrationsController
before_filter :authenticate_user!
end
In your routes.rb
devise_for :users, :controllers => { :registrations => 'registrations'}
It didn't worked for me because authenticate_user! is not getting called.
I fixed it that way :
class RegistrationsController < Devise::RegistrationsController
before_filter :prevent_sign_up
private
def prevent_sign_up
redirect_to new_user_session_path and return
end
end