Skip to content

Instantly share code, notes, and snippets.

@xlozinguez
Created April 11, 2013 16:34
Show Gist options
  • Save xlozinguez/5364950 to your computer and use it in GitHub Desktop.
Save xlozinguez/5364950 to your computer and use it in GitHub Desktop.
This is the code to hook up an API controller within rails and handle authentication using devise/warden It also includes how to handle the admin role. NOTE: If the user is admin, when the user tries to access a user without the correct id, the system respond with an error. If the user is not an admin, when the user tries to access a user withou…
class Api::ApiController < ActionController::API
before_filter :user_authenticated?
private
def user_authenticated?
unless user_signed_in?
return render :status => 401, :json => {:success => false, :errors => ["Y U NO authenticated?"]}
end
end
def user_admin?
unless current_user.admin?
return render :status => 401, :json => {:success => false, :errors => ["Y U NO admin?"]}
end
end
def find_user
if current_user.admin?
if (params[:user_id] || params[:id].present?) && User.find_by_id(params[:user_id] || params[:id]).present?
@user = User.find_by_id(params[:user_id] || params[:id])
else
return render status: 422, json: {success: false, errors: "no user found, id is missing or non-existent"}
end
else
@user = ((params[:user_id] || params[:id].present?) && User.find_by_id(params[:user_id] || params[:id]).present?) ? User.find_by_id(params[:user_id] || params[:id]) : current_user
end
end
end
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "Joe_#{n}" }
sequence(:email) { |n| "joe#{n}@example.com" }
password 'password'
password_confirmation 'password'
factory :admin do
admin true
end
end
end
class Api::UsersController < Api::ApiController
before_filter :user_admin?, only: :index
before_filter :find_user, only: [:show, :update]
def index
render json: User.all, each_serializer: UserSerializer
end
def show
render json: @user, serializer: UserSerializer, root: :user
end
def update
if @user.update_attributes(params[:user])
return render status: 200, json: @user, serializer: UserSerializer, root: :user
else
return render status: 422, json: {success: false, errors: @user.errors.full_messages.map{|error|{error: error}}}
end
end
end
class UserSerializer < ActiveModel::Serializer
attributes :id,
:email,
:name,
:created_at,
:updated_at
end
require 'spec_helper'
describe Api::UsersController do
describe "GET index /api/users" do
context 'if the user is not authenticated' do
it 'should deny access' do
get 'index'
response.should_not be_success
response.status.should == 401
end
end
context 'if the user is not authenticated as an admin' do
before do
@user = FactoryGirl.create(:user)
sign_in @user
end
it 'should deny access' do
get 'index'
response.should_not be_success
response.status.should == 401
end
end
context 'if the user is an authenticated admin' do
before do
@admin = FactoryGirl.create(:admin)
sign_in @admin
end
it 'should deny access' do
get 'index'
response.should be_success
JSON.parse(response.body)["users"].should have(1).item
end
end
end
describe "GET show /api/users/:id" do
context 'if the user is not authenticated' do
it 'should deny access' do
get :show, id: ''
response.should_not be_success
response.status.should == 401
end
end
context 'if the user is not authenticated as an admin' do
before do
@user = FactoryGirl.create(:user)
sign_in @user
end
it 'should output the current user regardless of the id passed' do
get :show, id: ''
response.should be_success
JSON.parse(response.body)["user"]["id"].should eql(@user.id)
end
end
context 'if the user is authenticated as an admin' do
before do
@admin = FactoryGirl.create(:admin)
sign_in @admin
@a_user = FactoryGirl.create(:user)
end
it 'should output the id of the corresponding user' do
get :show, id: @a_user.id
response.should be_success
JSON.parse(response.body)["user"]["id"].should eql(@a_user.id)
end
it 'should output an error if the id does not match any user' do
get :show, id: '0'
response.should_not be_success
response.status.should == 422
end
it 'should output an error if the id is not specified' do
get :show, id: ''
response.should_not be_success
response.status.should == 422
end
end
end
describe "PUT update /api/users/:id" do
context 'if the user is not authenticated' do
it 'should deny access' do
put :update, {id: '', name: 'Joe Shmo'}
response.should_not be_success
response.status.should == 401
end
end
context 'if the user is not authenticated as an admin' do
before do
@user = FactoryGirl.create(:user)
sign_in @user
end
it 'should output the current user regardless of the id passed' do
put :update, {id: '', name: 'Joe Shmo'}
response.should be_success
response.status.should == 200
end
end
context 'if the user is authenticated as an admin' do
before do
@admin = FactoryGirl.create(:admin)
sign_in @admin
@a_user = FactoryGirl.create(:user)
end
it 'should output the id of the corresponding user' do
put :update, {id: @a_user.id, name: 'Joe Shmo'}
response.should be_success
response.status.should == 200
end
it 'should output an error if the id does not match any user' do
put :update, {id: '0', name: 'Joe Shmo'}
response.should_not be_success
response.status.should == 422
end
it 'should output an error if the id is not specified' do
put :update, {id: '', name: 'Joe Shmo'}
response.should_not be_success
response.status.should == 422
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment