Skip to content

Instantly share code, notes, and snippets.

@nathanows
Created March 16, 2015 17:41
Show Gist options
  • Save nathanows/97ea304c97eef41d2f5c to your computer and use it in GitHub Desktop.
Save nathanows/97ea304c97eef41d2f5c to your computer and use it in GitHub Desktop.
RSpec: Testing Token/API Key Authentication (with results scoped to current user)
##
## TOKEN/API KEY AUTHENTICATION
## This was based on blogger-advanced
## Continuing from the class we built this in...
## if not already done, you'll need to make an ApiKey table in the DB 'rails g model ApiKey token:string'
## Add a new column to the ApiKey table to associate a key with an author
## 'rails g migration add-author-to-api-key author:references'
##
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
helper_method :current_author, :current_author_by_api
def current_author
Author.find_by_id(session[:author_id])
end
## THIS IS TO BE ADDED AND MADE A HELPER_METHOD
def current_author_by_api
token = ActionController::HttpAuthentication::Token.token_and_options(request)
author_id = ApiKey.find_by(token: token).author_id
Author.find_by_id(author_id)
end
def require_author
unless current_author
redirect_to login_path, notice: "You must be logged in to go there"
end
end
end
# app/controllers/api/v1/articles_controller.rb
class Api::V1::ArticlesController < ApplicationController
#...
before_action :authenticate
#...
#this is the updated index method that scopes .all to the current author (yeah, this should probably be refactored to be a scope...)
def index
respond_with Article.where(author_id: current_author_by_api.id)
end
#...
private
def authenticate
authenticate_or_request_with_http_token do |token, options|
ApiKey.exists?(token: token)
end
end
end
# spec/support/auth_helper.rb
module AuthHelper
def http_login
token = 'SomeRandomToken'
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token)
end
end
# spec/spec_helper.rb (or rails_helper.rb, whichever, but in the existing RSpec.configure block include the AuthHelper module)
RSpec.configure do |config|
config.include AuthHelper, :type => :controller
end
# Skipping the Factory girl setup steps (find them here http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md)
# Summary: add 'factory_girl_rails' and 'database_cleaner' gems to your Gemfile
# From the link above, add in the code snippets from the 'Configure your test suite' and 'Linting factories' sections
# spec/factories.rb
FactoryGirl.define do
factory :api_key do
token "SomeRandomToken"
author_id 1
end
factory :author do
name "John Doe"
email "[email protected]"
password "password"
end
factory :article do
title "How to play cards"
body "It's pretty simple really..."
author
end
end
# controller spec (spec/controllers/app/v1)
require 'spec_helper'
RSpec.describe Api::V1::ArticlesController, :type => :controller do
describe "GET index" do
it "responds to json" do
author = create(:author)
create(:api_key, author_id: author.id)
create(:article, title: "Tight Pants", author_id: author.id)
create(:article)
http_login
get :index, format: 'json'
items = JSON.parse(response.body)
first_item = items.first
expect(response.status).to eq(200)
expect(items.count).to eq(1)
expect(first_item["title"]).to eq("Tight Pants")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment