Rails: Before process_action callback :authenticate_user! has not been defined - ruby-on-rails

I'm creating a rails app that includes devise.
I'm trying to add Twilio messaging to my site with Ngrok, i used this tutorial:
https://www.twilio.com/blog/2016/04/receive-and-reply-to-sms-in-rails.html
I was able to open Ngrok in the console and get the web-id they give for my url.
I keep getting this error when I plug the url into my browser ..I'm supposed to get to my own rails local app. Not sure whats wrong.
What I added in my messaging controller made for ngrok:
class MessagesController < ApplicationController
skip_before_filter :verify_authenticity_token
skip_before_filter :authenticate_user!, :only => "reply"
def reply
message_body = params["Body"]
from_number = params["From"]
boot_twilio
sms = #client.messages.create(
from: Rails.application.secrets.twilio_number,
to: from_number,
body: "Hello there, thanks for texting me. Your number is #{from_number}."
)
#twilio expects a HTTP response to this request
end
private
def boot_twilio
account_sid = Rails.application.secrets.twilio_sid
auth_token = Rails.application.secrets.twilio_token
#client = Twilio::REST::Client.new account_sid, auth_token
end
end
really unsure what is wrong.
when its not connecting to the 'def reply' and authenticate_user should be defined by devise.

Twilio developer evangelist here.
It looks like this was a problem that Rails 5 seems to have introduced. If the filter hasn't been defined by the time it is used in a controller it will raise an error. This was discovered in the Clearance project too.
Their fix was to pass the raise: false option to skip_before_filter:
class MessagesController < ApplicationController
skip_before_filter :verify_authenticity_token
skip_before_filter :authenticate_user!, :only => "reply", :raise => false
end

I had a similar issue to this when I was working on a Rails 6 application with Devise gem for authentication and authorization.
I added a skip_before_action :authenticate_admin!, only: [:index, :show] to the Products controller
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
skip_before_action :authenticate_admin!, only: [:index, :show]
def index
#products = Product.all
end
.
.
.
end
And it was throwing the error below when I visit the Products page:
Before process_action callback :authenticate_admin! has not been defined
Here's how I fixed it:
To use the skip_before_action :authenticate_admin!, only: [:index, :show] in the Products controller, I first needed to define the before_action :authenticate_user! in the application_controller:
# app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_admin!
end
Now I can use the skip_before_action :authenticate_admin!, only: [:index, :show] in the Products controller:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
skip_before_action :authenticate_admin!, only: [:index, :show]
def index
#products = Product.all
end
.
.
.
end
An alternative, if I don't want to define the before_action :authenticate_user! in the application_controller is to use the before_action :authenticate_admin!, except: [:index, :show]:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_action :authenticate_admin!, except: [:index, :show]
def index
#products = Product.all
end
.
.
.
end
That's all.
I hope this helps

Related

Can I use 2 index actions in my controller?

class MoviesController < ApplicationController
before_action :set_movie, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#movies = Movie.all
end
def current_user_movie_index
#movies = current_user.movies
end
end
I want to show all the movies for all user on index, but I want to add a new link to show only the movies for current_user. Will I do a new action? can I use the same index view for both?
Like this:
controller:
class MoviesController < ApplicationController
before_action :set_movie, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#movies = Movie.all
end
def current_user_movies
#movies = current_user.movies
end
end
routes:
resources :movies do
get :current_user_movies, on: :collection
end
It will now be available at /movies/current_user_movies.

before_action extend from superclass

I have next definitions:
ApplicationController:
before_action :set_resource, only: [:edit, :update, :destroy]
...
private
def set_resource
...
OtherController < ApplicationController
before_action :set_resource, only: [:new_action1, :new_action2]
...
def new_action1
....
def new_action2
I expect set_resource method will be called before actions edit, update, destroy, new_action1, new_action2, but it right only for methods: edit, update, destroy
I faced almost the same problem today while writing plugin for Redmine.
There is an issues_controller with callbacks in Redmine:
OtherController < ApplicationController
before_filter :find_issue, :only => [:show, :edit, :update]
before_filter :authorize, :except => [:index]
end
And I added another action in module that is being included in issues_controller:
module IssuesControllerPatch
def self.included(base)
before_filter :find_issue, :only => [:show, :edit, :update, :merge]
end
end
What happened here is newly added filter for merge action gets called after authorize method, thus failing authorization.
To solve the problem, I overrode authorize method like that:
module IssuesControllerPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
alias_method :default_authorize, :authorize
alias_method :authorize, :authorize_with_merge
end
end
module InstanceMethods
def authorize_with_merge
find_issue if params[:action] == "merge" && params[:controller] == "issues"
default_authorize
end
end
end
Not quite elegant, but works like a charm. This should help you, as well.

Not only define action for before_filter but also controller

Is it possible that i not only define an action for before_filter but also the controller of the action? I want to put the before_filter method into my application_controller but when i define there for example:
before_filter :authorize, except: [:index]
All controllers are affected that have an index action!
I would like to wirte something like that:
before_filter :authorize, except: [user#index]
Thanks
You cannot do what you are asking for. What you can do is
class ApplicationController < ActionController::Base
before_filter :authorize
...
end
class UsersController < ApplicationController
skip_before_filter :authorize, :only => [:index]
...
end
Why not put the before filter in your users_controller?
class UsersController < ApplicationController
before_filter :authorize, except: [:index]
...
end

Model level method to call in before_filter

I am working in rails 2, I have a model level method, which i want to call in before_filter. How can i do this?
I tried this way, but its not working
before_filter :LmsUser.can_edit_update, :only => [:new, :create, :edit, :update, :destroy]
You should add a method to your controller and use that as the before filter. For example:
class MyController < ApplicationController
before_filter :check_permissions,
:only => [:new, :create, :edit, :update, :destroy]
private
def check_permissions
unless LmsUser.can_edit_update
# redirect_to, render, or raise
end
end
end
See the filters section of the Action Controller Overview guide for more information.

How do I ignore the authenticity token for specific actions in Rails?

When I have a specific action that I don't want to check the authenticity token on, how do I tell Rails to skip checking it?
Rails 5.2+
You can use the same skip_before_action method listed below or a new method skip_forgery_protection which is a thin wrapper for skip_before_action :verify_authenticity_token
skip_forgery_protection
Rails 4+:
# entire controller
skip_before_action :verify_authenticity_token
# all actions except for :create, :update, :destroy
skip_before_action :verify_authenticity_token, except: [:create, :destroy]
# only specified actions - :create, :update, :destroy
skip_before_action :verify_authenticity_token, only: [:create, :destroy]
See all options # api.rubyonrails.org
Rails 3 and below:
skip_before_filter :verify_authenticity_token
In Rails4 you use skip_before_action with except or only.
class UsersController < ApplicationController
skip_before_action :verify_authenticity_token, only: [:create]
skip_before_action :some_custom_action, except: [:new]
def new
# code
end
def create
# code
end
protected
def some_custom_action
# code
end
end

Resources