From 192ef3494089f272d3e7bf43ffe499f2d0ae9e9f Mon Sep 17 00:00:00 2001 From: junv Date: Sun, 19 Jan 2014 15:46:16 +0800 Subject: [PATCH] Add token based API authentication support. --- app/controllers/api/v1/sessions_controller.rb | 2 +- app/controllers/api_controller.rb | 3 ++ app/controllers/application_controller.rb | 34 +++++++++++++----- app/models/auth_key.rb | 6 +++- app/models/user.rb | 23 ++++++------ config/routes.rb | 1 - libr_development | Bin 53248 -> 53248 bytes libr_test | Bin 53248 -> 17408 bytes spec/models/auth_key_spec.rb | 7 +++- spec/models/user_spec.rb | 12 +++++-- 10 files changed, 62 insertions(+), 26 deletions(-) diff --git a/app/controllers/api/v1/sessions_controller.rb b/app/controllers/api/v1/sessions_controller.rb index 93b804f..d97ab00 100644 --- a/app/controllers/api/v1/sessions_controller.rb +++ b/app/controllers/api/v1/sessions_controller.rb @@ -2,7 +2,7 @@ class Api::V1::SessionsController < Devise::SessionsController def create warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure") - render :json => {:success => true} + render :json => {:success => true, token: current_user.auth_keys.last.value} end diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index c21ee93..2562078 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -1,5 +1,8 @@ class ApiController < ApplicationController + before_filter :authenticate_user_from_token!, only: :books + #before_filter :authenticate_user! + def book_info book = Book.find_by_isbn params[:isbn] diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d8b208a..4ff4dfb 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,20 +3,23 @@ class ApplicationController < ActionController::Base before_filter :current_user! + #before_filter :authenticate_user_from_token! + + def current_user! @current_user = nil @current_user = current_user if user_signed_in? end - def sign_in(name, avatar) - if session[:name] == name - return - end - unless User.find_by_name name - User.create_user(name, avatar) - end - session[:name] = name - end + #def sign_in(name, avatar) + # if session[:name] == name + # return + # end + # unless User.find_by_name name + # User.create_user(name, avatar) + # end + # session[:name] = name + #end def same_user(controller) user = User.find_by_id params[:id] @@ -25,4 +28,17 @@ class ApplicationController < ActionController::Base end end + def authenticate_user_from_token! + user_email = params[:user_email].presence + user = user_email && User.find_by_email(user_email) + token = AuthKey.find_by_value params[:user_token] + + if user && user.auth_keys.include?(token) + sign_in user, store: false + else + render :json => {:success => false, msg: "Authentication failed"} + end + end + + end diff --git a/app/models/auth_key.rb b/app/models/auth_key.rb index 862e978..d0a6469 100644 --- a/app/models/auth_key.rb +++ b/app/models/auth_key.rb @@ -8,7 +8,11 @@ class AuthKey < ActiveRecord::Base belongs_to :user def self.create_key_for(user) - AuthKey.create value: Utils.random_key, user_id: user.id + token = Devise.friendly_token + if user.auth_keys.include? token + token = Devise.friendly_token + end + AuthKey.create value: token, user_id: user.id end def active diff --git a/app/models/user.rb b/app/models/user.rb index d4e19cc..9544915 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,26 +1,27 @@ require 'utils' class User < ActiveRecord::Base - # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable + after_save :ensure_authentication_token + include Utils attr_accessible :email, :name, :avatar, :id, :location, :preferred_name, :encrypted_password, :password, :password_confirmation, :remember_me - - has_many :book_instances - has_many :borrow_records - has_many :borrowed_books, :source => :book_instance, through: :borrow_records - has_many :auth_keys + def ensure_authentication_token + if auth_keys.empty? + generate_auth_key + end + end + def self.create_user(name, avatar) User.create name: name, avatar: avatar @@ -66,7 +67,7 @@ class User < ActiveRecord::Base end def generate_auth_key - auth_keys.create value: Utils.random_key, user_id: id + AuthKey.create_key_for self end def create_book_instance(isbn, is_public = 'true') @@ -79,14 +80,14 @@ class User < ActiveRecord::Base if is_public == 'false' instance.be_private end - end def open_books - book_instances.where(public:true) + book_instances.where(public: true) end def private_books - book_instances.where(public:false) + book_instances.where(public: false) end + end diff --git a/config/routes.rb b/config/routes.rb index 5773ce7..a8c3229 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,7 +48,6 @@ Libr::Application.routes.draw do namespace :api do namespace :v1 do - devise_for :users devise_scope :user do resources :sessions, :only => [:create, :destroy, :failure] end diff --git a/libr_development b/libr_development index d2b1a791083de040a40cac25ba442043f8938fda..0089cb4126cc4635cd49b5f989ff767bee40f9b2 100644 GIT binary patch delta 258 zcmZozz}&Ead4e>f)kGO*Myrhp3+?&&Uof!n?_%Kp#=ndIB>$Dof)10fuV`6 zfuXJ;ioCg*u@Rb#k(H5!p1Gxkk-7QickyBd98COi4E$U9paWHT)m^wO& zS2-4kxkWk}7lnG4Wmgr1hL;<;p_*lA0(6L;p@pS^i5YI0w8Wg^)XiJxdm8`%tO7z< delta 159 zcmZozz}&Ead4e>f!9*EnMuUwB3+?$C7#LXiPcra-~X<84fZjSLJ;bPWu34N>HcP0UO% kWsLNUjZI99EjGW47c*dE&VogJ2XBy+CSyi2qlO_ zgX;<*%KV8Mx2gD+EFXa)7p=mdOXZn2th*Nd3o4{UQivoC z(;E}Q}j`#CB(!Jqs;$-MS|GcCeP@AAOS&LfFG!icdOUdS);3=;-)fC_Z=Yo#{ zRpjtpVCz@(ZwaM|Qi4*RF~mJ~DFxHhc8k=`clEWe)UFkiS%F7f;RFZR!3GvFfnKzt z4pk_DlF#y5W<9el)7eadVlpFeiDT?x3#*vL2)fXWILhJ3oV=0eGJ{9YY{+yb+eDGi zFO{@~wB;Cp8PDX1Uvwpfxy-KTKAoU^pDK7x7xS5p@x2wN0xs9hJYXd#!YQl$1A7B{ Az5oCK delta 600 zcmZqZU~E{xtPmXNlUb6gkd|MRn^>Y?%pkzP$jIQJpuoVuAOpm_6BV449;xyInLMmX z4E&sY+j--73b}i@dN>cTN3(rli)VeqnzUJv+Md?zzT?#cR2DwBJhL?+*JQk~51q|V3%6tSN?TUU~ibMsbRZ>Gs6@|uhsljGzU zO*WC!W@Mk7Aa`|gfUE=~+vH5yGm}Nc-)!C`8p$|0Lo{e|p~!bOkdqh$z!q;-V0pld zASO=8p2We*IOOF_@c03roCT{Y-#G^Ucl>wwPx0^IU&cR$zlpzqKaSsr--=&@UyPrH z?-SnxzH?|{w{gN(rp@Q9%o$br_A&6^=0Cx|m46X`KYtB>CVv>eGrs}9EI$|DcfKcl T7y0(_zr)b|lxg!mJ10f}q!GL- diff --git a/spec/models/auth_key_spec.rb b/spec/models/auth_key_spec.rb index 9fe6cec..39b179e 100644 --- a/spec/models/auth_key_spec.rb +++ b/spec/models/auth_key_spec.rb @@ -1,5 +1,10 @@ require 'spec_helper' describe AuthKey do - pending "add some examples to (or delete) #{__FILE__}" + + it 'should create a auth token a target user' do + @user = User.create name: 'Mary', email: 'mary@qq.com', password: 'passworD1' + token = AuthKey.create_key_for @user + token.should_not be nil + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9242333..f76960c 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -63,11 +63,11 @@ describe :User do describe :generate_auth_key do it 'ensure generate a auth key for a user' do - @user.auth_keys.count.should == 0 + @user.auth_keys.count.should == 1 lambda do @user.generate_auth_key end.should change(@user.auth_keys, :count).by(1) - @user.auth_keys[0].value.size.should == 8 + @user.auth_keys[0].value.size.should == 20 end end @@ -77,4 +77,12 @@ describe :User do # how to test with network ,mock end end + + describe :generate_authentication_token do + it 'should generate a not nil token when create a user' do + @user.auth_keys.empty?.should == false + @user.auth_keys.size.should == 1 + end + + end end \ No newline at end of file