Last active
December 16, 2015 01:08
-
-
Save nguyenlocduy/5352257 to your computer and use it in GitHub Desktop.
How to integrate SHIFT API (https://shift.com) to your Rails App. You should read SHIFT API Docs to understand the flow before implementing this.
This file contains hidden or 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
# config/omniauth.rb | |
# this is OPTIONAL if you want user to login not through SHIFT Website | |
# Register our provider with the OmniAuth Gem | |
module OmniAuth | |
module Strategies | |
# tell OmniAuth to load our strategy | |
autoload :Shift, 'shift_strategy' | |
end | |
end | |
Rails.application.config.middleware.use OmniAuth::Builder do | |
provider :facebook, ENV['FB_APP'], ENV['FB_SECRET'], {:scope => 'publish_actions, email, user_interests, user_groups, user_likes, publish_stream, offline_access, user_birthday, create_event, manage_pages'} | |
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'] | |
provider :shift, ENV['SHIFT_APP_ID'], ENV['SHIFT_APP_SECRET'], {} | |
end |
This file contains hidden or 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
#----------------------------------------------------------------------# | |
# function: app_install | |
# summary: when user authenticate through shift website, this is where | |
# the redirect_uri settings from shift pointed to | |
# author: Duy | |
#----------------------------------------------------------------------# | |
def app_install | |
# uri | |
uri = URI.parse("https://shift.com") | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
# prepare data | |
data = {'code' => params["code"], | |
'client_id' => ENV['SHIFT_APP_ID'], | |
'client_secret' => ENV['SHIFT_APP_SECRET'], | |
'grant_type' => 'authorization_code', | |
'redirect_uri' => ENV['SHIFT_REDIRECT_URL'] | |
} | |
# grab the path if available | |
path = params['path'] || '/' | |
# post request | |
request = Net::HTTP::Post.new("/v1/oauth2/token") | |
request.add_field('Content-Type', 'application/json') | |
request.set_form_data(data) | |
response = http.request(request) | |
# get the token from the response | |
result = JSON(response.body) | |
@access_token = result["access_token"] | |
@refresh_token = response["refresh_token"] | |
# obtain user information and put into a hash | |
user_uri = URI.parse("https://shift.com/v1/users/me") | |
user_request = Net::HTTP::Get.new(user_uri.request_uri) | |
user_request.add_field('Authorization', "Bearer #{@access_token}") | |
user_response = http.request(user_request) | |
user_data = JSON(user_response.body) | |
#send_test_message(@access_token) | |
shift_check_and_login(user_data, @access_token, path) | |
end | |
#----------------------------------------------------------------------# | |
# function: shift_check_and_login | |
# summary: prepares data hash for user to sign in | |
# author: Duy | |
#----------------------------------------------------------------------# | |
def shift_check_and_login(user_hash, access_token, path = '/') | |
auth_hash = {} | |
data_hash = user_hash["data"][0] | |
uid = data_hash["id"] | |
user = User.where("providers.provider" => 'shift', "providers.uid" => uid).first | |
# provider hash | |
provider = {"provider" => "shift", "uid" => uid} | |
# info hash | |
info = { | |
"info" => { | |
'username' => data_hash['username'], | |
'first_name' => data_hash['first_name'], | |
'last_name' => data_hash['last_name'], | |
'email' => data_hash['primary_email']['address'], | |
'image' => data_hash['images'][0]['sizes']['default'] | |
} | |
} | |
# credentials hash | |
credentials = { | |
"credentials" => { | |
"token" => access_token | |
} | |
} | |
# extra info | |
extra = { | |
"extra" => { | |
"title" => data_hash['title'], | |
"company" => data_hash['company'] | |
} | |
} | |
# prepare data | |
auth_hash = auth_hash.merge(provider) | |
auth_hash = auth_hash.merge(info) | |
auth_hash = auth_hash.merge(credentials) | |
auth_hash = auth_hash.merge(extra) | |
# authenticate user and redirect to the right path | |
# this function is customized with your authentication system eg. Devise | |
authenticate(auth_hash, path) | |
end |
This file contains hidden or 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
# app/workers/shift_object_creation_worker.rb | |
# To create an SHIFT Object and Post the message to team feed via background job (Resque) | |
require "uri" | |
require "net/https" | |
require "json" | |
class ShiftCampaignCreateApi | |
@queue = :shift_api | |
def self.perform(campaign_id, access_token) | |
campaign = Campaign.find(campaign_id) | |
link = "campaigns/#{ campaign.slug }" | |
# uri | |
uri = URI.parse("https://shift.com") | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
# create a test object | |
obj_hash = '{ | |
"url" : "'+link+'", | |
"type" : "Campaign", | |
"team" : "'+ENV['SHIFT_TEAM_ID']+'", | |
"name" : "'+campaign.title+'" | |
}' | |
obj_uri = URI.parse("https://shift.com/v1/applications/#{ENV['SHIFT_APP_ID']}/objects") | |
obj_request = Net::HTTP::Post.new(obj_uri.request_uri) | |
obj_request.add_field("Content-Type", "application/json") | |
obj_request.add_field("Authorization", "Bearer #{access_token}") | |
obj_request.body = obj_hash | |
obj_response = http.request(obj_request) | |
obj_result = JSON(obj_response.body) | |
obj_id = obj_result["data"][0]["id"] | |
# Send a test message | |
message_data = '{ | |
"addressed_users": [],' | |
message_data += ' | |
"text": "Create a new Campaign {0}",' | |
message_data += ' | |
"addressed_teams": [ | |
"'+ENV['SHIFT_TEAM_ID']+'" | |
],' | |
message_data += ' | |
"mentions": [{"type": "appobject", "id": "'+obj_id+'", "name": "'+campaign.title+'"}] | |
}' | |
msg_uri = URI.parse("https://shift.com/v1/messages") | |
msg_request = Net::HTTP::Post.new(msg_uri.request_uri) | |
msg_request.add_field('Content-Type', 'application/json') | |
msg_request.add_field('Authorization', "Bearer #{access_token}") | |
msg_request.body = message_data | |
msg_response = http.request(msg_request) | |
end | |
end |
This file contains hidden or 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
# lib/shift_strategy.rb | |
# this is OPTIONAL if you want user to login not through SHIFT Website | |
# creates a omniauth strategry (provider) for OmniAuth | |
require 'omniauth/strategies/oauth2' | |
require 'base64' | |
require 'openssl' | |
require 'rack/utils' | |
module OmniAuth | |
module Strategies | |
class Shift < OmniAuth::Strategies::OAuth2 | |
class NoAuthorizationCodeError < StandardError; end | |
option :client_options, { | |
:site => 'https://shift.com', | |
:authorize_url => "https://shift.com/v1/oauth2/auth", | |
:token_url => '/v1/oauth2/token' | |
} | |
uid { raw_info['data'][0]['id'] } | |
info do | |
prune!({ | |
'username' => raw_info['data'][0]['username'], | |
'first_name' => raw_info['data'][0]['first_name'], | |
'last_name' => raw_info['data'][0]['last_name'], | |
'email' => raw_info['data'][0]['primary_email']['address'], | |
'image' => raw_info['data'][0]['images'][0]['sizes']['default'] | |
}) | |
end | |
extra do | |
hash = {} | |
hash['raw_info'] = raw_info unless skip_info? | |
prune! hash | |
end | |
def raw_info | |
@raw_info ||= access_token.get('/v1/users/me').parsed || {} | |
end | |
def request_phase | |
if request.params["access_token"] | |
url = callback_url | |
url << "?" unless url.match(/\?/) | |
url << "&" unless url.match(/[\&\?]$/) | |
url << query | |
redirect url | |
else | |
super | |
end | |
end | |
# NOTE if we're using code from the signed request | |
# then FB sets the redirect_uri to '' during the authorize | |
# phase + it must match during the access_token phase: | |
# https://github.com/facebook/php-sdk/blob/master/src/base_facebook.php#L348 | |
def callback_url | |
options[:callback_url] || super | |
end | |
private | |
def prune!(hash) | |
hash.delete_if do |_, value| | |
prune!(value) if value.is_a?(Hash) | |
value.nil? || (value.respond_to?(:empty?) && value.empty?) | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment