Doorkeeper error help needed - ruby-on-rails

I am using doorkeeper for OAuth functionality on my ruby on rails application. Also I am using devise for user security management.
Here is my current doorkeeper.rb file:
Doorkeeper.configure do
orm :active_record
resource_owner_authenticator do
user_signed_in? || redirect_to(new_user_session_url)
end
admin_authenticator do
user_signed_in? || redirect_to(new_user_session_url)
end
enable_application_owner :confirmation => true
# authorization_code_expires_in 10.minutes
# access_token_expires_in 2.hours
# use_refresh_token
# default_scopes :public
# optional_scopes :write, :update
# client_credentials :from_basic, :from_params
# access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
# test_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
# skip_authorization do |resource_owner, client|
# client.superapp? or resource_owner.admin?
# end
# realm "Doorkeeper"
end
When I access /oauth/applications, I get an error page which says "uninitialized constant Admin", and "config/initializers/doorkeeper.rb:18:in `block (2 levels) in '".
What am I doing wrong?

I have resolved the issue. The problem lay in rails server caching the doorkeeper.rb initialiser file and I needed to restart the server after I had edited that file.

Related

Error in cancancan ability initializer when testing controllers

I added cancancan gem to my app, but it broked all my controller and feature tests. The error start in ability.rb initialize: the user variable is nil.
Here is the error log of one of the tests:
14) TestCasesController DELETE #destroy when not logged-in redirects to sign-in page
Failure/Error: if user.teacher?
NoMethodError:
undefined method `teacher?' for nil:NilClass
# ./app/models/ability.rb:5:in `initialize'
# /usr/local/rvm/gems/ruby-2.3.1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `new'
# /usr/local/rvm/gems/ruby-2.3.1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `current_ability'
# /usr/local/rvm/gems/ruby-2.3.1/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:342:in `authorize!'
# /usr/local/rvm/gems/ruby-2.3.1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:49:in `authorize_resource'
# /usr/local/rvm/gems/ruby-2.3.1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:34:in `load_and_authorize_resource'
# /usr/local/rvm/gems/ruby-2.3.1/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:10:in `block in add_before_action'
# /usr/local/rvm/gems/ruby-2.3.1/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/template_assertions.rb:61:in `process'
# /usr/local/rvm/gems/ruby-2.3.1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `block in process'
# /usr/local/rvm/gems/ruby-2.3.1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `catch'
# /usr/local/rvm/gems/ruby-2.3.1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `_catch_warden'
# /usr/local/rvm/gems/ruby-2.3.1/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `process'
# /usr/local/rvm/gems/ruby-2.3.1/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/integration.rb:12:in `block (2 levels) in <module:Integration>'
# ./spec/controllers/test_cases_controller_spec.rb:182:in `block (3 levels) in <top (required)>'
# ./spec/controllers/test_cases_controller_spec.rb:193:in `block (4 levels) in <top (required)>'
Here is the corresponding action:
describe "DELETE #destroy" do
let!(:test_case) { create(:test_case) }
subject { delete :destroy, params: { id: test_case } }
context "when not logged-in" do
before { subject }
it "redirects to sign-in page" do
expect(response).to redirect_to(new_user_session_url)
end
end
end
This is my controller:
class TestCasesController < ApplicationController
include ApplicationHelper
load_and_authorize_resource
before_action :authenticate_user!
before_action :find_test_case, only: [:show, :edit, :update, :destroy, :test]
before_action :find_question, only: [:index, :new, :create, :test_all]
def index
#test_cases = TestCase.where(question: #question)
end
def new
#test_case = TestCase.new
end
def create
#test_case = #question.test_cases.build(test_case_params)
if #test_case.save
flash[:success] = "Caso de teste criado!"
redirect_to #test_case
else
render 'new'
end
end
def show
end
def edit
end
def update
if #test_case.update_attributes(test_case_params)
flash[:success] = "Caso de teste atualizado!"
redirect_to #test_case
else
render 'edit'
end
end
def destroy
question = #test_case.question
#test_case.destroy
flash[:success] = "Caso de teste deletado!"
redirect_to question_test_cases_url(question)
end
def test
result = #test_case.test(plain_current_datetime, "pas", params[:source_code])
#output = result[:output]
#results = [ { title: #test_case.title, status: result[:status] } ]
respond_to { |format| format.js }
end
def test_all
#results = #question.test_all(plain_current_datetime, "pas", params[:source_code])
respond_to { |format| format.js }
end
private
def test_case_params
params.require(:test_case).permit(:title, :description, :input, :output, :question_id)
end
def find_test_case
#test_case = TestCase.find(params[:id])
end
def find_question
#question = Question.find(params[:question_id])
end
end
This is my ability class:
class Ability
include CanCan::Ability
def initialize(user)
if user.teacher?
can :manage, [Exercise, Question, TestCase]
can :manage, Team, owner: user
can [:read, :create], Team
can [:enroll], Team do |team|
!team.enrolled?(user)
end
can [:unenroll], Team do |team|
team.enrolled?(user)
end
end
end
end
This is my rails_helper (from rspec):
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
require 'support/helpers/relationships'
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
# Checks for pending migration and applies them before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.
#
# You can disable this behaviour by removing the line below, and instead
# explicitly tag your specs with their type, e.g.:
#
# RSpec.describe UsersController, :type => :controller do
# # ...
# end
#
# The different available types are documented in the features, such as in
# https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
# Helpers
config.include Helpers::Relationships, type: :model
config.include Devise::Test::ControllerHelpers, :type => :controller
config.include Warden::Test::Helpers
end
Any tips of how to fix that?
OBS: I'm using Devise for authentication, it provides me the required current_user to cancancan work.
The primary reason you're getting a nil:NilClass error is because current_user is nil unless you are signed in via Devise. Your ability needs to handle for when a user is not logged in, something like this:
def initialize(user)
return unless user.present?
if user.teacher?
...
end
end
If you return nil from your ability, the authorization fails and is handled accordingly.

