I have a Admin::SessionsController who extends from Admin::ApplicationController.
I'm using a before_filter except to the login page, but the server is entering in a loop
I think there`s is something with the except thing, I think that I need to set the namespace or something...
This is the line of before_filte:
before_filter :authenticate_user , :except => { :sessions => :new }
This is my SessionController
class Admin::SessionsController < Admin::ApplicationController
def new
end
end
It might be easiest just to put a skip_before_filter in the Admin:SessionsController
class Admin::SessionsController < Admin::ApplicationController
skip_before_filter :authenticate_user, :only => [:new]
def new
end
end
Related
I want users to access the home page whether they're authenticated or not. Though, whenever the root url is visited, the user is immediately redirected to /users/sign_in. How do I disable this?
routes.rb
Rails.application.routes.draw do
root 'home#index'
devise_for :users
end
home_controller.rb
class HomeController < ApplicationController
before_action :authenticate_user!, except: [:index]
def index
end
end
With Devise is usually better to require authentication by default and then add exceptions with skip_before_action:
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
class HomeController < ApplicationController
skip_before_action :authenticate_user!
def index
end
end
This avoids the risk of leaving security holes just by programmer omission.
I can do this to skip calling "authenticate_user" in a certain controller where I need to:
class ApplicationController
before_filter :authenticate_user!
end
class MyController < ApplicationController
skip_before_filter :authenticate_user!
end
I want to call skip_before_filter for "login" action of devise gem and I don't want to have to override anything else. How can I do that?
One approach is to override devise sessions controler:
1) create a users/sessions_controller.rb file:
class Users::SessionsController < Devise::SessionsController
skip_before_filter :authenticate_user!
end
2) and set it on routes.rb:
devise_for :users, controllers: { sessions: "users/sessions"}
skip_before_filter is deprecated, so try to use skip_before_action
it's worked with me
basically I want to have two separate actions for change password and change email instead of just one.
I have updated my routes to point to my new controller which inherits from Devise::RegistrationsController.
My routes.rb:
devise_for :users, :controllers => { :registrations => "registrations" }
devise_scope :user do
get "/users/password" => "registrations#change_password", :as => :change_password
end
My registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def change_password
end
end
My app/views/devise/registrations/change_password.html.erb
<%=debug resource%>
Which gives me nil.
What am I missing here?
Thanks!
In Devise's built-in registrations_controller.rb, there is an authenticate_scope! method that creates the resource object you're looking for. It is executed by a prepend_before_filter, but only for certain methods:
class Devise::RegistrationsController < DeviseController
...
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]`
So you simply need to tell your custom controller to run that filter on your change_password method:
class RegistrationsController < Devise::RegistrationsController
prepend_before_filter :authenticate_scope!, :only => [:change_password]
def change_password
end
end
class RegistrationsController < Devise::RegistrationsController
def change_password
super
#resource = resource
end
end
app/views/devise/registrations/change_password.html.erb
<%=debug #resource%>
I'm using Devise as authenticating solution in Rails and I have a cached fragment :recent_users.
I want this fragment to expire when a new user is registered, changed or removed, so I put in my(manually created) users_controller.rb
class UsersController < ApplicationController
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
...
But my fragment does not expire when new creates or changes.
My user_sweeper contains basic prescriptions
class UserSweeper < ActionController::Caching::Sweeper
observe User
def after_save(user)
expire_cache(user)
end
def after_destroy(user)
expire_cache(user)
end
private
def expire_cache(user)
expire_fragment :recent_users
end
end
What am I doing wrong?
Problem solved!
I followed this steps and everything works:
$ mkdir app/controllers/users
$ touch app/controllers/users/registrations_controller.rb
In registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
end
Problem was that Registrations in Devise is a separate controller.
Put this in applications_controller.rb
class ApplicationController < ActionController::Base
cache_sweeper :user_sweeper, :only => [:create, :update, :destroy]
...
I have a number of resources (Trips, Schedules, etc) with actions that should be limited to just the resource's owner.
How do you implement code with a #require_owner method defined in ApplicationController to achieve this? Ideally, the code will look up the inheritance chain for the owner so the before_filter will work on a :comment that belongs_to :trip that belongs_to :user.
class TripsController < ApplicationController
belongs_to :member
before_filter :require_owner
...
end
I don't fully follow the description (would a comment really be owned by the trip owner?), but expanding slightly on jonnii's answer, here is an example that restricts the trip controller:
class ApplicationController < ActionController::Base
...
protected
# relies on the presence of an instance variable named after the controller
def require_owner
object = instance_variable_get("##{self.controller_name.singularize}")
unless current_user && object.is_owned_by?(current_user)
resond_to do |format|
format.html { render :text => "Not Allowed", :status => :forbidden }
end
end
end
end
class TripsController < ApplicationController
before_filter :login_required # using restful_authentication, for example
# only require these filters for actions that act on single resources
before_filter :get_trip, :only => [:show, :edit, :update, :destroy]
before_filter :require_owner, :only => [:show, :edit, :update, :destroy]
...
protected
def get_trip
#trip = Trip.find(params[:id])
end
end
Assuming the model looks like this:
class Trip < ActiveRecord::Base
belongs_to :owner, :class_name => 'User'
...
def is_owned_by?(agent)
self.owner == agent
# or, if you can safely assume the agent is always a User, you can
# avoid the additional user query:
# self.owner_id == agent.id
end
end
The login_required method (provided by or relying on an auth plugin like restful_authentication or authlogic) makes sure that the user is logged in and provides the user with a current_user method, get_trip sets the trip instance variable which is then checked in require_owner.
This same pattern can be adapted to just about any other resource, provided the model has implemented the is_owned_by? method. If you are trying to check it when the resource is a comment, then you'd be in the CommentsController:
class CommentsController < ApplicationController
before_filter :login_required # using restful_authentication, for example
before_filter :get_comment, :only => [:show, :edit, :update, :destroy]
before_filter :require_owner, :only => [:show, :edit, :update, :destroy]
...
protected
def get_comment
#comment = Comment.find(params[:id])
end
end
with a Comment model that looks like:
class Comment < ActiveRecord::Base
belongs_to :trip
# either
# delegate :is_owned_by?, :to => :trip
# or the long way:
def is_owned_by?(agent)
self.trip.is_owned_by?(agent)
end
end
Make sure to check the logs as you are doing this since association-dependent checks can balloon into a lot of queries if you aren't careful.
There's a few different ways to do this. You should definitely check out the acl9 plugin (https://github.com/be9/acl9/wiki/tutorial:-securing-a-controller).
If you decide you want to do this yourself, I'd suggest doing something like:
class Trip < ...
def owned_by?(user)
self.user == user
end
end
class Comment < ...
delegate :owned_by?, :to => :trip
end
# in your comment controller, for example
before_filter :find_comment
before_filter :require_owner
def require_owner
redirect_unless_owner_of(#commemt)
end
# in your application controller
def redirect_unless_owner_of(model)
redirect_to root_url unless model.owned_by?(current_user)
end
Forgive me if there are any syntax errors =) I hope this helps!
Acl9 is a authorization plugin. I'd give you the link, but I don't have cut and paste on my iPhone. If no one else provides the link by the time I get to a computer, I'll get it for you. Or you can google. Whichever. :)
I have only just started using it, but it has an extremely simple interface. You just have to create a roles table and a roles_user. Let me know how it goes if you decide to use it.
Or just use inherited resources:
InheritedResources also introduces another method called begin_of_association_chain. It’s mostly used when you want to create resources based on the #current_user and you have urls like “account/projects”. In such cases you have to do #current_user.projects.find or #current_user.projects.build in your actions.
You can deal with it just by doing:
class ProjectsController < InheritedResources::Base
protected
def begin_of_association_chain
#current_user
end
end