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.
Related
I am using Rails 4 and Devise 3.
I am using the following in the routes file to prevent access to a page from non authenticated users (not signed in):
authenticate :user do
#page to protect
end
This redirects me to the user/sign_in page, but I want the user to be redirected to the root. So, I added the following as well to the routes page:
get 'user/sign_in' => redirect('/')
But this will mess up what I did in the sessions_controllers:
def new
return render :json => {:success => false, :type => "signinn", :errors => ["You have to confirm your email address before continuing."]}
end
This will stop showing. So, I would like another solution that redirects users to the root directly, instead of having to use authenticate :user and then get 'user/sign_in' => redirect('/').
The following may not have anything to do with redirecting the user to the root, but I would like to explain more about why I am overwriting the new method in the sessions_controller. I moved the sign_in and sign_up views to the root page (home page). In this case, I also needed to hack the error messages so that they appear in the home page, instead of redirecting the user to user/sign_in to show the errors. I used ajax for that.
Update
What I am looking for is something like this:
if user_authenticated?
#show the protected page
else
# redirect the user to the ROOT
end
You can set your devise scope to look something like this.
devise_scope :user do
authenticated :user do
root :to => 'pages#dashboard', as: :authenticated_root
end
unauthenticated :user do
root :to => 'session#new', as: :unauthenticated_root
end
end
EDIT (Based on the new info):
If you have something like this in your routes.rb
root to: 'visitors#index`
then you can have something like this in your visitors_controller.rb
class VisitorsController < ApplicationController
def index
if current_user
redirect_to some_authenticated_path
else
# business logic here
end
end
end
You will still want to handle the propper authorization requirements and authentication requirements in the some_authenticated_path controller and action.
I'm sorry I didn't understand your question, anyway you can do something like this:
class CustomFailure < Devise::FailureApp
def route(scope)
#return super unless [:worker, :employer, :user].include?(scope) #make it specific to a scope
new_user_session_url(:subdomain => 'secure')
end
# You need to override respond to eliminate recall
def respond
if http_auth?
http_auth
else
redirect
end
end
end
And in config/initializers/devise.rb:
config.warden do |manager|
manager.failure_app = CustomFailure
end
This was taken from the wiki of devise:
https://github.com/plataformatec/devise/wiki/How-To%3a-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated
I'm using Rails 4 and Devise to authenticate users. Once a user logs in, they are redirected to a sinatra app. I need the route to that page to be protected from unsigned-in users.
So the route I need to prevent users from visiting if they are not signed in is /kibana
Here is my routes files:
devise_for :user
root 'pages#home'
mount Kibana::Sinatra::Web => '/kibana', :trailing_slash => true
Any help is much appreciated, thank you.
EDIT here is my ApplicationController file
protect_from_forgery
before_filter :check_user
private
def check_user
if request.fullpath =~ /kibana/ && !user_signed_in?
authenticate :user do
end
end
end
Yet, not the result I need. When I visit localhost:3000 it redirects me to the user login with the note that I need to be logged in, but when I visit /kibana/ it just shows it without having to be logged in.
More or less this way:
class ApplicationController
before_filter :check_user
private
def check_user
if !current_user && request.fullpath =~ /kibana/
redirect_to your_app_login_url
end
end
end
Edit:
It looks like I was wrong, within your routes.rb:
authenticate :user do
mount Kibana::Sinatra::Web => '/kibana', :trailing_slash => true
end
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.
I just implemented a new homepage using public/index.html which I read that it overrides a lot of the routes.
I originally had root to: static_pages#home and in my static_pages\home.html.erb view if a user was logged in, they saw the logged in homepage and the anonymous visitor (public/index.html) homepage if not logged in.
After implementing public/index.html, I created a new route for logged in users and made previous root_path redirects to home_path
get '/home' => 'static_pages#home', :as => :home
However, I would like to use http://localhost:3000 as the homepage for both logged in and visitor homepages. Is this possible? How can I have visitors see the current public/index.html which works good right now, but not have to use http://localhost:3000/home after login? I want http://localhost:3000 after login as well.
Thanks
public/index.html is served by webserver before Rails, so you need another solution.
Instead you can move public/index.html into app/views/static_pages/index.html and edit your controller as follows:
class StaticPagesController < ApplicationController
def home
if signed_in?
# current content of #home action
else
render :index, :layout => false
end
end
end
or even more clean way
class StaticPagesController < ApplicationController
before_filter :show_index_page, :only => :home
def home
# the same
end
private
def show_index_page
render :index, :layout => false unless signed_in?
end
end
What you need is a simple HomeController which render the right view for corresponding user.
You must have two erb view files for anonymous and signed in user.
Story: A non logged in user should see a welcome static page and when he's logged in he should see a list of his blog posts.
I suppose the right way to do this is to route root to the action that lists all the user's posts which then checks for authentication. If the user isn't logged in then it renders the welcome page?
I need help with writing an action for the posts controller which displays posts for the logged in user.
routes.rb:
root :to => "posts#index"
post_controller.rb
class PostsController < ApplicationController
before_filter :authenticate_user!
def index
#posts = current_user.posts.all
end
end
If the user is not logged in, the before filter catches this and redirects somewhere (login? error message?). Otherwise the index method is called and the index view rendered.
This would work out of the box with devise, if you roll another authentication you need to adapt and/or write your own helpers, e.g. something like this:
application.html.erb
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user
helper_method :user_signed_in?
private
def current_user
#current_user ||= User.find_by_id(session[:user_id]) if session[:user_id]
end
def user_signed_in?
return 1 if current_user
end
def authenticate_user!
if !current_user
flash[:error] = 'You need to sign in before accessing this page!'
redirect_to signin_services_path
end
end
end
I had this problem but didn't want a redirect (adds delay and changes url) so I'm deciding between constraints suggested in User-centric Routing in Rails 3 or scoped routes mentioned in Use lambdas for Rails 3 Route Constraints
Constraints
root :to => "landing#home", :constraints => SignedInConstraint.new(false)
Scoped routes
scope :constraints => lambda{|req| !req.session[:user_id].blank? } do
# all signed in routes
end