undefined local variable or method `flash' for #<Devise::OmniauthCallbacksController:0x007fb5d1741e48>

I am building a Rails-API using Omniauth-facebook and Devise-token-auth with Angular and ng-token-auth for the frontend.
However when logging in with facebook I am presented with the error:
undefined local variable or method `flash' for #<Devise::OmniauthCallbacksController:0x007fd027a51e10>
It seems omniauth automatically uses flash middleware however the rails-api doesn't include this and I have been unsuccessfully disabling the use of flash with omniauth.
My configuration is as below:
application.rb:
require File.expand_path('../boot', __FILE__)
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module PathfinderApi
class Application < Rails::Application
config.active_record.raise_in_transactional_callbacks = true
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
config.api_only = true
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
end
end
devise_token_auth.rb:
DeviseTokenAuth.setup do |config|
Rails.application.secrets.facebook_app_secret
config.change_headers_on_each_request = true
end
devise.rb:
Devise.setup do |config|
config.navigational_formats = [:json]
end
omniauth.rb:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['APP_KEY'], ENV['APP_SECRET']
end
I have not managed to disable the flash error with:
config.navigational_formats = [:json]
and devise/omniauth is still using flash middleware and throws the error, any help appreciated!
Had the same problem. Searched the devise source code for 'flash'. Found about 17 matches, all using set_flash_message! (with exclamation mark), except for the failure method in the OmniauthCallbacksController, which uses set_flash_message (without exclamation mark). Looking at the definition we see:
\app\controllers\devise\omniauth_callbacks_controller.rb
# Sets flash message if is_flashing_format? equals true
def set_flash_message!(key, kind, options = {})
if is_flashing_format?
set_flash_message(key, kind, options)
end
end
\lib\devise\controllers\helpers.rb
def is_flashing_format?
is_navigational_format?
end
def is_navigational_format?
Devise.navigational_formats.include?(request_format)
end
The actual flash message is generated in the method without exclamation mark (I would have progged it the other way around...). The missing exclamation mark is the reason why setting the navigational_formats as mentioned in other solutions doesn't work here.
Conclusion: they forgot the exlamation mark.
The fix: monkey-patch the failure method from the OmniauthCallbacksController. Do this in an initializer, for example in
\config\initializers\devise.rb
Rails.application.config.to_prepare do # to_prepare ensures that the monkey patching happens before the first request
Devise::OmniauthCallbacksController.class_eval do # reopen the class
def failure # redefine the failure method
set_flash_message! :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message
redirect_to after_omniauth_failure_path_for(resource_name)
end
end
end
Had the same problem in Rails (5.0.0.1) + devise_token_auth (0.1.39).
Besides the override in #Koen's answer, the following addition is also necessary in my case:
# in config/application.rb
config.middleware.use ActionDispatch::Cookies
I managed to solve this by adding this to the devise.rb config:
config.navigational_formats = []
This way devise will never attempt to use flash and never throw a 500 error.
Taken from https://github.com/heartcombo/devise/issues/4275

Functional Test Keeps Failing (Rspec, Devise)

