Created
April 11, 2013 16:34
-
-
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…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UserSerializer < ActiveModel::Serializer | |
attributes :id, | |
:email, | |
:name, | |
:created_at, | |
:updated_at | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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