diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 08b06a09..047f5a8e 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -1,11 +1,9 @@ -module API - class BaseController < ActionController::Base - skip_before_action :verify_authenticity_token +class Api::BaseController < ActionController::Base + skip_before_action :verify_authenticity_token - private + private - def unauthorized(reason) - render json: {error: reason} - end + def unauthorized(reason) + render status: :unauthorized, json: { error: reason } end end diff --git a/app/controllers/api/session_controller.rb b/app/controllers/api/session_controller.rb deleted file mode 100644 index faac3fd8..00000000 --- a/app/controllers/api/session_controller.rb +++ /dev/null @@ -1,26 +0,0 @@ -module API - class SessionController < API::BaseController - def github_create - begin - client = Octokit::Client.new(:access_token => params[:access_token]) - github_uid = client.user.try(:[], 'id') - user = User.where(provider: 'github', uid: github_uid).first() - - if user.nil? - # TODO: create a new user - raise StandardError('TODO: create a new user') - end - - tomato_auth = Authorization.where(provider: 'tomatoes', uid: user.uid).first() - if tomato_auth.nil? - tomato_auth = Authorization.new(provider: 'tomatoes', uid: user.uid) - end - tomato_auth.api_authorize - tomato_auth.save! - rescue => err - Rails.logger.error("Cannot log user in using Github: #{err}") - unauthorized('authentication failed') - end - end - end -end diff --git a/app/controllers/api/sessions_controller.rb b/app/controllers/api/sessions_controller.rb new file mode 100644 index 00000000..d7f6292f --- /dev/null +++ b/app/controllers/api/sessions_controller.rb @@ -0,0 +1,23 @@ +class Api::SessionsController < Api::BaseController + def create + begin + client = Octokit::Client.new(access_token: params[:access_token]) + github_uid = client.user.try(:[], 'id') + user = User.find_by_auth_provider(provider: 'github', uid: github_uid) + + if user.nil? + # TODO: create a new user + raise StandardError('TODO: create a new user') + end + + tomatoes_auth = user.authorizations.where(provider: 'tomatoes').first_or_initialize + tomatoes_auth.refresh_token unless tomatoes_auth.token + tomatoes_auth.save! + + render json: { token: tomatoes_auth.token } + rescue => err + Rails.logger.error("Cannot log user in using GitHub: #{err}") + unauthorized('authentication failed') + end + end +end diff --git a/app/models/authorization.rb b/app/models/authorization.rb index 3f2e5d7b..39ed4d44 100644 --- a/app/models/authorization.rb +++ b/app/models/authorization.rb @@ -43,9 +43,7 @@ def url "http://#{provider}.com/#{nickname}" end - def api_authorize - new_token = SecureRandom.hex - self.token = new_token - return new_token + def refresh_token + self.token = SecureRandom.hex end end diff --git a/app/models/user.rb b/app/models/user.rb index afdb2152..d34fec0f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -53,12 +53,17 @@ class User index('authorizations.provider' => 1) def self.find_by_omniauth(auth) + find_by_auth_provider(provider: auth['provider'].to_s, uid: auth['uid'].to_s) + end + + def self.find_by_auth_provider(provider:, uid:) any_of( - { authorizations: { - '$elemMatch' => { - provider: auth['provider'].to_s, - uid: auth['uid'].to_s } } }, - provider: auth['provider'], uid: auth['uid'] + { + authorizations: { + '$elemMatch' => { provider: provider, uid: uid } + } + }, + provider: provider, uid: uid ).first end diff --git a/config/routes.rb b/config/routes.rb index 5a0e1388..c5c8daec 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,6 +2,10 @@ # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". + namespace :api do + resource :session, only: [:create] + end + resources :tags, only: [:index, :show] resources :projects diff --git a/test/functional/api/sessions_controller_test.rb b/test/functional/api/sessions_controller_test.rb new file mode 100644 index 00000000..4def1ed9 --- /dev/null +++ b/test/functional/api/sessions_controller_test.rb @@ -0,0 +1,58 @@ +require 'test_helper' + +class Api::SessionsControllerTest < ActionController::TestCase + setup do + @github_user = User.create!( + name: 'name', + email: 'email@example.com' + ) + @github_user.authorizations.create!( + provider: 'github', + uid: 'github_user_id' + ) + + @github_user_with_api_auth = User.create!( + name: 'name', + email: 'email@example.com' + ) + @github_user_with_api_auth.authorizations.create!( + provider: 'github', + uid: 'github_user_with_api_auth_id' + ) + @github_user_with_api_auth.authorizations.create!( + provider: 'tomatoes', + token: 'tomatoes_token' + ) + end + + teardown do + @github_user.destroy + @github_user_with_api_auth.destroy + end + + test 'given a github access token it should create a new session' do + github_client = Octokit::Client.new + github_client.expects(:user).returns('id' => 'github_user_id') + Octokit::Client.expects(:new).with(access_token: 'github_access_token').returns(github_client) + + assert_difference('@github_user.reload.authorizations.count') do + post :create, provider: 'github', access_token: 'github_access_token' + end + assert_response :success + assert_equal 'application/json', @response.content_type + assert JSON.parse(@response.body).has_key?('token') + end + + test 'given a github access token it should return an existing session' do + github_client = Octokit::Client.new + github_client.expects(:user).returns('id' => 'github_user_with_api_auth_id') + Octokit::Client.expects(:new).with(access_token: 'github_access_token').returns(github_client) + + assert_no_difference('@github_user_with_api_auth.reload.authorizations.count') do + post :create, provider: 'github', access_token: 'github_access_token' + end + assert_response :success + assert_equal 'application/json', @response.content_type + assert_equal({ token: 'tomatoes_token' }.to_json, @response.body) + end +end