I'm trying to implement an rspec functional test to check that a user is signed in with devise. I've looked through my code again and again and tried different solutions but so far nothing has worked.
I've included what I believe are the relevant files. Let me know if anything is missing. Any recommendations are appreciated.
spec/rails_helper.rb
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
# Add additional requires below this line. Rails is not loaded until this point!
require 'spec_helper'
require 'rspec/rails'
# note: require 'devise' after require 'rspec/rails'
require 'devise'
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
# Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
# Checks for pending migration and applies them before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.
#
# You can disable this behaviour by removing the line below, and instead
# explicitly tag your specs with their type, e.g.:
#
# RSpec.describe UsersController, :type => :controller do
# # ...
# end
#
# The different available types are documented in the features, such as in
# https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
#Added for Devise
config.include Devise::Test::ControllerHelpers, :type => :controller
end
spec/controllers/users_controller_spec.rb
require 'rails_helper'
describe UsersController, :type => :controller do
before do
#user = User.create!(email: 'example#example.com', password: 'example')
end
# let(:user) { User.create!(email: 'example#example.com', password: 'example') }
describe 'GET #show' do
context "when user is logged in" do
before do
sign_in #user
end
it "loads correct user details" do
get :show, id: #user.id
expect(response).to have_http_status(200)
expect(assigns(:user)).to eq #user
end
end
context "when no user is logged in" do
it "redirects to login" do
get :show, id: #user.id
expect(response).to redirect_to(root_path)
end
end
end
end
And my feedback from the terminal after running bundle exec rpsec
Failures:
1) UsersController GET #show when user is logged in loads correct user details
Failure/Error: elsif user?
NoMethodError:
undefined method `user?' for #<Ability:0x007fa1d784cb98>
# ./app/models/ability.rb:9:in `initialize'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `new'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:361:in `current_ability'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/cancancan-1.15.0/lib/cancan/controller_additions.rb:342:in `authorize!'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:49:in `authorize_resource'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:34:in `load_and_authorize_resource'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/cancancan-1.15.0/lib/cancan/controller_resource.rb:10:in `block in add_before_action'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/template_assertions.rb:61:in `process'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `block in process'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `catch'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:100:in `_catch_warden'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/devise-4.2.0/lib/devise/test/controller_helpers.rb:33:in `process'
# /Users/Admin/.rvm/gems/ruby-2.3.0/gems/rails-controller-testing-1.0.1/lib/rails/controller/testing/integration.rb:12:in `block (2 levels) in <module:Integration>'
# ./spec/controllers/users_controller_spec.rb:19:in `block (4 levels) in <top (required)>'
2) UsersController GET #show when no user is logged in redirects to login
Failure/Error: expect(response).to redirect_to(root_path)
Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/users/sign_in>.
Expected "http://test.host/" to be === "http://test.host/users/sign_in".
# ./spec/controllers/users_controller_spec.rb:29:in `block (4 levels) in <top (required)>'
Finished in 0.90214 seconds (files took 11.05 seconds to load)
6 examples, 2 failures
Failed examples:
rspec ./spec/controllers/users_controller_spec.rb:18 # UsersController GET #show when user is logged in loads correct user details
rspec ./spec/controllers/users_controller_spec.rb:27 # UsersController GET #show when no user is logged in redirects to login
A friend actually helped me figure it out. Apparently there's some issue that involves the seperate gem cancancan. I had to go into the models/ability.rb file and change a line in it.
In the original code the line if !user.admin? was just user?
So if you run into this same issue, that's the fix!
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new #guest user (not logged in)
# can :manage, User, id: user.id
if user.admin?
can :manage, :all
elsif !user.admin?
can :manage, User, id: user.id
else
can :read, :all
end
end
end

Capybara::Webkit::InvalidResponseError: Javascript failed to execute

I converted an app from Rails 3.2 to 4.2 that was using the cancan gem. Googling around and checking on their github says it's enought to just replace gem cancan with gem cancancan without changing anything. This doesn't seem to work. My test fails:
Failures:
1) Redactable fields Manual redaction Redacting selected text in body
Failure/Error:
page.execute_script <<-EOS
document.getElementById('notice_#{#name}').focus();
document.getElementById('notice_#{#name}').select();
EOS
Capybara::Webkit::InvalidResponseError:
Javascript failed to execute
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/browser.rb:305:in `check'
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/browser.rb:211:in `command'
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/browser.rb:232:in `execute_script'
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-webkit-1.11.1/lib/capybara/webkit/driver.rb:80:in `execute_script'
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/session.rb:524:in `execute_script'
# ./spec/support/page_objects/redactable_field_on_page.rb:15:in `select'
# ./spec/support/page_objects/redactable_field_on_page.rb:22:in `select_and_redact'
# ./spec/integration/redaction_spec.rb:37:in `block (4 levels) in <top (required)>'
2) Redactable fields Manual redaction Restoring body from original
Failure/Error: page.find("#notice_#{#name}").click
Capybara::ElementNotFound:
Unable to find css "#notice_body"
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/node/finders.rb:44:in `block in find'
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/node/base.rb:85:in `synchronize'
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/node/finders.rb:33:in `find'
# /Users/siaw23/.rvm/gems/ruby-2.1.9/gems/capybara-2.7.1/lib/capybara/session.rb:699:in `block (2 levels) in <class:Session>'
# ./spec/support/page_objects/redactable_field_on_page.rb:9:in `unredact'
# ./spec/integration/redaction_spec.rb:46:in `block (4 levels) in <top (required)>'
The elements being searched for can be reached manually after loggin in. This means neither cancancan nor cancan successfully applies :admin permission to my user that's created in the test. I used You are not authorized to access this page. and I get "You are not authorized to access this page."
The spec itself looks like this:
require 'rails_helper'
require 'support/notice_actions'
#lots of irrelevant code
private
def visit_redact_notice
user = create(:user, :admin)
visit '/users/sign_in'
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_on "Log in"
notice = create(:dmca, :redactable)
visit "/admin/notice/#{notice.id}/redact_notice"
notice
end
end
end
end
The visit_redact_notice method in the above spec is where everything is happening. I need help :). This is my repo if it might help: https://github.com/siaw23/lumendatabase
ability.rb
class Ability
include CanCan::Ability
def initialize(user)
return unless user
if user.has_role?(Role.submitter)
can :submit, Notice
end
if user.has_role?(Role.redactor)
grant_admin_access
grant_redact
end
if user.has_role?(Role.publisher)
grant_admin_access
grant_redact
can :publish, Notice
end
if user.has_role?(Role.admin)
grant_admin_access
grant_redact
can :edit, :all
cannot :edit, [User, Role]
can :publish, Notice
can :rescind, Notice
can :pdf_requests, :all
end
if user.has_role?(Role.super_admin)
can :manage, :all
end
if user.has_role?(Role.researcher)
can :read, Notice
end
end
def grant_admin_access
can :read, :all
can :access, :rails_admin
can :dashboard
can :search, Entity
can :access, :original_files
end
def grant_redact
can :edit, Notice
can :redact_notice, Notice
can :redact_queue, Notice
end
end
A couple issues you might want to check out...
There's a new version of Devise out that allows authentication via feature / integration tests. I've always spent hours debugging actually getting step-by-step login functionality to work. With Devise 4.2, logging in via integration tests is now supported. You'll have to make some changes to the RSpec configuration for Devise, as noted in the documentation above for the sign_in method to work.
If at this point logging in as an admin still does not work, I would check to see if your RSpec configuration has use_transactional_fixtures set to true. If it does, I would strongly encourage you to let the database_cleaner gem manage your test database, and set use_transactional_fixtures to false.
One or both of those should get you around your authentication issue. My guess is that it's most likely an issue with the transactional fixtures, as Rails is likely cleaning up a transaction before you're fully authenticated (thus why I'd suspect #1 above won't work).

Rolling a token auth mechanisim on top of devise [Rails 4]

Aloha,
After discovering Devise' token_authenticatable has been depreciated, I'm now attempting to roll my own solution, however I think I'm having an issue with devise' sign_in method:
spec:
context "with an admin user" do
before(:each) { #user = FactoryGirl.create(:user, account_type: 'admin') }
it "should respond with a 200 status" do
post :verify, "token"=> #user.authentication_token
response.status.should eq(200)
end
end
error:
1) UsersController#verify with an admin user should respond with a 200 status
Failure/Error: post :verify, "token"=> #user.authentication_token
NoMethodError:
undefined method `user' for nil:NilClass
# ./app/controllers/application_controller.rb:24:in `authenticate_user_from_token!'
# ./spec/controllers/users_controller_spec.rb:39:in `block (4 levels) in <top (required)>'
application_controller.rb:
class ApplicationController < ActionController::Base
# If there's a token present we're using the api authentication
# mechanism, else we fall back to devise auth
before_filter :authenticate_user_from_token!, :authenticate_user!
# Setup an AccessDenied error
class AccessDenied < StandardError; end
# setup a handler
rescue_from AccessDenied, :with => :access_denied
private
# API requests should be made to the resource path
# with the requesters token as params.
#
# This method extracts the params, checks if they are
# valid and then signs the user in using devise' sign_in method
def authenticate_user_from_token!
user = User.find_by_authentication_token params[:token]
if !user.nil? && user.admin?
# store: false ensures we'll need a token for every api request
sign_in user, store: false # this is the line the spec complains about
else
raise ApplicationController::AccessDenied
end
end
def access_denied
render :file => "public/401", :status => :unauthorized
end
end
users_controller.rb
class UsersController < ApplicationController
[snip]
# We use this 'verify' method to provide an endpoint
# for clients to poll for token verification
# If the before filter rejects the user/token
# they recieve a 401, else we respond with a 200
# and the user params for verification on the remote app
def verify
user = User.find_by_authentication_token params[:token]
render json: user
end
end
I don't know where the 'user' method the error mentions is being called, nor what the object it's being called on is.
I've found Authy's devise module very easy to use/modify for token based authentication, rather than rolling my own from scratch.

Resources